#! /usr/bin/python3
# Test program for module {hacks}
# Last edited on 2021-10-01 15:07:15 by stolfi

import hacks
import color

import rn

import pyx
import sys
from math import sqrt, sin, cos, floor, ceil, inf, nan, pi

def test_adjust_dash_pattern():
  sys.stderr.write("--- testing {adjust_dash_pattern} ---\n")
  rlen = 0.3
  rgap = 0.2
  sys.stderr.write("ideal ratios: rlen = %.6f rgap = %.6f\n" % (rlen, rgap))
  D1 = tuple( 0.1*k for k in range(11) )
  D2 = tuple( 10+0.1*k for k in range(31) )
  for rdist in D1 + D2:
    dashed, dashpat = hacks.adjust_dash_pattern(rdist, rlen, rgap)
    sys.stderr.write("rdist = %.6f" % rdist)
    if dashed:
      assert type(dashpat) is list or type(dashpat) is tuple
      assert len(dashpat) == 2
      rlen1, rgap1 = dashpat
      sys.stderr.write(" dashed [ %.6f, %.6f]" % (rlen1, rgap1))
      n = int(floor((rdist-rlen1)/(rlen1+rgap1) + 0.5)) # Number of gaps.
      rdist1 = n*(rlen1+rgap1) + rlen1
      sys.stderr.write(" n = %d rdist1 = %.6f\n" % (n, rdist1))
      assert abs(rdist - rdist1) < 1.0e-8*rdist
    else:
      assert dashpat == None
      sys.stderr.write(" solid\n")
  return
  # ----------------------------------------------------------------------
  
def test_basic_plot():
  sys.stderr.write("--- testing {pyx,round_box,plot_line,plot_box,plot_frame,plot_grid} ---\n")
  tag = "basic_plot"

  scale = 1.0
  sys.stderr.write("scale = %8.4f\n" % scale)
  pyx.unit.set(uscale=scale, wscale=scale, vscale=scale)
  c = pyx.canvas.canvas()

  tan = pyx.color.rgb(0.800, 0.700, 0.600)
  glo = pyx.color.rgb(0.400, 0.900, 1.000)

  # Bounding box of one drawing:
  B = ((0.5, 0.5), (7.5, 4.5))
  pbox = hacks.round_box(B, 1)
  XPstep,YPstep = rn.box_size(pbox)
  YPstep += 1

  dp = (3,1)

  # Testing {Plot_line}:
  nwd = 5 # Number of line widths including negative and zero,
  wdmax = 0.10 # Max line width.
  Xlo = B[0][0] + 1.5
  Ylo = B[0][1] + 1.5
  Xlen = 1.5 # Length of lines.
  Ytot = 1.5 # Space for the lines.
  Xstep = Xlen + 1.5     # Disp between solid and dashed.
  Ystep = Ytot/(nwd-1) # Disp between different widths.
  Y = Ylo
  for kwd in range(nwd):
    X = Xlo
    for dashed in (False,True):
      wd = wdmax*kwd/(nwd-1)
      clr = pyx.color.rgb.blue
      p = rn.add(dp, ( X, Y ))
      q = rn.add(dp, ( X + Xlen, Y ))
      dashpat = [0.15, 0.10] if dashed else None
      hacks.plot_line(c, clr, wd, dashpat, p, q)
      X += Xstep
    Y += Ystep
  
  # Testing {plot_box}:
  BA = ((3.1,1.8), (3.9,2.2))
  clr = pyx.color.rgb.green
  hacks.plot_box(c, clr, dp, BA)

  # Testing {plot_frame}:
  wd_frame_a = 0.06
  wd_frame_b = 0.02
  hacks.plot_frame(c, pyx.color.rgb.red,   wd_frame_a, dp, pbox, +0.20)
  hacks.plot_frame(c, pyx.color.rgb.black, wd_frame_b, dp, pbox, 00.00)
  hacks.plot_frame(c, pyx.color.rgb.blue,  wd_frame_a, dp, pbox, -0.20)

  # Testing {plot_grid}:
  dp = (dp[0], dp[1] + YPstep)
  wd_grid_a = 0.01
  wd_grid_b = 0.03
  hacks.plot_grid(c, tan, wd_grid_a, True,  dp, pbox, -0.50, 0.50,0.20)
  hacks.plot_grid(c, glo, wd_grid_b, False, dp, pbox, -0.35, 1.00,1.00)

  hacks.write_plot(c, "tests/out/hacks_TST_plot_" + tag)
  return 
  # ----------------------------------------------------------------------

def test_make_canvas():
  sys.stderr.write("--- testing {make_canvas} ---\n")
  
  dp = (2, 2)
  B = ((2, 3), (5, 7))
  nx = 2
  ny = 3
  for frame in False, True:
    for grid in False, True:
      tag = "make_canvas_fr%s_gr%s" % ("FT"[frame], "FT"[grid])
      c,szx,szy = hacks.make_canvas(B, dp, frame, grid, 2, 3)
      hacks.write_plot(c, "tests/out/hacks_TST_plot_" + tag)
  return 
  # ----------------------------------------------------------------------

def test_poly_orientation():
  sys.stderr.write("--- testing {poly_orientation} ---\n")

  C = (( 3, 1), ( 3, 9), (10, 9), (10, 1), ( 3, 1))
  assert hacks.poly_orientation(C) == -1
  
  F = (( 4, 6), ( 9, 6), ( 9, 8), ( 4, 8), ( 4, 6))
  assert hacks.poly_orientation(F) == +1
  
  K = (
    ( 0, 0), ( 9, 0), ( 9, 9), ( 0, 9), 
    ( 0, 2), ( 7, 2), ( 7, 7), ( 2, 7),
    ( 2, 4), ( 5, 4), ( 5, 5), ( 3, 5),
    ( 3, 6), ( 6, 6), ( 6, 3), ( 2, 3),
    ( 2, 8), ( 8, 8), ( 8, 1), ( 0, 1),
    ( 0, 0),
  )
  assert hacks.poly_orientation(K) == +1
  return
  # ----------------------------------------------------------------------

def test_quatratic_roots():
  sys.stderr.write("--- testing {real_quadratic_roots} ---\n")

  n = 5
  for iA in range(2*n+1):
    for iB in range(2*n+1):
      for iC in range(2*n+1):
        A = (iA-n)/n
        B = (iB-n)/n
        C = (iC-n)/n
        if (A != 0):
          t0, t1 = hacks.real_quadratic_roots(A, B, C)
          for t in t0, t1:
            if t != None:
              v = A*t*t + B*t + C
              if abs(v) > 1.0e-8:
                sys.stderr.write("** error? A = %10.7f B = %10.7f C = %10.7f" % (A, B, C))
                sys.stderr.write("  t = %21.15e v = %21.15e\n" % (t,v))
  return
  # ----------------------------------------------------------------------
  
def test_choose_grid_steps():
  sys.stderr.write("--- testing {choose_grid_steps} ---\n")

  sz = 3.14
  while (sz < 314):
    gstep_big, gstep_sma = hacks.choose_grid_steps(sz)
    sys.stderr.write("  %8.3f %8.3f %8.3f\n" % (sz, gstep_big, gstep_sma))
    sz = 1.2345*sz
    
  return
  # ----------------------------------------------------------------------
  
def test_colors(nc):
  sys.stderr.write("--- testing {trace_colors,link_colors} nc = %d ---\n" % nc)

  CLRS = [ None, None ]
  CLRS[0] = hacks.trace_colors(nc)
  CLRS[1] = hacks.link_colors(nc)
  RGB = [ [], [] ]
  dmin = [ 2.000, 2.000 ]
  for k1 in range(nc):
    for i in range(2):
      clrk1 = CLRS[i][k1]
      RGBk1 = ( clrk1.r, clrk1.g, clrk1.b )
      xn = ( "tr", "lk" )[i]
      sys.stderr.write("  %s: RGB = ( %5.3f %5.3f %5.3f )" % (xn,RGBk1[0],RGBk1[1],RGBk1[2]))
      sys.stderr.write(" Y = %5.3f" % color.Y_from_RGB(RGBk1))
      RGB[i].append(RGBk1)
      for k2 in range(k1):
        clrk2 = CLRS[i][k2]
        RGBk2 = ( clrk2.r, clrk2.g, clrk2.b )
        dmin[i] = min(dmin[i], rn.dist(RGBk1, RGBk2))
      sys.stderr.write(" dmin = %6.4f" % dmin[i])
    sys.stderr.write("\n")
    
  return
  # ----------------------------------------------------------------------

sys.stderr.write("??? Needs more tests ???\n")

test_quatratic_roots()
test_poly_orientation()
test_colors(10)
test_colors(50)

test_choose_grid_steps()
test_adjust_dash_pattern()
test_basic_plot()
test_make_canvas()

