diff --git a/JansenLegViewer.sln b/JansenLegViewer.sln
new file mode 100644
index 0000000..f36a48e
--- /dev/null
+++ b/JansenLegViewer.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31727.386
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JansenLegSimulator", "JansenLegViewer\JansenLegSimulator.csproj", "{85D59382-1D81-41E1-8213-CAAF5D8F6B2C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {85D59382-1D81-41E1-8213-CAAF5D8F6B2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {85D59382-1D81-41E1-8213-CAAF5D8F6B2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {85D59382-1D81-41E1-8213-CAAF5D8F6B2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {85D59382-1D81-41E1-8213-CAAF5D8F6B2C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B0ECD860-46CD-477E-ADA8-2F17A594387D}
+ EndGlobalSection
+EndGlobal
diff --git a/JansenLegViewer/App.xaml b/JansenLegViewer/App.xaml
new file mode 100644
index 0000000..18588f8
--- /dev/null
+++ b/JansenLegViewer/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/JansenLegViewer/App.xaml.cs b/JansenLegViewer/App.xaml.cs
new file mode 100644
index 0000000..b97d03c
--- /dev/null
+++ b/JansenLegViewer/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace JansenLegViewer
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/JansenLegViewer/AssemblyInfo.cs b/JansenLegViewer/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/JansenLegViewer/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/JansenLegViewer/CosasQueNoSeExplicanEnMatesDePrimero.cs b/JansenLegViewer/CosasQueNoSeExplicanEnMatesDePrimero.cs
new file mode 100644
index 0000000..d80ce46
--- /dev/null
+++ b/JansenLegViewer/CosasQueNoSeExplicanEnMatesDePrimero.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Linq;
+using System.Text;
+using System.Drawing;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using static System.Math;
+using System.Numerics;
+
+/*
+ Función que permite obtener las posiciones de las
+ posibles intersecciones entre dos circulos.
+
+ PD: le debeo un café a alguien random de internet
+ */
+
+namespace JansenLegSimulator
+{
+ public class CosasQueNoSeExplicanEnMatesDePrimero
+ {
+ ///
+ /// Gets the intersections of two circles
+ ///
+ /// The first circle's center
+ /// The second circle's center
+ /// The first circle's radius
+ /// The second circle's radius. If omitted, assumed to equal the first circle's radius
+ /// An array of intersection points. May have zero, one, or two values
+ /// Adapted from http://csharphelper.com/blog/2014/09/determine-where-two-circles-intersect-in-c/
+ public static Vector2[] CalculateCircleIntersections(Vector2 center1, Vector2 center2, double radius1, double? radius2 = null)
+ {
+ // Definir radios. Si sólo se ha dado R1,
+ // asignar valor de R1 a los dos radios
+ var (r1, r2) = (radius1, radius2 ?? radius1);
+
+ // Definir centros de los circulos.
+ (double x1, double y1, double x2, double y2) = (center1.X, center1.Y, center2.X, center2.Y);
+
+ // Determinar la distancia entre los dos centros.
+ // Es el módulo del vector que une los dos centros.
+ double d = Sqrt(Pow(x1 - x2, 2) + Pow(y1 - y2, 2));
+
+ // Si la suma de radios es menor a la distancia que
+ // une los centros, devolver un array vacío.
+ // No existe intersección.
+ if (!(Abs(r1 - r2) <= d && d <= r1 + r2)) { return new Vector2[0]; }
+
+ // En este momento, se dan las condiciones para que
+ // por lo menos exista una intersección
+ var dsq = d * d; // Caucular el cuadrado de la distancia (d^2)
+ var (r1sq, r2sq) = (r1 * r1, r2 * r2); // Calcular los cuadrados de los radios (r^2)
+ var r1sq_r2sq = r1sq - r2sq; // Calcular la diferencia de los r^2 (incR^2)
+ var a = r1sq_r2sq / (2 * dsq); // Calcular la división (incR^2)/(2*d^2)
+
+ var c = Sqrt(2 * (r1sq + r2sq) / dsq - (r1sq_r2sq * r1sq_r2sq) / (dsq * dsq) - 1);
+
+ // Calcular las componentes de los resultados
+ var fx = (x1 + x2) / 2 + a * (x2 - x1);
+ var gx = c * (y2 - y1) / 2;
+
+ var fy = (y1 + y2) / 2 + a * (y2 - y1);
+ var gy = c * (x1 - x2) / 2;
+
+ // Generar los vectores de las intersecciones resultado
+ var i1 = new Vector2((float)(fx + gx), (float)(fy + gy));
+ var i2 = new Vector2((float)(fx - gx), (float)(fy - gy));
+
+ // Si son la misma solucción deveolver sólo i1.
+ // Si son ditintas, devolver ambas soluciones.
+ return i1 == i2 ?
+ new Vector2[] { i1 } :
+ new Vector2[] { i1, i2 };
+ }
+ }
+}
diff --git a/JansenLegViewer/Cálculos.cs b/JansenLegViewer/Cálculos.cs
new file mode 100644
index 0000000..23cba18
--- /dev/null
+++ b/JansenLegViewer/Cálculos.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+using static JansenLegSimulator.Rod;
+
+namespace JansenLegSimulator
+{
+ public partial class Cálculos
+ {
+ private void DefineSystem()
+ {
+ // Definir las barra motriz
+ M = new Rod(new Vector2(a, l)) { Length = m, RodName = "M" };
+
+ // Definir las barras semi-independientes
+ // Aquellas que tienen un extremo fijado a una coordenada
+ B = new Rod(new Vector2(0, 0)) { Length = b, RodName = "B" };
+ C = new Rod(new Vector2(0, 0)) { Length = c, RodName = "C" };
+ D = new Rod(new Vector2(0, 0)) { Length = d, RodName = "D" };
+
+ // Definir y conectar los inicios de las barras flotantes
+ // Aquellas cuyos dos extremos están conectados a otra barra
+ J = new Rod() { Length = j, RodName = "J" }; J.ConnectBegin(ref M);
+ K = new Rod() { Length = k, RodName = "K" }; K.ConnectBegin(ref M);
+ E = new Rod() { Length = e, RodName = "E" }; E.ConnectBegin(ref B);
+
+ G = new Rod() { Length = g, RodName = "G" }; G.ConnectBegin(ref C);
+ F = new Rod() { Length = f, RodName = "F" }; F.ConnectBegin(ref D);
+
+ H = new Rod() { Length = h, RodName = "H" }; H.ConnectBegin(ref G);
+ I = new Rod() { Length = i, RodName = "I" }; I.ConnectBegin(ref C);
+
+ // Añadir las barras definidas a la lista
+ // de elementos móviles.
+ Elements.Add(M);
+ Elements.Add(J);
+ Elements.Add(B);
+
+ Elements.Add(C);
+ Elements.Add(K);
+
+ Elements.Add(E);
+ Elements.Add(D);
+
+ Elements.Add(G);
+ Elements.Add(F);
+
+ Elements.Add(H);
+ Elements.Add(I);
+ }
+
+ [STAThread]
+ public void CalculateSystem()
+ {
+ // Para cada par de barras calcular y asignar los
+ // ángulos de rotación necesarios para unirlas
+
+ // Articulación JB
+ (J.Alpha, B.Alpha) = GetIntersectionAlphas(J, B);
+ // Articulación CK
+ (C.Alpha, K.Alpha) = GetIntersectionAlphas(C, K);
+ // Articulación ED
+ (E.Alpha, D.Alpha) = GetIntersectionAlphas(E, D);
+ // Articulación FG
+ (F.Alpha, G.Alpha) = GetIntersectionAlphas(F, G);
+ // Articulación HI
+ (H.Alpha, I.Alpha) = GetIntersectionAlphas(H, I);
+ }
+ }
+}
diff --git a/JansenLegViewer/JansenLegSimulator.csproj b/JansenLegViewer/JansenLegSimulator.csproj
new file mode 100644
index 0000000..407932c
--- /dev/null
+++ b/JansenLegViewer/JansenLegSimulator.csproj
@@ -0,0 +1,9 @@
+
+
+
+ WinExe
+ net5.0-windows
+ true
+
+
+
diff --git a/JansenLegViewer/JansenLegSimulator.zip b/JansenLegViewer/JansenLegSimulator.zip
new file mode 100644
index 0000000..2ebee8c
Binary files /dev/null and b/JansenLegViewer/JansenLegSimulator.zip differ
diff --git a/JansenLegViewer/MainWindow.xaml b/JansenLegViewer/MainWindow.xaml
new file mode 100644
index 0000000..8100b97
--- /dev/null
+++ b/JansenLegViewer/MainWindow.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/JansenLegViewer/MainWindow.xaml.cs b/JansenLegViewer/MainWindow.xaml.cs
new file mode 100644
index 0000000..699182d
--- /dev/null
+++ b/JansenLegViewer/MainWindow.xaml.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using System.Numerics;
+using System.Drawing;
+using System.Windows.Controls;
+using static JansenLegSimulator.Rod;
+
+namespace JansenLegSimulator
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class Cálculos : Window
+ {
+ // Origen de cordenadas
+ Vector2 Center;
+ // Dimensiones de los segmentos (iniciales, se pueden modificar des de la interfaz)
+ public float SCALE { get; set; } = 2.0f;
+ public float a => 38.0f * SCALE;
+ public float b => 41.5f * SCALE;
+ public float c => 39.3f * SCALE;
+ public float d => 40.1f * SCALE;
+ public float e => 55.8f * SCALE;
+ public float f => 39.4f * SCALE;
+ public float g => 36.7f * SCALE;
+ public float h => 65.7f * SCALE;
+ public float i => 49.0f * SCALE;
+ public float j => 50.0f * SCALE;
+ public float k => 61.9f * SCALE;
+ public float l => 7.8f * SCALE;
+ public float m => 15.0f * SCALE;
+
+ private Rod B, C, D, E, F, G, H, I, J, K, M;
+
+ public float Omega { get; set; } = (2 * MathF.PI);
+
+ System.Timers.Timer t = new(15);
+ private System.Diagnostics.Stopwatch Chrono = new();
+
+ public List Elements { get; set; } = new List();
+ private List Points = new();
+ public int MaxPoints { get; set; } = 25;
+
+ #region Constructor y handlers de la ventana
+ public Cálculos()
+ {
+ InitializeComponent();
+
+ this.Loaded += MainWindow_Loaded;
+ this.Closing += MainWindow_Closing;
+ }
+ private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ Environment.Exit(0);
+ }
+ private void MainWindow_Loaded(object sender, RoutedEventArgs e)
+ {
+ DefineSystem();
+ DrawSystem();
+ t.Elapsed += Tick;
+ }
+
+ // Receptores de eventos de click de los botones de la interfaz
+ private void btnPlay_Click(object sender, RoutedEventArgs e) => StartSimulation();
+ private void btnPause_Click(object sender, RoutedEventArgs e) => PauseSimulation();
+ private void btnStop_Click(object sender, RoutedEventArgs e) => StopSimulation();
+ #endregion
+
+ // Receptor de evento de ciclo del reloj
+ private void Tick(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ try
+ {
+ // Actualizar el ángulo de la barra motriz
+ // con ω * t radianes
+ (Elements[0] as Rod).Alpha = (float)(Omega * Chrono.Elapsed.TotalSeconds) % 2 * MathF.PI;
+
+ lock (Points)
+ {
+ // Eliminar puntos antiguos si se ha superado el límite de puntos especificado
+ if (Points.Count > MaxPoints)
+ Points.RemoveAt(0);
+ }
+
+ // Ejecutar cálculos del sistema
+ CalculateSystem();
+ // Ejecutar renderizado del sistema en el hilo de principal
+ this.Dispatcher.Invoke(() => DrawSystem());
+ }
+ catch
+ {
+ // Si la geometría es inválida, se lanzará una excepción
+ // Detener simulación y mostrar el estado de error
+ this.Dispatcher.Invoke(() =>
+ {
+ StopSimulation();
+ SimulationStatus.Content = "Error";
+ });
+ }
+ }
+
+ #region Control de la simulación
+ // Inicia la simulación
+ public void StartSimulation()
+ {
+ SimulationStatus.Content = "Simulando...";
+ t.Start();
+ Chrono.Start();
+ }
+ // Pausa la simulación
+ public void PauseSimulation()
+ {
+ SimulationStatus.Content = "En pausa";
+ t.Stop();
+ Chrono.Stop();
+ }
+ // Detiene la simulación y reinicia las variables
+ // de tiempo
+ public void StopSimulation()
+ {
+ SimulationStatus.Content = "Detenido";
+ t.Stop();
+ Chrono.Stop();
+ Chrono.Reset();
+ }
+ #endregion
+
+ [STAThread]
+ public void DrawSystem()
+ {
+ plot.Children.Clear(); // Borrar el contenido anterior del lienzo
+ Center = new Vector2( // Calcular el centro del lienzo
+ (float)plot.ActualWidth / 2,
+ (float)plot.ActualHeight / 2);
+
+ foreach (var element in Elements) // Dibujar los elementos en el lienzo
+ {
+ if (element.GetType() == typeof(Rod))
+ DrawElement(element);
+ if (element.GetType() == typeof(MotorRod))
+ DrawElement(element);
+ }
+
+ // Registrar el punto que actualmente se ubica
+ // en el extremo final de la barra I
+ Points.Add(I.EndPosition);
+
+ lock (Points)
+ {
+ // Dibujar los puntos en el lienzo
+ foreach (Vector2 point in Points)
+ DrawPoint(point);
+ }
+ }
+
+ #region Inserción de objetos
+ public void DrawElement(object r) where Type : Rod
+ {
+ // Declarar una línea de color azul con 5px de grosos
+ // segmentada entre los dos extremos de la barra.
+ Line l = new Line()
+ {
+ Stroke = Brushes.Blue,
+ StrokeThickness = 5,
+ X1 = Center.X + (r as Type).StartPosition.X,
+ X2 = Center.X + (r as Type).EndPosition.X,
+ Y1 = Center.Y - (r as Type).StartPosition.Y,
+ Y2 = Center.Y - (r as Type).EndPosition.Y,
+ };
+ // Añadir la barra al lienzo
+ plot.Children.Add(l);
+ }
+ public void DrawPoint(Vector2 Location, double diameter = 5)
+ {
+ double r = diameter / 2; // Calcular radio del punto
+
+ // Declarar una elipse de color rojo con
+ // el mismo ancho que altura (diámetro).
+ Ellipse e = new Ellipse()
+ {
+ Fill = Brushes.Red,
+ Width = diameter,
+ Height = diameter
+ };
+
+ // Añadir la elipse al lienzo
+ plot.Children.Add(e);
+
+ // Situar la elipse dentro del lienzo.
+ // Los ejes de coordenadas del lienzo tienen origen en
+ // la esquina superior izquierda. El eje vertical se debe
+ // invertir.
+ Canvas.SetLeft(e, Center.X + Location.X - r);
+ Canvas.SetTop(e, plot.ActualHeight - (Center.Y + Location.Y - r));
+ }
+ #endregion
+ }
+}
diff --git a/JansenLegViewer/Motor.cs b/JansenLegViewer/Motor.cs
new file mode 100644
index 0000000..4d8038a
--- /dev/null
+++ b/JansenLegViewer/Motor.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Numerics;
+using System.Drawing;
+
+namespace JansenLegSimulator
+{
+ public class MotorRod : Rod
+ {
+ public override Vector2 StartPosition { get; set; }
+ }
+}
diff --git a/JansenLegViewer/Rod.cs b/JansenLegViewer/Rod.cs
new file mode 100644
index 0000000..a557afe
--- /dev/null
+++ b/JansenLegViewer/Rod.cs
@@ -0,0 +1,199 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Numerics;
+using System.Drawing;
+
+namespace JansenLegSimulator
+{
+ public class Rod
+ {
+ #region Constructores
+ // Constructor de barra libre
+ public Rod() { }
+
+ // Constructor de barra con un extremo fijado a un punto
+ public Rod(Vector2 begining)
+ {
+ _startPosition = begining;
+ }
+ #endregion
+ #region Conexiones
+ ///
+ /// Barra a la que se une por el extremo inicial
+ ///
+ private Rod JointBegining { get; set; } = null;
+ ///
+ /// Barras a las cuales se une por el extremo final
+ ///
+ private List JointsEnding { get; set; } = new();
+ ///
+ /// Conecta el inicio de una barra a otra barra
+ ///
+ /// La barra a la cual se unirá esta
+ public void ConnectBegin(ref Rod linkage)
+ {
+ if (linkage == null) throw new NullReferenceException("The rod cannot be null");
+ if (JointBegining != null) throw new Exception("The beginning is already assigned");
+ JointBegining = linkage;
+ }
+ ///
+ /// Conecta el final de una barra a otra barra
+ ///
+ /// La barra a la cual se unirá esta
+ public void ConnectEnd(ref Rod linkage)
+ {
+ if (linkage == null) throw new NullReferenceException("The rod cannot be null");
+ if (!JointsEnding.Contains(linkage))
+ JointsEnding.Add(linkage);
+ }
+ ///
+ /// Desconecta (si está conectada) la barra especificada
+ ///
+ /// Barra a ser desconectada
+ public void Disconnect(ref Rod linkage)
+ {
+ if (JointBegining == linkage) JointBegining = null;
+ if (JointsEnding.Contains(linkage)) JointsEnding.Remove(linkage);
+ }
+ #endregion
+
+ #region Propiedades de la barra
+ public string RodName { get; set; } = "Unnamed";
+ ///
+ /// Longitud de la barra
+ ///
+ public float Length { get; set; } = 20;
+
+ private float? _alpha = null;
+ ///
+ /// Ángulo de rotación de la barra. Si no se establece será 0 radianes.
+ ///
+ public float Alpha
+ {
+ get => (_alpha != null) ? (float)_alpha : 0;
+ set => _alpha = value;
+ }
+
+ private Vector2? _startPosition = null;
+ ///
+ /// Posición de incio (eje de esta barra).
+ /// Si se ha unido el inicio a otra barra, se calculará a partir de la posición final de la barra sobre la cual está
+ ///
+ public virtual Vector2 StartPosition
+ {
+ get => (_startPosition != null) ? (Vector2)_startPosition :
+ (JointBegining != null) ? JointBegining.EndPosition : new Vector2(0, 0);
+ set => _startPosition = value;
+ }
+ ///
+ /// Posición final.
+ /// Se calcula a partir de la posición inicial, el ángulo y la longitud.
+ ///
+ public virtual Vector2 EndPosition
+ {
+ get => new Vector2(
+ StartPosition.X + Length * MathF.Cos(Alpha),
+ StartPosition.Y + Length * MathF.Sin(Alpha)
+ );
+ }
+ ///
+ /// Posición central.
+ /// Se calcula a partir de la posición inicial, el ángulo y la longitud.
+ ///
+ public virtual Vector2 Center
+ {
+ get => new Vector2(
+ StartPosition.X + Length * MathF.Cos(Alpha) / 2,
+ StartPosition.Y + Length * MathF.Sin(Alpha) / 2
+ );
+ }
+ #endregion
+
+ ///
+ /// Calcula el punto de intersección entre dos barras de longitud y eje de rotación determinados.
+ ///
+ /// Primera barra
+ /// Segunda barra
+ /// En caso de que existan dos intersecciones, número de la intersección a elegir
+ /// El vector que representa el punto en el que se unen las dos barras.
+ /// Si las barras no intersecan en ningún punto, lanzará una excepción.
+ /// Si las barras intersecan pero no se encuentra la intersección especificada, lanzará una excepción.
+ public static Vector2 GetIntersection(Rod A, Rod B, int solution = -1)
+ {
+ Vector2[] intersects = CosasQueNoSeExplicanEnMatesDePrimero.CalculateCircleIntersections(
+ A.StartPosition,
+ B.StartPosition,
+ A.Length,
+ B.Length);
+
+ return (intersects.Length == 0) ? throw new RodsDoNotIntersectException("No existe conexión posible entre estas dos barras. Pruebe a darles la vuelta.") :
+ (intersects.Length == 1 || solution < 0) ? intersects[0] :
+ (intersects.Length > solution) ? intersects[solution] :
+ throw new IntersectionOutOfRangeException("La intersección especificada no existe. Pruebe con las soluciones 0 y 1");
+ }
+
+ ///
+ /// Calcula la diferencia entre dos vectores
+ ///
+ /// Vector final
+ /// Vector inicial
+ /// Vector final - Vector inicial
+ public static Vector2 Delta(Vector2 A, Vector2 B) => A - B;
+
+
+ ///
+ /// Calcula para cada elemento el ángulo de la intersección de dos vectores a su posición respecto el 0 en el primer cuadrante.
+ ///
+ /// Vector 1
+ /// Vector 2
+ /// Devuelve los angulos de cada eje a la intersección
+ ///
+ public static (float, float) GetIntersectionAlphas(Rod A, Rod B, int solution = -1)
+ {
+ (float, float) result = new();
+
+ // Calcular las intersecciones y los vectores de
+ // incremento entre el eje de la barra y su unión.
+ Vector2
+ I = GetIntersection(A, B, solution),
+ DeltaA = Delta(I, A.StartPosition),
+ DeltaB = Delta(I, B.StartPosition);
+
+ // Obtener los ángulos mediante la inversa del coseno
+ result.Item1 = MathF.Acos(DeltaA.X / DeltaA.Length());
+ result.Item2 = MathF.Acos(DeltaB.X / DeltaB.Length());
+ // Voltear verticalmente según la dirección vertical
+ // del vector incremento
+ if (DeltaA.Y < 0) result.Item1 *= -1.0f;
+ if (DeltaB.Y < 0) result.Item2 *= -1.0f;
+
+ return result;
+ }
+
+
+ [Serializable]
+ public class RodsDoNotIntersectException : Exception
+ {
+ public RodsDoNotIntersectException() { }
+ public RodsDoNotIntersectException(string message) : base(message) { }
+ public RodsDoNotIntersectException(string message, Exception inner) : base(message, inner) { }
+ protected RodsDoNotIntersectException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+
+ [Serializable]
+ public class IntersectionOutOfRangeException : Exception
+ {
+ public IntersectionOutOfRangeException() { }
+ public IntersectionOutOfRangeException(string message) : base(message) { }
+ public IntersectionOutOfRangeException(string message, Exception inner) : base(message, inner) { }
+ protected IntersectionOutOfRangeException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ }
+}
\ No newline at end of file