
# sagCatParab.py
# Andrew Davison, Nov 2025, ad@coe.psu.ac.th

'''
Plot a catenary and parabola which hang from the same points and
have the same vertex (i.e. have the same sag). Also draw a curve
showing the difference between their y-values.

The plot includes a slider which varies the sag value (d) to show
how the curves change.
'''

import math
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
from catSolver import getCatA


def catenary(x, a):
  # Vertex (lowest pt) is at x=0
  return a * math.cosh(x / a) - a

def parabola(x, d, H):
  return d * ((2*x)/H)**2


def update(val):
  global a, d
  d = slider_h.val
  a = getCatA(H=H, d=d)
  # print("d", d, "approx a:", a)

  ysCat = [catenary(x, a) for x in xs]
  ysPara = [parabola(x, d, H) for x in xs]
  diffs = [y1-y2 for y1, y2 in zip(ysCat, ysPara)]
  
  catLine.set_ydata(ysCat)
  paraLine.set_ydata(ysPara)
  diffLine.set_ydata(diffs)
  ax.legend(title=f"Sag:{d:.1f}, a:{a:.2f}", alignment='left')  
     # Update legend
  # fig.canvas.draw_idle()



# Initial catenary values
H = 40  # width or span; does not change 
d = 40  # height or sag
dInit = d
a = getCatA(H=H, d=d)
# print("d", d, "approx a:", a)


fig, ax = plt.subplots(figsize=(7, 7))
plt.subplots_adjust(bottom=0.25)  # Leave space for sliders

xs = [i*0.1 for i in range(int(-H*10/2), int(H*10/2+1))]  
ysCat = [catenary(x, a) for x in xs]
ysPara = [parabola(x, d, H) for x in xs]
diffs = [y1 - y2 for y1, y2 in zip(ysCat, ysPara)]

catLine, = ax.plot(xs, ysCat, 
      label=f'Catenary: $y = a\cosh(x/a)-a$', color='blue')
paraLine, = ax.plot(xs, ysPara, 
      label=f'Parabola: $y = d (2x/H)^2$', color='orange')
diffLine, = ax.plot(xs, diffs, 
      label='Difference: Catenary - Parabola', color='green', linestyle='--')

ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_yticks(range(-10, 61, 5))
ax.set_title('Sagging Catenary and Parabola')
ax.axhline(0, color='black', lw=0.8, linestyle=':')
ax.legend(title=f"Sag:{d:.1f}, a:{a:.2f}", alignment='left')

# Add slider
ax_h = plt.axes([0.2, 0.1, 0.65, 0.03], facecolor='lightgrey')  
slider_h = Slider(ax_h, 'Sag d', 
                       valmin=10, valmax=dInit+20,
                       valinit=dInit, valstep=1)
ax_h.add_artist(ax_h.xaxis)
ax_h.set_xticks(range(10,dInit+21,5))

slider_h.on_changed(update)

plt.show()
