elipse de transición en una leva
He diseñado un mecanismo para llevar el teléfono en la bicicleta, en el que una pieza gira alrededor de un eje y abraza al tubo del manillar. En la imagen, las piezas de color ladrillo giran alrededor del eje cian, y al final del recorrido el círculo resaltado del lado izquierdo encaja en un alojamiento cilíndrico que tiene la pieza fija superior.
Si nos fijamos en la imagen lateral, durante el giro alrededor de (0, 0) es necesario que el resalte del extremo izquierdo de la pieza inferior entre en contacto con la pieza amarilla en el punto (p, q) de forma natural, sin tensión. Conforme sigue girando, la pieza se deforma y va aumentando su radio de giro. Al rebasar el borde de la hendidura cilíndrica en (r, s) recupera súbitamente su forma haciendo un ¡clac! al caer en (t, u).
Geométricamente, los puntos (p, q) y (t, u) pertenecen a un círculo con origen en (0, 0). El punto (r, s) está más alejado, por lo que el arco que va de (p, q) a (r, s) forma parte de una elipse que constituye el flanco de subida de una leva, y de ahí el título de esta página.
Si definimos la elipse con sus semiejes A y B, cualquier punto (x, y) cumplirá x²/A² + y²/B² = 1. Por lo tanto, en el caso que nos ocupa tendremos un sistema de dos ecuaciones con dos incógnitas:
p²/A² + q²/B² = 1
r²/A² + s²/B² = 1
Despejando A y B tenemos:
B = raiz( (p²s² - r²q²) / (p² - r²) )
A = raiz( r² / (1 - s²/B²) )
He preparado un ejemplo muy tontorrón: en el círculo de un reloj pondré una leva desde la 1 a las 11. El resultado está en la imagen de al lado, y el código a continuación:
$fs=1;
$fa=1;
X=0;
Y=1;
// considerando que el ángulo 0 está a las 3 en un reloj, quiero una leva que empiece a la 1
// vaya incrementando la altura hasta las 11 en sentido antihorario hasta 10mm
radio_principal = 40; // radio del círculo base
excentricidad = 10; // cuánto se aleja la leva desde el círculo base
angulo_inicio = 60; // ángulo de la 1
angulo_final = 120; // ángulo de las 11
espesor = 5; // altura, por hacerlo en 3D
if ((abs(angulo_final - angulo_inicio) < 90) && excentricidad < radio_principal) {
// calcularé la elipse con los semiejes A y B paralelos a X e Y respectivamente, y luego la giro
inicio = [radio_principal, 0];
final = [(radio_principal + excentricidad) * cos(angulo_final - angulo_inicio)
, (radio_principal + excentricidad) * sin(angulo_final - angulo_inicio)];
B = sqrt( (pow(inicio[X] * final[Y], 2) - pow(inicio[Y] * final[X], 2)) / (pow(inicio[X], 2) - pow(final[X], 2)) );
A = sqrt( pow(final[X], 2) / (1 - pow(final[Y]/B, 2)) );
linear_extrude(espesor)
difference() {
union() {
circle(radio_principal);
rotate([0, 0, angulo_inicio])
intersection() { // seleccionar sólo el arco de elipse que me interesa
resize([A*2, 0])
circle(B);
square(B);
rotate([0, 0, angulo_final - angulo_inicio])
translate([0, -B])
square(B);
}
}
// ya puestos, pinto las horas
for(hora= [1:12]) {
angulo = 90 - hora * 30;
rotate([0, 0, angulo])
translate([30, 0])
rotate([0, 0, -angulo])
text(str(hora), 8, halign="center", valign="center");
}
}
}
else // para levas >90º es preferible fundir con un círculo o elipse que no sea concéntrico, o mejor usar una clotoide
echo("PROBLEMA INCONGRUENTE");