gear mesh: fix angle math

This commit is contained in:
jaseg 2024-08-13 13:38:56 +02:00
parent f3b554dc14
commit e238fb929c

View file

@ -251,6 +251,8 @@ def cli(out_svg_1, out_svg_2, out_svg_3, radius, num_meshes, mesh_width, mesh_th
x = (offset**2 - r2**2 + r1**2) / (2*offset)
a1 = math.asin(chord/(2*r1))
a2 = math.asin(chord/(2*r2))
if offset > x:
a2 = math.pi - a2
c1, c2 = red(40, 70), blue(40, 70)
center_1, center_2 = (0, 0), (offset, 0)
@ -259,8 +261,7 @@ def cli(out_svg_1, out_svg_2, out_svg_3, radius, num_meshes, mesh_width, mesh_th
tags.append(circle(center_2, r2, c2))
dim_tags += dimension((x, chord/2), (x, -chord/2), h=offset/2+5)
tags += angular_dimension(center_1, a1, -a1, large_arc=False)
off = math.pi if x < offset else 0
tags += angular_dimension(center_2, off + a2, -(off + a2), large_arc=False)
tags += angular_dimension(center_2, a2, -a2, large_arc=False)
tags.append(Tag('path', fill='none', stroke_width=0.2, stroke=c1, d=f'M {x} {chord/2} L 0 0 L {x} {-chord/2}'))
tags.append(Tag('path', fill='none', stroke_width=0.2, stroke=c2, d=f'M {x} {chord/2} L {offset} 0 L {x} {-chord/2}'))
@ -349,17 +350,6 @@ def cli(out_svg_1, out_svg_2, out_svg_3, radius, num_meshes, mesh_width, mesh_th
plots.append(list(plot_angles(angles_1, c1, 'url(#hatch_1)', title='Mesh 1')))
plots.append(list(plot_angles(angles_2, c2, 'url(#hatch_2)', title='Mesh 2')))
plots.append([
*plot_angles(shift_angles(angles_1, a1), c1, 'url(#hatch_1)', title='First intersection'),
*plot_angles(shift_angles(angles_2, -a2 if counterrotation else a2), c2, 'url(#hatch_2)', axes=False),
])
plots.append([
*plot_angles(shift_angles(angles_1, -a1), c1, 'url(#hatch_1)', title='Second intersection'),
Tag('g', [*plot_angles(shift_angles(angles_2, a2 if counterrotation else -a2), c2, 'url(#hatch_2)', axes=False)],
style='mix-blend-mode:screen'),
])
def collide_schedules(sch_a, sch_b):
boundaries = []
for a1, a2 in sch_a:
@ -407,13 +397,19 @@ def cli(out_svg_1, out_svg_2, out_svg_3, radius, num_meshes, mesh_width, mesh_th
if rd == 2:
yield prev, boundaries[0][0]
collided = list(collide_schedules(angles_1, angles_2))
print(f'Shifting by {math.degrees(a1):.2f}° and {math.degrees(a2):.2f}°')
angles_1_intersection_1 = shift_angles(angles_1, -a1)
angles_1_intersection_2 = shift_angles(angles_1, a1)
angles_2_intersection_1 = shift_angles(angles_2, -a2)
angles_2_intersection_2 = shift_angles(angles_2, a2)
collided_1 = list(collide_schedules(angles_1_intersection_1, angles_2_intersection_1))
collided_2 = list(collide_schedules(angles_1_intersection_2, angles_2_intersection_2))
best_solution = None
def plot_centers(collided):
nonlocal best_solution
widths = sorted(((end-start)%tau, start, end) for start, end in collided)
widths = sorted((((end-start)%tau, start, end) for start, end in collided), reverse=True)
if collided:
print('Best phases:')
@ -432,35 +428,26 @@ def cli(out_svg_1, out_svg_2, out_svg_3, radius, num_meshes, mesh_width, mesh_th
print(' === One-sided schedule === ')
plots.append([
*plot_angles(collided, 'black', 'url(#hatch_b)', title='Valid shifts for first intersection'),
*plot_centers(collided)
*plot_angles(collided_1, 'black', 'url(#hatch_b)', title='Valid shifts for first intersection'),
*plot_centers(collided_1)
])
print()
print(' === Two-sided schedule === ')
if counterrotation:
angle_delta = 2*a1 + 2*a2
else:
angle_delta = 2*a1 - 2*a2
intersected = list(intersect_schedules(collided, shift_angles(collided, angle_delta)))
intersected = list(intersect_schedules(collided_1, collided_2))
plots.append([
*plot_angles(intersected, 'black', 'url(#hatch_b)', title='Valid shifts for both intersections'),
*plot_centers(intersected)
])
pitch = 20
for i, children in enumerate(plots):
tags.append(Tag('g', children, transform=f'translate(0 {(i + .2)*pitch})'))
out_svg_2.write_text(str(Tag.setup_svg(tags + dim_tags, bounds=((0, 0), (100, (i+.8)*pitch)), margin=3)))
tags2 = tags
tags = []
tags.append(Tag('defs', defs))
dim_tags = []
for cx, cy, r, th, sched, stroke, fill in [
( 0, 0, r1, th1, shift_angles(angles_1, a1), c1, 'url(#hatch_1)'),
(offset, 0, r2, th2, shift_angles(angles_2, math.pi - a2 - best_solution), c2, 'url(#hatch_2)')]:
( 0, 0, r1, th1, angles_1, c1, 'url(#hatch_1)'),
(offset, 0, r2, th2, shift_angles(angles_2, best_solution), c2, 'url(#hatch_2)')]:
max_a = max((a2 - a1) % tau for a1, a2 in sched)
max_w = math.tan(max_a) * (r-th/2)
@ -482,7 +469,25 @@ def cli(out_svg_1, out_svg_2, out_svg_3, radius, num_meshes, mesh_width, mesh_th
group.append(Tag('animateTransform', attributeName='transform', attributeType='XML', type='rotate',
_from=f'360 {cx} {cy}', to=f'0 {cx} {cy}', dur='10s', repeatCount='indefinite'))
tags.append(Tag('g', group))
print(math.degrees(best_solution))
print(f'Phase of best solution: {math.degrees(best_solution):.2f}°')
plots.append([
*plot_angles(angles_1_intersection_1, c1, 'url(#hatch_1)', title='First intersection'),
*plot_angles(shift_angles(angles_2_intersection_1, best_solution), c2, 'url(#hatch_2)', axes=False),
])
plots.append([
*plot_angles(angles_1_intersection_2, c1, 'url(#hatch_1)', title='Second intersection'),
Tag('g', [*plot_angles(shift_angles(angles_2_intersection_2, best_solution), c2, 'url(#hatch_2)', axes=False)],
style='mix-blend-mode:screen'),
])
pitch = 20
for i, children in enumerate(plots):
tags2.append(Tag('g', children, transform=f'translate(0 {(i + .2)*pitch})'))
out_svg_2.write_text(str(Tag.setup_svg(tags2 + dim_tags, bounds=((0, 0), (100, (i+.8)*pitch)), margin=3)))
out_svg_3.write_text(str(Tag.setup_svg(tags + dim_tags, bounds=(
(min(-r1, -r2+offset), min(-r1, -r2)),