# -----------------------------------------------------------------------------
# Report surface coloring volume data value in the status line when mouse
# is over surface.
#
# Opening this script starts the reporting and there is no way to turn it off.
#
def show_surface_value(event):

  # Find surfaces being colored by volume data.
  import SurfaceColor as sc
  surface_models = [s for s in sc.colorable_surface_models()
                    if isinstance(sc.surface_coloring(s)[0], sc.Volume_Color)]
  if len(surface_models) == 0:
    return      # No surfaces colored with volume data

  # Find surface intercept under mouse
  from VolumeViewer import slice
  xyz_in, xyz_out = slice.clip_plane_points(event.x, event.y)
  import PickBlobs as pb
  f, p, t = pb.closest_surface_intercept(surface_models, xyz_in, xyz_out)
  if f is None:
    return      # No surface intercept

  # Look-up surface coloring volume value including surface offset.
  from Matrix import linear_combination, apply_matrix, xform_matrix
  xyz = linear_combination((1.0-f), xyz_in, f, xyz_out)
  sxyz = apply_matrix(xform_matrix(p.model.openState.xform.inverse()), xyz)
  cs = sc.surface_coloring(p.model)[0]
  vol = cs.volume
  va, ta = p.maskedGeometry(p.Solid)
  tri = ta[t]
  w = triangle_vertex_weights(sxyz, [va[vi] for vi in tri])
  values, outside = cs.volume_values(p)
  v = sum([w[i]*values[vi] for i,vi in enumerate(tri)])

  # Report value on status line.
  from chimera import replyobj
  replyobj.status('%s value at surface point = %.5g' % (vol.name, v))

# -----------------------------------------------------------------------------
# Linear interpolate normal vector within surface triangle.
#
def triangle_vertex_weights(xyz, triangle_corners):
  c0, c1, c2 = triangle_corners
  p = xyz - c0
  from Matrix import distance, cross_product as cp
  from numpy import dot as ip
  n = cp(c1-c0, c2-c0)
  n1 = cp(n,c1-c0)
  n2 = cp(n,c2-c0)
  i1 = ip(n1,c2-c0)
  a2 = ip(n1,p)/i1 if i1 != 0 else 0
  i2 = ip(n2,c1-c0)
  a1 = ip(n2,p)/i2 if i2 != 0 else 0
  w = ((1-a1-a2),a1,a2)
  return w

# -----------------------------------------------------------------------------
#
def register_motion_handler():

  import SurfaceColor
  if not hasattr(SurfaceColor, 'svmhandler'):
    from chimera import tkgui
    h = tkgui.app.graphics.bind('<Any-Motion>', show_surface_value, add=1)
    SurfaceColor.svmhandler = h
    from chimera import replyobj
    replyobj.status('Started reporting surface value under mouse')


