Mejorando sistema de Links entre Objetos. Usando IItemsSource y suscribiendose al evento de cambio de Nombre. De esta forma se mantiene un enlace por string mas simple para serializar

This commit is contained in:
Miguel 2024-06-09 10:39:31 +02:00
parent 0305ae2506
commit c58a264d38
14 changed files with 568 additions and 222 deletions

View File

@ -1,9 +1,7 @@
<Application x:Class="CtrEditor.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CtrEditor"
xmlns:os="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
StartupUri="MainWindow.xaml">
<Application x:Class="CtrEditor.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:CtrEditor"
xmlns:osExtraccion="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
xmlns:os="clr-namespace:CtrEditor.ObjetosSim" StartupUri="MainWindow.xaml">
<Application.Resources>
<local:MeterToPixelConverter x:Key="MeterToPixelConverter" />
@ -19,7 +17,9 @@
<local:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<local:StringToBrushConverter x:Key="StringToBrushConverter" />
<local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<local:SubclassFilterConverter x:Key="SubclassFilterConverter" TargetType="{x:Type os:osBuscarCoincidencias}" />
<local:SubclassFilterConverter x:Key="SubclassFilterConverterosBuscarCoincidencias"
TargetType="{x:Type osExtraccion:osBuscarCoincidencias}" />
<local:SubclassFilterConverter x:Key="SubclassFilterConverterosVMMotor" TargetType="{x:Type os:osVMmotorSim}" />
</Application.Resources>
</Application>

View File

@ -109,8 +109,11 @@ namespace CtrEditor
DatosDeTrabajo.CargarImagenes();
ListaImagenes = new ObservableCollection<string>(DatosDeTrabajo.Imagenes.Keys); // Actualizar claves
SelectedImage = null;
if (ListaImagenes.FirstOrDefault() != null)
if (EstadoPersistente.Instance.imagen != null && EstadoPersistente.Instance.imagen.Length>0)
SelectedImage = EstadoPersistente.Instance.imagen;
else if (ListaImagenes.FirstOrDefault() != null)
SelectedImage = ListaImagenes.FirstOrDefault();
OnPropertyChanged(nameof(directorioTrabajo)); // Notificar el cambio de propiedad
OnPropertyChanged(nameof(ListaImagenes)); // Notificar que la lista de imágenes ha cambiado
}
@ -131,6 +134,8 @@ namespace CtrEditor
// SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]); // Dispara el evento con la nueva ruta de imagen
LoadStateObjetosSimulables();
EstadoPersistente.Instance.imagen = value;
EstadoPersistente.Instance.GuardarEstado();
}
}
@ -331,7 +336,10 @@ namespace CtrEditor
private void EliminarUserControl()
{
if (SelectedItemOsList is osBase objEliminar)
{
RemoverObjetoSimulable(objEliminar);
}
}
private void InitializeTipoSimulableList()
@ -524,6 +532,7 @@ namespace CtrEditor
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
// PreserveReferencesHandling = PreserveReferencesHandling.Objects,
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto
};
@ -547,7 +556,7 @@ namespace CtrEditor
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
// PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
@ -590,7 +599,7 @@ namespace CtrEditor
}
// Recorrer la colección de objetos simulables
foreach (var objetoSimulable in ObjetosSimulables)
CrearUserControlDesdeObjetoSimulable(objetoSimulable);
if (objetoSimulable != null) CrearUserControlDesdeObjetoSimulable(objetoSimulable);
}
}
catch { /* Consider logging the error or handling it appropriately */ }

View File

@ -3,8 +3,10 @@
xmlns:Siemens="clr-namespace:CtrEditor.Siemens" xmlns:local="clr-namespace:CtrEditor"
xmlns:uc="clr-namespace:CtrEditor.ObjetosSim.UserControls"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:ObjetosSim="clr-namespace:CtrEditor.ObjetosSim" x:Class="CtrEditor.MainWindow" Height="900" Width="1600"
WindowState="Maximized" ResizeMode="CanResize" Title="{Binding directorioTrabajo}" Icon="/app2.png">
xmlns:ObjetosSim="clr-namespace:CtrEditor.ObjetosSim"
xmlns:ObjetosExtraccion="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos" x:Class="CtrEditor.MainWindow"
Height="900" Width="1600" WindowState="Maximized" ResizeMode="CanResize" Title="{Binding directorioTrabajo}"
Icon="/app2.png">
<Window.DataContext>
<ctreditor:MainViewModel />
@ -32,7 +34,6 @@
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
@ -178,7 +179,8 @@
ResizeDirection="Rows" VerticalAlignment="Center" />
<!-- PanelEdicion -->
<xctk:PropertyGrid Grid.Row="2" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False">
<xctk:PropertyGrid Grid.Row="2" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False"
ShowDescriptionByTooltip="True">
<xctk:PropertyGrid.EditorDefinitions>
<!-- String -->
@ -230,6 +232,36 @@
</xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition>
<!-- osBuscarCoincidencias -->
<xctk:EditorTemplateDefinition>
<xctk:EditorTemplateDefinition.TargetProperties>
<xctk:TargetPropertyType Type="{x:Type ObjetosExtraccion:osBuscarCoincidencias}" />
</xctk:EditorTemplateDefinition.TargetProperties>
<xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.ObjetosSimulables,
RelativeSource={RelativeSource AncestorType=Window},
Converter={StaticResource SubclassFilterConverterosBuscarCoincidencias}}"
SelectedItem="{Binding Value}" DisplayMemberPath="Nombre" IsEditable="True" />
</DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition>
<!-- osVMmotorSim -->
<xctk:EditorTemplateDefinition>
<xctk:EditorTemplateDefinition.TargetProperties>
<xctk:TargetPropertyType Type="{x:Type ObjetosSim:osVMmotorSim}" />
</xctk:EditorTemplateDefinition.TargetProperties>
<xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.ObjetosSimulables,
RelativeSource={RelativeSource AncestorType=Window},
Converter={StaticResource SubclassFilterConverterosVMMotor}}"
SelectedItem="{Binding Value}" DisplayMemberPath="Nombre" />
</DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition>
<!-- osBase -->
<xctk:EditorTemplateDefinition>
<xctk:EditorTemplateDefinition.TargetProperties>
@ -237,9 +269,8 @@
</xctk:EditorTemplateDefinition.TargetProperties>
<xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.ObjetosSimulables,
RelativeSource={RelativeSource AncestorType=Window},
Converter={StaticResource SubclassFilterConverter}}"
<ComboBox
ItemsSource="{Binding DataContext.ObjetosSimulables, RelativeSource={RelativeSource AncestorType=Window}}"
SelectedItem="{Binding Value}" DisplayMemberPath="Nombre" />
</DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate>

View File

@ -419,6 +419,7 @@ namespace CtrEditor
private void ListaOs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//PanelEdicion.Children.Clear(); // Limpiar el panel existente
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
CargarPropiedadesosDatos(selectedObject);

View File

@ -51,38 +51,11 @@ namespace CtrEditor.ObjetosSim
public override void TopChanging(float oldValue, float newValue) {
UpdateChildsTop(newValue - oldValue);
}
public override void LeftChanging(float oldValue, float newValue) {
public override void LeftChanging(float oldValue, float newValue)
{
UpdateChildsLeft(newValue - oldValue);
}
protected void UpdateChildsTop(float offsetY)
{
if (!string.IsNullOrEmpty(Nombre) && _mainViewModel != null)
{
foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
{
if (objetoSimulable != this && objetoSimulable.Group_Panel == Nombre)
{
objetoSimulable.Top += offsetY;
}
}
}
}
protected void UpdateChildsLeft(float offsetX)
{
if (!string.IsNullOrEmpty(Nombre) && _mainViewModel != null)
{
foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
{
if (objetoSimulable != this && objetoSimulable.Group_Panel == Nombre)
{
objetoSimulable.Left += offsetX;
}
}
}
}
public osTextPlate()
{
Ancho = 0.5f;

View File

@ -7,7 +7,12 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.Siemens;
using CtrEditor.Simulacion;
using System.Windows.Input;
using Newtonsoft.Json;
using System.Collections.Generic;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.ComponentModel;
using System.Xml.Linq;
namespace CtrEditor.ObjetosSim
{
@ -18,15 +23,17 @@ namespace CtrEditor.ObjetosSim
public partial class osTransporteTTop : osBase, IosBase
{
private osBase _osMotor = null;
private simTransporte SimGeometria;
private osVMmotorSim Motor;
public static string NombreClase()
{
return "Transporte";
}
private string nombre = "Transporte TTOP";
[property: Category("Id:")]
public override string Nombre
{
get => nombre;
@ -34,6 +41,7 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulation:")]
public float velocidadActual;
partial void OnVelocidadActualChanged(float value)
@ -42,6 +50,7 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulation:")]
bool invertirDireccion;
partial void OnInvertirDireccionChanged(bool value)
@ -63,28 +72,53 @@ namespace CtrEditor.ObjetosSim
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
[ObservableProperty]
public string motor;
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
partial void OnMotorChanged(string value)
partial void OnId_MotorChanged(string value)
{
_osMotor = ObtenerLink(Motor, typeof(osVMmotorSim));
if (Motor != null)
Motor.PropertyChanged -= OnMotorPropertyChanged;
if (_mainViewModel != null && value != null && value.Length > 0)
{
Motor = (osVMmotorSim)_mainViewModel.ObjetosSimulables.FirstOrDefault(s => (s is osVMmotorSim && s.Nombre == value), null);
if (Motor != null)
Motor.PropertyChanged += OnMotorPropertyChanged;
}
}
private void OnMotorPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(osVMmotorSim.Nombre))
{
Id_Motor = ((osVMmotorSim)sender).Nombre;
}
}
[ObservableProperty]
[property: Category("Layout:")]
public float ancho;
[ObservableProperty]
[property: Category("Layout:")]
public float alto;
[ObservableProperty]
[property: Category("Layout:")]
public float angulo;
[ObservableProperty]
[property: Category("Setup:")]
public float frictionCoefficient;
[ObservableProperty]
[property: Category("Setup:")]
public float velMax50hz;
[ObservableProperty]
[property: Category("Setup:")]
public float tiempoRampa;
[ObservableProperty]
[property: Category("Setup:")]
public bool esMarcha;
@ -117,20 +151,17 @@ namespace CtrEditor.ObjetosSim
public override void UpdatePLC(PLCModel plc, int elapsedMilliseconds)
{
if (_osMotor != null)
{
if (_osMotor is osVMmotorSim motor)
if (Motor != null)
if (Motor is osVMmotorSim motor)
VelocidadActual = motor.Velocidad;
}
else if (Motor.Length > 0)
_osMotor = ObtenerLink(Motor, typeof(osVMmotorSim));
}
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
ActualizarLeftTop();
OnId_MotorChanged(Id_Motor);
if (_visualRepresentation is ucTransporteTTop uc)
{
@ -178,7 +209,8 @@ namespace CtrEditor.ObjetosSim
Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
}
}
public void Rotate(float Angle) {
public void Rotate(float Angle)
{
if (Datos != null)
if (Datos is osTransporteTTop datos)
datos.Angulo = Angle;
@ -190,6 +222,8 @@ namespace CtrEditor.ObjetosSim
}
}
}

View File

@ -15,6 +15,8 @@ using Point = System.Drawing.Point;
using Rectangle = System.Windows.Shapes.Rectangle;
using Size = System.Drawing.Size;
using Ookii.Dialogs.Wpf;
using Rect = System.Windows.Rect;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim.Extraccion_Datos
@ -26,15 +28,15 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
public partial class osBuscarCoincidencias : osBase, IosBase
{
private osBase _osMotor = null;
private simTransporte SimGeometria;
[ObservableProperty]
List<Rect> search_rectangles;
public static string NombreClase()
{
return "Search Templates";
}
private string nombre = NombreClase();
public override string Nombre
{
get => nombre;
@ -51,51 +53,54 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
Search_templates = false;
}
public override void TopChanged(float value)
{
base.TopChanged(value);
Search_templates = false;
}
public override void LeftChanged(float value)
{
base.LeftChanged(value);
Search_templates = false;
}
[ObservableProperty]
bool export_ocr;
[ObservableProperty]
string text_export_ocr;
partial void OnExport_ocrChanged(bool value)
{
if (Export_ocr)
{
Text_export_ocr = "";
if (!string.IsNullOrEmpty(Nombre) && _mainViewModel != null)
{
foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
{
if (objetoSimulable != this && objetoSimulable.Group_Panel == Nombre)
{
if (objetoSimulable is osExtraccionTag osExtraccionTag)
{
osExtraccionTag.CaptureImageAreaAndDoOCR();
Text_export_ocr += osExtraccionTag.Tag_extract;
}
}
}
}
}
Export_ocr = false;
}
public override void TopChanging(float oldValue, float newValue)
{
UpdateChildsTop(newValue - oldValue);
}
public override void LeftChanging(float oldValue, float newValue)
{
UpdateChildsLeft(newValue - oldValue);
}
[ObservableProperty]
[property: Description("Width of the object.")]
[property: Category("Position:")]
public float ancho;
partial void OnAnchoChanged(float value)
{
Search_templates = false;
}
[ObservableProperty]
[property: Description("Height of the object.")]
[property: Category("Position:")]
public float alto;
partial void OnAltoChanged(float value)
{
Search_templates = false;
}
public override void OnTimerAfterMovement()
{
}
[ObservableProperty]
public int n_Repeat_X;
[ObservableProperty]
public int n_Repeat_Y;
[ObservableProperty]
public float offset_Repeat_X;
[ObservableProperty]
public float offset_Repeat_Y;
[ObservableProperty]
public float angulo;
@ -117,12 +122,17 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
[ObservableProperty]
float threshold;
[ObservableProperty]
float coincidencias;
public osBuscarCoincidencias()
{
Ancho = 1;
Alto = 1;
Angulo = 0;
Opacity_oculto = 0.1f;
Threshold = 0.6f;
}
private void ShowPreviewWindow(Stream imageStream)
@ -165,6 +175,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
}
private void BuscarCoincidenciasAsync(ProgressDialog progressDialog)
{
// Reset the Canvas children
@ -241,6 +252,14 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
int ConteoPositivos = 0;
// Lista para mantener áreas ya aceptadas
List<Rectangle> acceptedRectangles = new List<Rectangle>();
if (search_rectangles != null)
search_rectangles.Clear();
else
search_rectangles = new List<Rect>();
// Obtener los puntos que superan el umbral
float[] resultArray = result.GetData(false) as float[];
if (resultArray != null)
@ -251,21 +270,42 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
{
int row = i / result.Cols;
int col = i % result.Cols;
// Crear y agregar el rectángulo al Canvas (ajustando por la escala)
Rect newRect = new Rect();
newRect.X = col / scaleFactorX;
newRect.Y = row / scaleFactorY;
newRect.Width = width / scaleFactorX;
newRect.Height = height / scaleFactorY;
// Crear un rectángulo para la coincidencia actual
Rectangle matchRect = new Rectangle
{
Stroke = new SolidColorBrush(Colors.Red),
StrokeThickness = 2,
Width = width / scaleFactorX,
Height = height / scaleFactorY,
Width = newRect.Width,
Height = newRect.Height,
Tag = "BuscarCoincidencias"
};
Canvas.SetLeft(matchRect, col / scaleFactorX);
Canvas.SetTop(matchRect, row / scaleFactorY);
Canvas.SetLeft(matchRect, newRect.X);
Canvas.SetTop(matchRect, newRect.Y);
// Verificar si la coincidencia actual está dentro de algún rectángulo aceptado
bool isOverlap = acceptedRectangles.Any(r =>
new Rect(Canvas.GetLeft(r), Canvas.GetTop(r), r.Width, r.Height).IntersectsWith(
new Rect(Canvas.GetLeft(matchRect), Canvas.GetTop(matchRect), matchRect.Width, matchRect.Height)
));
// Si no hay superposición, agregar el rectángulo al Canvas y a la lista de aceptados
if (!isOverlap)
{
Canvas.SetZIndex(matchRect, 40);
_mainViewModel.MainCanvas.Children.Add(matchRect);
acceptedRectangles.Add(matchRect);
search_rectangles.Add(newRect);
ConteoPositivos++;
Coincidencias = ConteoPositivos;
progressDialog.ReportProgress(90);
if (ConteoPositivos > 20)
return;
@ -274,9 +314,11 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
}
}
}
}
});
}
// Método para convertir BitmapSource a Mat
private Mat BitmapSourceToMat(BitmapSource bitmapSource)
{

View File

@ -1,15 +1,9 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Media;
using System.Windows.Navigation;
using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.Siemens;
using CtrEditor.Simulacion;
using System.Windows.Input;
using System.IO;
using System.Windows.Media.Imaging;
using Tesseract;
using Newtonsoft.Json;
namespace CtrEditor.ObjetosSim.Extraccion_Datos
@ -78,7 +72,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
}
[ObservableProperty]
osBase search_Templates;
osBuscarCoincidencias search_Templates;
[ObservableProperty]
public float angulo;
@ -95,10 +89,6 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
[ObservableProperty]
float opacity_oculto;
[ObservableProperty]
bool show_debug_ocr;
public osExtraccionTag()
{
Ancho = 1;
@ -107,80 +97,9 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
Opacity_oculto = 0.1f;
}
private void ShowPreviewWindow(Stream imageStream)
public void CaptureImageAreaAndDoOCR()
{
// Create a new window for preview
Window previewWindow = new Window
{
Title = "Preview Captured Image",
Width = 500,
Height = 500,
Content = new Image
{
Source = BitmapFrame.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad),
Stretch = Stretch.Uniform
}
};
previewWindow.ShowDialog();
}
private void CaptureImageAreaAndDoOCR()
{
if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo)
{
// Asegurarse de que la imagen origen está disponible
if (imagenDeFondo.Source is BitmapSource bitmapSource)
{
// Obtener los DPI de la imagen original
float originalDpiX = (float) bitmapSource.DpiX;
float originalDpiY = (float) bitmapSource.DpiY;
// Estándar DPI en el que el Canvas renderiza la imagen
float canvasDpiX = 96; // WPF usually renders at 96 DPI
float canvasDpiY = 96;
// Calcular el ratio de escala entre el Canvas y la imagen original
float scaleFactorX = originalDpiX / canvasDpiX;
float scaleFactorY = originalDpiY / canvasDpiY;
// Ajustar las coordenadas de recorte en función del ratio de escala
int x = (int)MeterToPixels(Left * scaleFactorX);
int y = (int)MeterToPixels(Top * scaleFactorY);
int width = (int)MeterToPixels(Ancho * scaleFactorX);
int height = (int)MeterToPixels(Alto * scaleFactorY);
// Validar y ajustar el tamaño del recorte para que se mantenga dentro de los límites de la imagen
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x;
if (y + height > bitmapSource.PixelHeight) height = bitmapSource.PixelHeight - y;
// Recortar el área deseada utilizando las coordenadas ajustadas
CroppedBitmap croppedBitmap = new CroppedBitmap(bitmapSource, new Int32Rect(x, y, width, height));
// Codificar el bitmap recortado a un MemoryStream
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(croppedBitmap));
using (MemoryStream memoryStream = new MemoryStream())
{
encoder.Save(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
// Mostrar la imagen recortada en una ventana de previsualización
if (show_debug_ocr) ShowPreviewWindow(memoryStream);
// Cargar la imagen en Tesseract desde el MemoryStream
using (var img = Pix.LoadFromMemory(memoryStream.ToArray()))
using (var engine = new TesseractEngine(@"./Tesseract", "eng", EngineMode.Default))
{
var result = engine.Process(img);
Tag_extract = result.GetText();
}
}
}
}
Tag_extract = CaptureImageAreaAndDoOCR(Left, Top, Ancho, Alto);
}
public override void ucLoaded()

View File

@ -59,7 +59,9 @@ namespace CtrEditor.ObjetosSim
}
// Crear una instancia del tipo especificado
return (osBase?)Activator.CreateInstance(tipoObjeto);
osBase obj = (osBase?)Activator.CreateInstance(tipoObjeto);
obj.InicializaNuevoObjeto();
return obj;
}
public static osBase? CreateInstanceAndPopulate(Type tipoObjeto, string jsonString)
@ -84,6 +86,14 @@ namespace CtrEditor.ObjetosSim
}
}
public static void LimpiarPropiedadesosDatos(PropertyGrid propertyGrid)
{
// Clear previous properties
propertyGrid.SelectedObject = null;
propertyGrid.PropertyDefinitions.Clear();
}
public static void CargarPropiedadesosDatos(object selectedObject, PropertyGrid propertyGrid)
{
// Clear previous properties
@ -114,7 +124,8 @@ namespace CtrEditor.ObjetosSim
propertyDefinition.DisplayName = property.Name.Replace("_", " ");
}
if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int) ||
property.PropertyType == typeof(bool) || property.PropertyType == typeof(osBase) || property.PropertyType == typeof(Color) )
property.PropertyType == typeof(bool) || property.PropertyType == typeof(osBase) ||
property.PropertyType == typeof(osVMmotorSim) || property.PropertyType == typeof(osBuscarCoincidencias) || property.PropertyType == typeof(Color) )
{
propertyGrid.PropertyDefinitions.Add(propertyDefinition);
}

View File

@ -0,0 +1,12 @@
<UserControl x:Class="CtrEditor.ObjetosSim.UserControls.OSComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid>
<ComboBox x:Name="comboBox"
ItemsSource="{Binding FilteredObjetosSimulables, RelativeSource={RelativeSource AncestorType=UserControl}}"
DisplayMemberPath="Nombre"
SelectedItem="{Binding SelectedObject, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}" />
</Grid>
</UserControl>

View File

@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace CtrEditor.ObjetosSim.UserControls
{
public partial class OSComboBox : UserControl, INotifyPropertyChanged
{
public OSComboBox()
{
InitializeComponent();
DataContext = this;
}
public static readonly DependencyProperty ObjetosSimulablesProperty =
DependencyProperty.Register("ObjetosSimulables", typeof(IEnumerable<osBase>), typeof(OSComboBox), new PropertyMetadata(null, OnObjetosSimulablesChanged));
public IEnumerable<osBase> ObjetosSimulables
{
get { return (IEnumerable<osBase>)GetValue(ObjetosSimulablesProperty); }
set { SetValue(ObjetosSimulablesProperty, value); }
}
public static readonly DependencyProperty ObjectTypeProperty =
DependencyProperty.Register("ObjectType", typeof(Type), typeof(OSComboBox), new PropertyMetadata(null, OnObjectTypeChanged));
public Type ObjectType
{
get { return (Type)GetValue(ObjectTypeProperty); }
set { SetValue(ObjectTypeProperty, value); }
}
public static readonly DependencyProperty SelectedObjectNameProperty =
DependencyProperty.Register("SelectedObjectName", typeof(string), typeof(OSComboBox), new PropertyMetadata(string.Empty, OnSelectedObjectNameChanged));
public string SelectedObjectName
{
get {
var str = (string)GetValue(SelectedObjectNameProperty);
return str;
}
set
{
SetValue(SelectedObjectNameProperty, value);
OnPropertyChanged(nameof(SelectedObjectName));
}
}
public static readonly DependencyProperty SelectedObjectProperty =
DependencyProperty.Register("SelectedObject", typeof(osBase), typeof(OSComboBox), new PropertyMetadata(null, OnSelectedObjectChanged));
public osBase SelectedObject
{
get { return (osBase)GetValue(SelectedObjectProperty); }
set
{
SetValue(SelectedObjectProperty, value);
OnPropertyChanged(nameof(SelectedObject));
}
}
public ObservableCollection<osBase> FilteredObjetosSimulables { get; } = new ObservableCollection<osBase>();
private static void OnObjetosSimulablesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (OSComboBox)d;
control.FilterObjetosSimulables();
}
private static void OnObjectTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (OSComboBox)d;
control.FilterObjetosSimulables();
}
private static void OnSelectedObjectNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (OSComboBox)d;
control.UpdateSelectedObject();
}
private static void OnSelectedObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (OSComboBox)d;
control.UpdateSelectedObjectName();
}
private void FilterObjetosSimulables()
{
FilteredObjetosSimulables.Clear();
if (ObjetosSimulables != null && ObjectType != null)
{
foreach (var obj in ObjetosSimulables.Where(o => o.GetType() == ObjectType))
{
FilteredObjetosSimulables.Add(obj);
}
}
}
private void UpdateSelectedObject()
{
if (SelectedObjectName != null && ObjetosSimulables != null)
{
SelectedObject = ObjetosSimulables.FirstOrDefault(o => o.Nombre == SelectedObjectName);
}
}
private void UpdateSelectedObjectName()
{
if (SelectedObject != null)
{
SelectedObjectName = SelectedObject.Nombre;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -15,6 +15,13 @@ using System.Windows.Controls;
using System.ComponentModel;
using System.Configuration;
using System.Windows.Threading;
using System.IO;
using Tesseract;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using Newtonsoft.Json;
using JsonIgnoreAttribute = Newtonsoft.Json.JsonIgnoreAttribute;
using System.Collections.ObjectModel;
using ItemCollection = Xceed.Wpf.Toolkit.PropertyGrid.Attributes.ItemCollection;
namespace CtrEditor.ObjetosSim
{
@ -59,11 +66,17 @@ namespace CtrEditor.ObjetosSim
public abstract partial class osBase : ObservableObject
{
public virtual string Nombre { get; set; } = "osBase";
[JsonIgnore]
private Storyboard _storyboard;
[JsonIgnore]
private System.Threading.Timer timer = null;
public UniqueId Id { get; set; }
[ObservableProperty]
[property: Description("X coordinate.")]
[property: Category("Layout:")]
private float left;
partial void OnLeftChanged(float value)
@ -81,6 +94,8 @@ namespace CtrEditor.ObjetosSim
public virtual void LeftChanging(float oldValue, float newValue) { }
[ObservableProperty]
[property: Description("Y coordinate.")]
[property: Category("Layout:")]
private float top;
partial void OnTopChanged(float value)
@ -97,13 +112,128 @@ namespace CtrEditor.ObjetosSim
public virtual void TopChanging(float oldValue, float newValue) { }
public void InicializaNuevoObjeto()
{
Id = new UniqueId().ObtenerNuevaID();
}
// Group
[ObservableProperty]
[property: Description("This is a link to a faceplate. It works like an anchor.")]
[property: Category("Group:")]
private string group_Panel;
protected void UpdateChildsTop(float offsetY)
{
if (!string.IsNullOrEmpty(Nombre) && _mainViewModel != null)
{
foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
{
if (objetoSimulable != this && objetoSimulable.Group_Panel == Nombre)
{
objetoSimulable.Top += offsetY;
}
}
}
}
protected void UpdateChildsLeft(float offsetX)
{
if (!string.IsNullOrEmpty(Nombre) && _mainViewModel != null)
{
foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
{
if (objetoSimulable != this && objetoSimulable.Group_Panel == Nombre)
{
objetoSimulable.Left += offsetX;
}
}
}
}
private void ShowPreviewWindow(Stream imageStream)
{
// Create a new window for preview
Window previewWindow = new Window
{
Title = "Preview Captured Image",
Width = 500,
Height = 500,
Content = new Image
{
Source = BitmapFrame.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad),
Stretch = Stretch.Uniform
}
};
previewWindow.ShowDialog();
}
public string CaptureImageAreaAndDoOCR(float Left, float Top, float Ancho, float Alto)
{
if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo)
{
// Asegurarse de que la imagen origen está disponible
if (imagenDeFondo.Source is BitmapSource bitmapSource)
{
// Obtener los DPI de la imagen original
float originalDpiX = (float)bitmapSource.DpiX;
float originalDpiY = (float)bitmapSource.DpiY;
// Estándar DPI en el que el Canvas renderiza la imagen
float canvasDpiX = 96; // WPF usually renders at 96 DPI
float canvasDpiY = 96;
// Calcular el ratio de escala entre el Canvas y la imagen original
float scaleFactorX = originalDpiX / canvasDpiX;
float scaleFactorY = originalDpiY / canvasDpiY;
// Ajustar las coordenadas de recorte en función del ratio de escala
int x = (int)MeterToPixels(Left * scaleFactorX);
int y = (int)MeterToPixels(Top * scaleFactorY);
int width = (int)MeterToPixels(Ancho * scaleFactorX);
int height = (int)MeterToPixels(Alto * scaleFactorY);
// Validar y ajustar el tamaño del recorte para que se mantenga dentro de los límites de la imagen
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x;
if (y + height > bitmapSource.PixelHeight) height = bitmapSource.PixelHeight - y;
// Recortar el área deseada utilizando las coordenadas ajustadas
CroppedBitmap croppedBitmap = new CroppedBitmap(bitmapSource, new Int32Rect(x, y, width, height));
// Codificar el bitmap recortado a un MemoryStream
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(croppedBitmap));
using (MemoryStream memoryStream = new MemoryStream())
{
encoder.Save(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
//ShowPreviewWindow(memoryStream);
// Cargar la imagen en Tesseract desde el MemoryStream
using (var img = Pix.LoadFromMemory(memoryStream.ToArray()))
using (var engine = new TesseractEngine(@"./Tesseract", "eng", EngineMode.Default))
{
var result = engine.Process(img);
return result.GetText();
}
}
}
}
return "";
}
// All Pages Objects
[NotifyPropertyChangedFor(nameof(Show_on_this_page))]
[ObservableProperty]
[property: Description("Enable this object to be used in all pages.")]
[property: Category("Layout:")]
private bool enable_on_all_pages;
partial void OnEnable_on_all_pagesChanged(bool value)
@ -115,6 +245,7 @@ namespace CtrEditor.ObjetosSim
private List<string> Show_on_this_pages_oculto;
private bool show_on_this_page;
[property: Category("Layout:")]
public bool Show_on_this_page
{
get
@ -687,6 +818,45 @@ namespace CtrEditor.ObjetosSim
}
public class UniqueId
{
public int Value { get; set; }
public UniqueId ObtenerNuevaID()
{
Value = EstadoPersistente.Instance.newid;
if (Value == 0)
Value++;
return this;
}
public void NoId()
{
// No ID == NULL
Value = 0;
}
}
public class osBaseItemsSource<T> : IItemsSource
{
public ItemCollection GetValues()
{
ItemCollection items = new ItemCollection();
var viewModel = (MainViewModel)App.Current.MainWindow.DataContext;
var objetosSimulables = viewModel.ObjetosSimulables;
items.Add("");
foreach (var obj in objetosSimulables)
{
if (obj.GetType() == typeof(T))
{
items.Add(obj.Nombre);
}
}
return items;
}
}
public class TimerTON_TOFF
{
Stopwatch _stopwatch_ON = new Stopwatch();

View File

@ -13,7 +13,6 @@ using System.Collections.ObjectModel;
namespace CtrEditor
{
public class SubclassFilterConverter : IValueConverter
{
public Type TargetType { get; set; }

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using System;
using System.IO;
using System.Text.Json;
using System.Security.Permissions;
namespace CtrEditor
{
@ -20,6 +21,9 @@ namespace CtrEditor
// Propiedad privada para el directorio de trabajo
private string _strDirectorioTrabajo;
private string _imagen;
private int _id;
// Propiedad pública con get y set para controlar el acceso a _strDirectorioTrabajo
public string directorio
{
@ -27,6 +31,20 @@ namespace CtrEditor
set { _strDirectorioTrabajo = value; }
}
public string imagen
{
get { return _imagen; }
set { _imagen = value; }
}
public int newid
{
get {
_id++;
return _id; }
set { _id = value; }
}
// Constructor privado para evitar la instanciación externa
public EstadoPersistente()
{