Fivebar MechanismΒΆ
[1]:
import numpy as np
from kingdon import Algebra
import ipywidgets
[2]:
alg = Algebra(2, 0, 1)
[3]:
def point(x, y): return alg.vector(e0=1, e1=x, e2=y).dual()
def plane(a, b, c): return alg.vector(e1=a, e2=b, e0=c)
def exp_np(x):
xsq = (x|x).grade(0)
if not xsq:
return 1 + x
lsqrt = (-xsq.e)**0.5
return x * np.sinc(lsqrt / np.pi) + np.cos(lsqrt)
def translator(line, dist):
e0 = line.algebra.blades['e0']
return 1 + 0.5 * dist * (e0 * line.normalized() * e0.dual())
def elbow(point1, point2, r1, r2, alternative=False):
"""
Given two points and two radii, give the intersection point of the
circles centered on those points with those radii.
"""
u = point1 & point2
v = u | point1
usq_inv = 1 / (u|u).e
s = 0.5 * (usq_inv * (r1**2 - r2**2) + 1)
t = ((usq_inv * r1**2) - s**2)**0.5
point2perp = (1 - point1) / 2**0.5 >> point2
if alternative:
return point1 + (point2-point1) * s - (point2perp-point1) * t
return point1 + (point2-point1) * s + (point2perp-point1) * t
def fivebar(t, A, B, ac, bd, cd, de, theta_D, pol_A, full_output=False, exp=exp_np):
# Create C by translating A up, and then rotating it by the desired angle.
tr_ac = translator(A & B, ac)
# tr_ac = exp(0.5 * ac * alg.blades['e01'])
if isinstance(pol_A, (tuple, list)):
theta_At = sum(t**i * coeff for i, coeff in enumerate(reversed(pol_A)))
else:
theta_At = pol_A
M_A = exp(- 0.5 * A * theta_At)
C = (M_A * tr_ac) >> A
# Create D as the elbow of C and B.
D = elbow(B, C, bd, cd)
# Create E by translating D up, and then rotating it by the desired angle.
tr_de = translator(C & D, de)
# tr_de = exp(0.5 * de * alg.blades['e01'])
M_D = exp(- 0.5 * theta_D * D)
E = (M_D * tr_de) >> D
if full_output:
return C, D, E
return E
[4]:
from timeit import default_timer
from functools import partial
DistSlider = partial(ipywidgets.FloatSlider, min=-10, max=10, step=0.01, readout=True, readout_format='.2f')
ac_widget = DistSlider(value=4.329777002067039)
bd_widget = DistSlider(value=-6.418389614876762)
usecase = [point(1.5, 3.0), point(5.0, 5.0), point(8.5, 2.0)]
best = [
7.522375791897677,
-1.2297104295438015,
1.4883454465783046,
9.65978858247454,
4.329777002067039,
-6.418389614876762,
12.91788027878568,
10.223852704675853,
-3.393426372984221,
0.9098149166712446,
-3.763919738437536,
-5.266926540202572
]
Ax, Ay, Bx, By, ac, bd, cd, de, theta_D, tA1, tA2, tA3 = best
# Anchor points
A = point(Ax, Ay);
B = point(Bx, By);
endpoints = []
def graph_func():
t = default_timer() / 1000
ac = ac_widget.value
bd = bd_widget.value
C, D, E = fivebar(t, A, B, ac, bd, cd, de, theta_D, [1, 0, 0], full_output=True)
endpoints.append(E)
if len(endpoints) > 50:
endpoints.pop(0)
return [
# usecase
*usecase,
# Anchor points
0xff0000, A, 'A', B, 'B',
0x000000, [A, C], [B, D], [C, D], [D, E],
# Moving points
0x00ff00,
C, 'C', D, 'D',
# end point and previous endpoints
0xff00ff, *endpoints,
0x0000ff,
E, 'E',
]
graph = alg.graph(
graph_func,
scale=0.1, animate=True,
)
# graph
ipywidgets.VBox([ac_widget, bd_widget, graph])
[4]:
[ ]: