escrito programa principal

This commit is contained in:
alexb737
2022-10-06 12:01:09 +02:00
parent 8a1a35d523
commit 9e059203ec

176
Q01-Cálculos/Program.cs Normal file
View File

@ -0,0 +1,176 @@
using System.Numerics;
using System.Runtime.Intrinsics;
using OpenTK;
using OpenTK.Windowing.Desktop;
using Q01_Cálculos;
// Convenio de signos:
// X: Eje horizontal de la pantalla (izquierda a derecha positivo)
// Z: Eje vertical de la pantalla (abajo a arriba positivo)
// Y: Eje perpendicular a la pantalla (saliente positivo)
// Definimos una palanca en punto neutro, utilizando las medidas que
// hemos tomado para definir el volumen, la masa y el centro de gravedad
// de los componentes del ensamblaje que componen la palanca.
// La masa la estimaremos como el volumen del componente por la densidad
// de su material.
// Creamos una instancia de la clase Assembly para unir las piezas
// Para simplificar el programa, usamos técnicas de programación orientada a objetos (OOP)
// que nos permiten crear clases que describen los componentes del sistema, y las operaciones
// que se pueden realizar con ellos. Estas son "Assembly" y "Component".
Assembly Palanca = new() { Name = "Palanca de cambio" };
// Describimos físicamente los componentes, estimando su masa a partir del
// volumen y la densidad del material, y su centro de masas en base a sólidos
// tridimensionales sencillos:
// Perimero definimos las densidades de los materiales
const float
DensAcero = 7800f, // kg/m3
DensAbs = 1110f; // kg/m3
// Aproximamos la parte superior del pomo como una esfera
float diametro_esfera = 4.5e-2f; //m
float VolPomo1 = 4 / 3 * MathF.PI * MathF.Pow(diametro_esfera / 2, 3);
Palanca.components.Add(new Component()
{
Name = "Parte Superior Pomo",
Mass = VolPomo1 * DensAbs,
CenterOfMass = new(0, -diametro_esfera / 2, 30e-2f)
});
float LongitudPalanca = 30e-2f; //m
// Aproximamos la parte inferior del pomo como un cilindro hueco por donde
// pasarán la varilla y su cubierta
float diametro_cilindro = 2.5e-2f; // m
float diametro_interno_cilindro = 1.5e-2f; // m
float altura_cilindro = 1.5e-2f; // m
float VolPomo2 = MathF.PI * (MathF.Pow(diametro_cilindro / 2, 2) - MathF.Pow(diametro_interno_cilindro / 2, 2)) * altura_cilindro;
Palanca.components.Add(new Component()
{
Name = "Base Pomo",
Mass = VolPomo2 * DensAbs,
CenterOfMass = new(0, 0, LongitudPalanca - ((diametro_esfera / 2) - (altura_cilindro / 2)))
});
// Aproximamos la cubierta de la varilla como un cilindro hueco
float DiametroExterno2 = 1.5e-2f; //m
float DiametroInterno2 = 0.8e-2f; //m
float VolPalancaExterna = MathF.PI * (MathF.Pow(DiametroExterno2 / 2, 2) - MathF.Pow(DiametroInterno2 / 2, 2)) * LongitudPalanca;
Palanca.components.Add(new Component()
{
Name = "Cubierta plástica de la varilla",
Mass = VolPalancaExterna * DensAbs,
CenterOfMass = new(0, 0, LongitudPalanca / 2)
});
// Aproximamos la varilla como un cilindro macizo
float DiametroExterno1 = 1.5e-2f; //m
float VolPalancaInterna = MathF.PI * MathF.Pow(DiametroExterno1 / 2, 2) * LongitudPalanca;
Palanca.components.Add(new Component()
{
Name = "Varilla interna de la palanca",
Mass = VolPalancaInterna * DensAcero,
CenterOfMass = new(0, 0, LongitudPalanca / 2)
});
// Definimos las posicíones que hemos medido en el plano como tuplas (plano X Y)
(float, float) primera = (-6.5e-2f, -4.5e-2f);
(float, float) tercera = (0, -4.5e-2f);
(float, float) quinta = (4.5e-2f, -4.5e-2f);
(float, float) segunda = (-6.5e-2f, 10e-2f);
(float, float) cuarta = (0, 10e-2f);
(float, float) reversa = (4.5e-2f, 10e-2f);
Console.WriteLine("================================================");
Console.WriteLine("== Datos del sistema ==");
Console.WriteLine("================================================");
// Mostramos las propiedades físicas de la palanca por pantalla
Console.Write(Palanca.Summary());
// La fuerza que hace la palanca en reposo sobre la base es el peso de la palanca:
var fuerza_base = Palanca.Weight;
// Como está en reposo, no se trasalda, de modo que el sumatorio de fuerzas debe ser cero.
// Por ello, la reacción será el vector nulo menos la fuerza sobre la base (el peso de la palanca).
var reaccion_base = Vector3.Zero - fuerza_base;
// El momento sobre la base será el producto vectorial de la posición del centro de masas
// por el peso de la palanca.
var momento_base = Vector3.Cross(Palanca.CenterOfMass, Palanca.Weight);
// Y como tampoco rota, significa que el sumatorio de momentos se cancela.
// Por ello, el momento de reacción que hace la base sobre la palanca será el vector nulo menos
// el momento que hace la palanca sobre la base.
var momento_reaccion = Vector3.Zero - momento_base;
Console.WriteLine();
Console.WriteLine("===============================================================================");
Console.WriteLine("== Cálculos de fuerzas y momentos : Escalares / <x,y,z> ==");
Console.WriteLine("===============================================================================");
Console.WriteLine($"Fuerza que ejerce la barra sobre la base : {fuerza_base} N");
Console.WriteLine($"Fuerza resistente que hace la base sobre la palanca : {reaccion_base} N");
Console.WriteLine($"Momento que hace la barra sobre la base : {momento_base * 100} N·cm");
Console.WriteLine($"Momento que hace la base sobre la palanca : {momento_reaccion * 100} N·cm");
Console.WriteLine();
Console.WriteLine("Momentos que hace la palanca cuando engrana una marcha:");
Console.WriteLine($"Centro de masa 1a : {CentroDeMasasRotado(Palanca, LongitudPalanca, primera)}");
Console.WriteLine($"Centro de masa 2a : {CentroDeMasasRotado(Palanca, LongitudPalanca, segunda)}");
Console.WriteLine($"Centro de masa 3a : {CentroDeMasasRotado(Palanca, LongitudPalanca, tercera)}");
Console.WriteLine($"Centro de masa 4a : {CentroDeMasasRotado(Palanca, LongitudPalanca, cuarta)}");
Console.WriteLine($"Centro de masa 5a : {CentroDeMasasRotado(Palanca, LongitudPalanca, quinta)}");
Console.WriteLine($"Centro de masa Reversa : {CentroDeMasasRotado(Palanca, LongitudPalanca, reversa)}");
Console.WriteLine();
//Simulation simulación = new Simulation(new GameWindowSettings() { UpdateFrequency = 20, RenderFrequency = 20 }, new NativeWindowSettings() { Size = new OpenTK.Mathematics.Vector2i(500, 500) });
//simulación.Run();
// Obtiene el vector de longitud determinada que corta los planos X e Y por
// los puntos especificados
Vector3 Position(float X, float Y, float vectorLength)
{
// Calculamos la longitud del segmento de la base de nuestro vector resultado como
// la hipotenusa del triangulo de catetos X,Y (usando Pitágoras):
float _base = MathF.Sqrt(MathF.Pow(X, 2) + MathF.Pow(Y, 2));
// Calculamos la componente Z como el cateto restante del triangulo cuya hipotenusa
// es el módulo de nuestro vector, con la base calculada en el paso anterior.
float _z = MathF.Sqrt(MathF.Pow(vectorLength, 2) - MathF.Pow(_base, 2));
// Construimos y devolvemos un vector con el valor Z hallado.
return new Vector3(X, Y, _z);
}
// Obtiene el vector que representa el centro de masas de la palanca cuando se mueve en el plano XY
// hacia la posición de la marcha.
Vector3 CentroDeMasasRotado(IRigidBody componente, float longitud, (float, float) posicionesMarcha)
{
Vector3 rcm_rotado;
// Calculamos el vector de la posición de la palanca con la marcha metida.
var posiciónDestino = Position(posicionesMarcha.Item1, posicionesMarcha.Item2, longitud);
// Calculamos el eje de la rotación que se debe producir para que el vector de posición
// realice el movimiento para engranar la marcha.
// El eje de rotación lo podemos definir como el vector unitario perpendicular al vector rotado
// respecto al vector original. Para ello podemos usar el producto vectorial (producto en cruz)
// normalizado, para convertirlo en vector unitario.
var ejeDeRotación = Vector3.Normalize(Vector3.Cross(componente.CenterOfMass, posiciónDestino));
// El siguiente caso es determinar el ángulo que rotó el vector para orientarse a la posición
// final. Para ello usamos una formula derivada de la definición de producto escalar.
// El producti escalar se puede calcular como = a * b * el coseno del angulo que forman, de modo que:
var ángulo = MathF.Acos(
Vector3.Dot(componente.CenterOfMass, posiciónDestino) /
(componente.CenterOfMass.Length() * posiciónDestino.Length()));
// A continuación, crearemos un quaternión a partir del eje y el ángulo de rotación hallados:
Quaternion rotación = Quaternion.CreateFromAxisAngle(ejeDeRotación, ángulo);
// Y finalmente aplicamos la transformación vectorial del centro de masas para aplicar la misma
// rotación que ha sufrido el vector que representa la orientación de la palanca de cambio.
rcm_rotado = Vector3.Transform(componente.CenterOfMass, rotación);
// Devolvemos el centro de masas rotado como resultado
return rcm_rotado;
}