# Implementation of module {timing_path}
# Last edited on 2021-09-30 12:29:31 by stolfi

import timing_path
import move
import move_parms
import path
import rn
from math import sqrt, sin, cos, floor, ceil, inf, nan, pi
import sys

def straight(pt, n, d, ang, jmp, udnoz, mp_trace, mp_jump):
  mp = mp_jump if jmp else mp_trace
  mvs = []
  pant = pt
  u = rn.rotate2((d,0), ang*pi/180) # "Horizontal" direction.
  for k in range(n):
    if jmp and udnoz:
      # Insert a zero-length trace:
      trk = move.make(pant, pant, mp_trace)
      mvs.append(trk)
    pk = rn.add(pant, u)
    mvk = move.make(pant, pk, mp)
    mvs.append(mvk)
    pant = pk
  ph = path.from_moves(mvs)
  return ph
  # ----------------------------------------------------------------------

def zigzag(pt, n, d, ang, jmp, udnoz, mp_trace, mp_jump):
  mp = mp_jump if jmp else mp_trace
  u = rn.rotate2((d,0), (ang+45)*pi/180) # "NE" direction.
  v = (+u[1],-u[0]) # "SE" direction.
  mvs = []
  pant = pt
  for k in range(n):
    if jmp and udnoz:
      # Insert a zero-length trace:
      trk = move.make(pant, pant, mp_trace)
      mvs.append(trk)
    if (k % 2) == 0:
      pk = rn.add(pant, u)
    else:
      pk = rn.add(pant, v)
    mvk = move.make(pant, pk, mp)
    mvs.append(mvk)
    pant = pk
  ph = path.from_moves(mvs)
  return ph
  # ----------------------------------------------------------------------

def greek(pt, n, xd, yd, ang, jmp, udnoz, mp_trace, mp_jump):
  mp = mp_jump if jmp else mp_trace
  u = rn.rotate2((xd,0), ang*pi/180) # "Horizontal" direction.
  v = rn.rotate2((0,yd), ang*pi/180) # "Vertical" direction.
  ysgn = +1
  mvs = []
  pant = pt
  for k in range(n):
    if jmp and udnoz:
      # Insert a zero-length trace:
      trk = move.make(pant, pant, mp_trace)
      mvs.append(trk)
    if (k % 2) == 0:
      pk = rn.add(pant, u)
    else:
      pk = rn.mix(1.0, pant, ysgn, v)
      ysgn = -ysgn
    mvk = move.make(pant, pk, mp)
    mvs.append(mvk)
    pant = pk
  ph = path.from_moves(mvs)
  return ph
  # ----------------------------------------------------------------------

def starry(ctr, n, d, bend, jmp, udnoz, mp_trace, mp_jump):
  mp = mp_jump if jmp else mp_trace
  beta = bend*pi/180
  theta = pi/n                    # Angle subtended by one move as seen from center.
  alpha = ((1 - 1/n)*pi - beta)/2 # Half-angle of a spike.
  # sys.stderr.write("theta = %.3f alpha = %.3f\n" % (theta*180/pi,alpha*180/pi))
  Rin = d * sin(alpha)/sin(theta)     # Inradius.
  Rex = Rin*cos(theta) + d*cos(alpha) # Extradius
  sys.stderr.write("Rin = %.3f Rex = %.3f\n" % (Rin,Rex))
  ang = 0
  mvs = []
  pant = rn.add(ctr, (Rex, 0))
  for k in range(2*n):
    ang = ang + theta
    if jmp and udnoz:
      # Insert a zero-length trace:
      trk = move.make(pant, pant, mp_trace)
      mvs.append(trk)
    if (k % 2) == 1:
      R = Rex
    else:
      R = Rin
    pk = rn.add(ctr, (R*cos(ang), R*sin(ang)))
    assert abs(rn.dist(pant, pk)/d - 1) < 1.0e-6
    mvk = move.make(pant, pk, mp)
    mvs.append(mvk)
    pant = pk
  ph = path.from_moves(mvs)
  return ph
  # ----------------------------------------------------------------------

def stair(pt, m, nx, xd, ny, yd, ang, jmp, udnoz, mp_trace, mp_jump):
  if m == 0:
    ph = path.empty(pt)
  else:
    ns = 2*m # Number of straight elements.
    phs = [] # Straight paths to be concatenated.
    pant = pt
    for k in range(ns):
      if (k % 2) == 0:
        dk = xd; nk = nx; ak = ang;
      else:
        dk = yd; nk = ny; ak = ang+90; nk = ny
      phk = straight(pant, nk, dk, ak, jmp, udnoz, mp_trace, mp_jump)
      phs.append(phk)
      pant = path.pfin(phk)
    use_links = False
    ph = path.concat(phs, use_links, None)
  return ph
  # ----------------------------------------------------------------------
def full(nx, xdist, ny, ydist, ang, jmp, udnoz, totsz, mp_trace, mp_jump):
  assert False, "not implemented yet"

