Tables?
Maybe tables would be a useful way to express a linkage.
I’m thinking about a tabular representation. It’s not working out. So far, the best I have is this:
def test_table(self):
p = 'p'
n = 'n'
o = 'o'
table = [
{ p: '--', n: 'fp', o: FixedPoint(position=vector(2, 1))},
{ p: '--', n: 'wh', o: Wheel()},
{ p: '--', n: 'c1', o: Crank(radius=1)},
{ p: '--', n: 'sr', o: SideRod(length=7)},
{ p: 'c1', n: 'cr', o: ConRod(length=5, piston_angle=135)},
{ p: '--', n: 'pi', o: Piston(length=2, angle=135)},
]
The table elements are parent, name, and object, shorthanded for convenience in typing. In what’s above the user could specify each parent but -- is shorthand meaning to use the preceding component. You only need to specify a parent when it is not your immediate predecessor in the list.
What if we didn’t name things that didn’t need names?
def test_table_sparse_names(self):
p = 'p'
n = 'n'
o = 'o'
table = [
{ p: '--', n: '--', o: FixedPoint(position=vector(2, 1))},
{ p: '--', n: '--', o: Wheel()},
{ p: '--', n: 'c1', o: Crank(radius=1)},
{ p: '--', n: '--', o: SideRod(length=7)},
{ p: 'c1', n: '--', o: ConRod(length=5, piston_angle=135)},
{ p: '--', n: '--', o: Piston(length=2, angle=135)},
]
Maybe that’s better. I’m not sure. What else?
Clearly the little dictionaries could be replaced by an object creation of our own if we wished, but it wouldn’t be much better. Perhaps like this:
def test_table_object(self):
p = 'p'
n = 'n'
o = 'o'
table = [
E( '--', '--', FixedPoint(position=vector(2, 1))),
E( '--', '--', Wheel()),
E( '--', 'c1', Crank(radius=1)),
E( '--', '--', SideRod(length=7)),
E( 'c1', '--', ConRod(length=5, piston_angle=135)),
E( '--', '--', Piston(length=2, angle=135)),
]
E is just a short class name to keep the notation clean. Stands for Element.
Recall that early on in this enterprise, we had an optional parent parameter in all the constructors. The main reason for getting rid of that was that we did not want the temptation of reaching back generations and ripping arbitrary facts out of ancestor objects. But perhaps a name and parent would be optional in E, maybe like this:
def test_table_object_default(self):
p = 'p'
n = 'n'
o = 'o'
table = [
E( o=FixedPoint(position=vector(2, 1))),
E( o=Wheel()),
E( o=Crank(radius=1), name='c1'),
E( o=SideRod(length=7)),
E( o=ConRod(length=5, piston_angle=135), parent='c1'),
E( o=Piston(length=2, angle=135)),
]
Not too awful, but the name and parent aren’t very obvious. Maybe we could put them first:
def test_table_object_default(self):
p = 'p'
n = 'n'
o = 'o'
table = [
E( o=FixedPoint(position=vector(2, 1))),
E( o=Wheel()),
E( name='c1', o=Crank(radius=1)),
E( o=SideRod(length=7)),
E( parent='c1', o=ConRod(length=5, piston_angle=135)),
E( o=Piston(length=2, angle=135)),
]
I’m not sure that any of these are better than this one, our current scheme in actual use:
linkage = Linkage()
linkage.add(
FixedPoint(base),
wheel := Wheel(),
crank := Crank(radius=radius, lead_degrees=lead_angle),
ConRod(length=rod_length, piston_angle=tilt_angle),
Piston(length=piston_length, angle=tilt_angle)
)
linkage.parent = crank
linkage.add(SideRod(length=7))
linkage.parent = wheel
linkage.add(
Crank(radius=0.5),
ArcRod(
length=5,
target_position=bell_pos,
target_radius=0.55,
target_angle=135)
)
I continue to look for better ideas. But mostly, we’d best get back to checking whether our ArcRod is fully operational, and then move on to additional components.
See you then!