
# confocalEl.py
# Andrew Davison, ad@coe.psu.ac.th, Oct. 2025

"""
Confocal Conics: Ellipse and Hyperbolas

Draw a single ellipse and multiple hyperbolas all with the 
same foci (+-c, 0). The hyperbolas all intersect the 
ellipse at 90 degs.

The plotting functions utilize 
elliptical coordinates (mu, nu). While drawing an ellipse,
mu is kept fixed and nu is varied. For a hyperbola, nu is
kept fixed and mu varies.
"""

import matplotlib.pyplot as plt
import math


def ellipsePlot(c, mu):
  # parametric equ using elliptical coords (mu, nu)
  # Fix mu -> ellipse with foci (+-c, 0)
  xs = []
  ys = []
  for i in range(361):
    nu = 2 * math.pi * i / 360   # vary nu to get coords
    x = c * math.cosh(mu) * math.cos(nu)
    y = c * math.sinh(mu) * math.sin(nu)
    xs.append(x)
    ys.append(y)
  return xs, ys


def drawHyperbola(c, nu):
  # parametric equ using elliptical coords (mu, nu)
  # Fix nu -> hyperbola with foci (+-c, 0)
  xs = []
  ys = []
  for k in range(1, 800):
    mu = 0.01 + k * 0.01   # vary mu to get coords
    x = c * math.cosh(mu) * math.cos(nu)
    y = c * math.sinh(mu) * math.sin(nu)
    if abs(x) > 10:  # stop if x goes beyond plot range
      break
    xs.append(x)
    ys.append(y)
  return xs, ys


# ---------------------------------
c = 2.0          # focal distance
muEllipse = 1.5  # controls ellipse size


xs, ys = ellipsePlot(c, muEllipse)
plt.plot(xs, ys, 'b') 

# Draw hyperbolas
for j in range(0, 181, 10):
  nu = math.pi * j/180
  xs, ys = drawHyperbola(c, nu)
  # plot above and below x-axis
  plt.plot(xs, ys, 'k')
  plt.plot(xs, [-yy for yy in ys], 'k')


plt.axhline(0, color='gray', lw=0.8)
plt.axvline(0, color='gray', lw=0.8)
plt.gca().set_aspect('equal')
plt.xlim(-10, 10)
plt.ylim(-10, 10)
plt.title("Confocal Ellipse and Hyperbolas")
plt.show()
