diff --git a/CtrEditor.csproj b/CtrEditor.csproj
index ee4c224..7b6fce2 100644
--- a/CtrEditor.csproj
+++ b/CtrEditor.csproj
@@ -12,6 +12,7 @@
+
diff --git a/ObjetosSim/osBase.cs b/ObjetosSim/osBase.cs
index 8676782..fb761af 100644
--- a/ObjetosSim/osBase.cs
+++ b/ObjetosSim/osBase.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Windows.Controls;
+using System.Windows.Data;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CtrEditor.ObjetosSim
@@ -80,6 +82,21 @@ namespace CtrEditor.ObjetosSim
}
}
+ public class MeterToPixelConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ float meters = (float)value;
+ return PixelToMeter.Instance.calc.MetersToPixels(meters);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ float pixels = (float)value;
+ return PixelToMeter.Instance.calc.PixelsToMeters(pixels);
+ }
+ }
+
public class UnitConverter
{
// La escala representa cuántos metros hay en un píxel
diff --git a/ObjetosSim/ucTransporteTTop.xaml.cs b/ObjetosSim/ucTransporteTTop.xaml.cs
index ac0a356..946e5b3 100644
--- a/ObjetosSim/ucTransporteTTop.xaml.cs
+++ b/ObjetosSim/ucTransporteTTop.xaml.cs
@@ -89,6 +89,7 @@ namespace CtrEditor.ObjetosSim
set
{
Data.Length = value;
+ OnPropertyChanged(nameof(AnchoPixels));
OnPropertyChanged(nameof(Ancho));
}
}
@@ -97,6 +98,7 @@ namespace CtrEditor.ObjetosSim
set
{
Data.Width = value;
+ OnPropertyChanged(nameof(AltoPixels));
OnPropertyChanged(nameof(Alto));
}
}
@@ -106,6 +108,7 @@ namespace CtrEditor.ObjetosSim
set
{
Data.Length = (float)PixelToMeter.Instance.calc.PixelsToMeters(value);
+ OnPropertyChanged(nameof(AnchoPixels));
OnPropertyChanged(nameof(Ancho));
}
}
@@ -115,6 +118,7 @@ namespace CtrEditor.ObjetosSim
set
{
Data.Width = (float)PixelToMeter.Instance.calc.PixelsToMeters(value);
+ OnPropertyChanged(nameof(AltoPixels));
OnPropertyChanged(nameof(Alto));
}
}
@@ -182,7 +186,7 @@ namespace CtrEditor.ObjetosSim
public void Resize(float width, float height)
{
if (Datos is osTransporteTTop datos)
- datos.Ancho = width;
+ datos.AnchoPixels = width;
}
public void Move(float LeftPixels, float TopPixels)
{
diff --git a/Simulacion/GeometrySimulator.cs b/Simulacion/GeometrySimulator.cs
index fe1853c..533411d 100644
--- a/Simulacion/GeometrySimulator.cs
+++ b/Simulacion/GeometrySimulator.cs
@@ -1,4 +1,5 @@
using CtrEditor.ObjetosSim;
+using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
@@ -44,7 +45,7 @@ public class Circle
foreach (var rectangle in rectangles)
{
float overlap = CalculateOverlapPercentage(this, rectangle);
- if (overlap > 0)
+ if (overlap > 10)
{
Overlap += overlap;
isTracted = true; // El círculo está siendo traccionado por un rectángulo
@@ -196,82 +197,59 @@ public class Circle
return angle < 90 ? 90 - angle : angle - 90;
}
- public float CalculateOverlapPercentage(Circle circle, Rectangle rectangle)
+ public static float CalculateOverlapPercentage(Circle circle, Rectangle rectangle)
{
- // Convertir ángulo del rectángulo de grados a radianes
- float angleRadians = (float)(rectangle.Angle * Math.PI / 180);
-
- // Centro del círculo
- Vector2 circleCenter = new Vector2(circle.Left + circle.Diameter / 2, circle.Top + circle.Diameter / 2);
- float radius = circle.Diameter / 2;
-
- // Pivot del rectángulo es el Top Left
- Vector2 rectPivot = new Vector2(rectangle.Left, rectangle.Top);
-
- // Rotar el centro del círculo respecto al pivote del rectángulo
- Vector2 rotatedCircleCenter = RotatePoint(circleCenter, rectPivot, -angleRadians);
-
- // Comprobar si el círculo rotado intersecta con el rectángulo alineado
- // Rectángulo "alineado" asume que después de rotar el círculo, el rectángulo se comporta como si estuviera alineado con los ejes
- if (IsCircleRectangleIntersecting(rotatedCircleCenter, radius, rectPivot, rectangle.Length, rectangle.Width))
- {
- float overlapArea = EstimateOverlapArea(rotatedCircleCenter, radius, rectPivot, rectangle.Length, rectangle.Width);
- float circleArea = (float)(Math.PI * radius * radius);
- return (overlapArea / circleArea) * 100;
- }
- return 0;
- }
-
-
- private bool IsCircleRectangleIntersecting(Vector2 circleCenter, float radius, Vector2 rectTopLeft, float length, float width)
- {
- float closestX = Math.Max(rectTopLeft.X, Math.Min(circleCenter.X, rectTopLeft.X + length));
- float closestY = Math.Max(rectTopLeft.Y, Math.Min(circleCenter.Y, rectTopLeft.Y + width));
-
- float distanceX = circleCenter.X - closestX;
- float distanceY = circleCenter.Y - closestY;
-
- return (distanceX * distanceX + distanceY * distanceY) < (radius * radius);
- }
-
-
-
- private float EstimateOverlapArea(Vector2 circleCenter, float radius, Vector2 rectTopLeft, float length, float width)
- {
- float rectRight = rectTopLeft.X + length;
- float rectBottom = rectTopLeft.Y + width;
- float distToLeft = Math.Max(0, rectTopLeft.X - circleCenter.X);
- float distToRight = Math.Max(0, circleCenter.X - rectRight);
- float distToTop = Math.Max(0, rectTopLeft.Y - circleCenter.Y);
- float distToBottom = Math.Max(0, circleCenter.Y - rectBottom);
- float distToNearestEdge = Math.Min(Math.Min(distToLeft, distToRight), Math.Min(distToTop, distToBottom));
-
- if (distToNearestEdge >= radius)
- return 0; // No overlap
-
- float overlapRadius = radius - distToNearestEdge;
- float overlapArea = (float)(Math.PI * overlapRadius * overlapRadius);
-
- return Math.Min(overlapArea, (float)(Math.PI * radius * radius)); // Cap at circle area
- }
-
-
-
- private Vector2 RotatePoint(Vector2 point, Vector2 pivot, float angle)
- {
- float cosTheta = (float)Math.Cos(angle);
- float sinTheta = (float)Math.Sin(angle);
- // Ajustar punto por pivot antes de aplicar rotación
- Vector2 translatedPoint = new Vector2(point.X - pivot.X, point.Y - pivot.Y);
- // Rotar el punto
- Vector2 rotatedPoint = new Vector2(
- translatedPoint.X * cosTheta - translatedPoint.Y * sinTheta,
- translatedPoint.X * sinTheta + translatedPoint.Y * cosTheta
+ // Convertir el círculo en un cuadrado aproximado.
+ float squareSide = circle.Diameter / (float)Math.Sqrt(Math.PI);
+ RotatedRect square = new RotatedRect(
+ new Point2f(circle.Left + circle.Diameter / 2, circle.Top + circle.Diameter / 2),
+ new Size2f(squareSide, squareSide),
+ 0 // Sin rotación
);
- // Traducir el punto de vuelta
- return new Vector2(rotatedPoint.X + pivot.X, rotatedPoint.Y + pivot.Y);
+
+ // Ajustamos el rectángulo para que se considere rotado desde el centro, pero calculado desde Top-Left
+ RotatedRect rotatedRectangle = CreateRotatedRectFromTopLeft(rectangle);
+
+ // Usar OpenCV para encontrar la intersección.
+ using (var mat = new Mat())
+ {
+ var result = Cv2.RotatedRectangleIntersection(square, rotatedRectangle, mat);
+ if (result != RectanglesIntersectTypes.None)
+ {
+ // Calcular el área de la intersección
+ float intersectionArea = (float) Cv2.ContourArea(mat);
+ float circleArea = (float)(Math.PI * Math.Pow(circle.Diameter / 2, 2));
+ return (intersectionArea / circleArea) * 100;
+ }
+ }
+
+ return 0; // No hay intersección
}
+ public static RotatedRect CreateRotatedRectFromTopLeft(Rectangle rectangle)
+ {
+ // El punto de pivote es Top-Left, calculamos el centro sin rotar
+ float originalCenterX = rectangle.Left + rectangle.Length / 2.0f;
+ float originalCenterY = rectangle.Top + rectangle.Width / 2.0f;
+
+ // Convertimos el ángulo a radianes para la rotación
+ float angleRadians = rectangle.Angle * (float)Math.PI / 180;
+
+ // Calcular las nuevas coordenadas del centro después de la rotación
+ float rotatedCenterX = rectangle.Left + (originalCenterX - rectangle.Left) * (float)Math.Cos(angleRadians) - (originalCenterY - rectangle.Top) * (float)Math.Sin(angleRadians);
+ float rotatedCenterY = rectangle.Top + (originalCenterX - rectangle.Left) * (float)Math.Sin(angleRadians) + (originalCenterY - rectangle.Top) * (float)Math.Cos(angleRadians);
+
+ // Crear el RotatedRect con el nuevo centro y el tamaño original
+ RotatedRect rotatedRect = new RotatedRect(
+ new Point2f(rotatedCenterX, rotatedCenterY),
+ new Size2f(rectangle.Length, rectangle.Width),
+ rectangle.Angle
+ );
+
+ return rotatedRect;
+ }
+
+
}
@@ -340,6 +318,21 @@ public class Line
}
}
+public class Square
+{
+ public float Left { get; set; }
+ public float Top { get; set; }
+ public float Size { get; set; } // 'Size' es la longitud de un lado del cuadrado
+
+ public Square(float left, float top, float size)
+ {
+ Left = left;
+ Top = top;
+ Size = size;
+ }
+}
+
+
// Clase principal que gestiona la simulación
public class SimulationManager