;;;;;;;;;;;;;;;;;;;;;;
;;;   vel_a.pro   ;;;
;;;;;;;;;;;;;;;;;;;;;;
;;;  Author: axel, wd (Wolfgang.Dobler@ncl.ac.uk)
;;;  Date:   8-Jul-1999
;;;  Version: vel_a 1.2
;;;  CVS $Revision: 1.6 $
;;;  Based on: vel.pro,v 1.4 1997/01/15 03:11:50 idl Exp,
;;;  Description: A clone of IDL's vel allowing for
;;;    a) X and Y arguments and the corresponding {X,Y}RANGE,
;;;       {X,Y}STYLE (like velovect, contour, ..)
;;;    b) a SEED argument specifying the random seed
;;;    c) the keywords NOERASE and OVERPLOT
;;;    If called without X and Y arguments, the (slightly bizarre)
;;;    behaviour of IDL's `vel' is reproduced.
;;;    All unknown keywords are passed over to PLOTS (which might not
;;;    be very clever, but makes vel_a,..,color=120 work)

function vel_mybi_a,a,x,y
on_error,2                      ;Return to caller if an error occurs
sizea=size(a)
nx=sizea[1]
i=long(x)+nx*long(y)
q=y-long(y)
p=x-long(x)
q1 = 1.-q
p1 = 1.-p

; Weighting factors were wrong for a(i+1) & a(i+nx), switched them.

aint=p1*q1*a[i] + p*q1*a[i+1] + q*p1*a[i+nx] + p*q*a[i+nx+1]
return,aint
end

PRO ARRHEAD_A,X

ON_ERROR,2                      ;Return to caller if an error occurs
theta = 30 * !radeg
TANT = TAN(THETA)
NP=3.0
SCAL=8.

SX=SIZE(X)
N=SX[2]

boundp = (x[*,N-4,0] eq 0) or (x[*,N-4,0] eq 1) or (x[*,N-4,1] eq 0) or (x[*,N-4,1] eq 1) 
bigl=sqrt((X[*,N-4,0]-X[*,N-5,0])^2+(X[*,N-4,1]-X[*,N-5,1])^2)
wbigl=where((bigl ne 0.0) and (not boundp))
wnbigl=where((bigl eq 0.0) or boundp, count)

LL  = SCAL*TANT*bigl[wbigl]/NP

DX = LL*(X[wbigl,N-4,1]-X[wbigl,N-5,1])/BIGL[wbigl]
DY = LL*(X[wbigl,N-4,0]-X[wbigl,N-5,0])/BIGL[wbigl]

XM = X[wbigl,N-4,0]-(SCAL-1)*(X[wbigl,N-4,0]-X[wbigl,N-5,0])/NP
YM = X[wbigl,N-4,1]-(SCAL-1)*(X[wbigl,N-4,1]-X[wbigl,N-5,1])/NP

X[wbigl,N-3,0] = XM-DX
X[wbigl,N-2,0] = X[wbigl,N-4,0]
X[wbigl,N-1,0] = XM+DX

X[wbigl,N-3,1] = YM+DY
X[wbigl,N-2,1] = X[wbigl,N-4,1]
X[wbigl,N-1,1] = YM-DY

if count ge 1 then begin  ;No head for 0 length
	X[wnbigl,N-3,0] = x[wnbigl,n-4,0]
	X[wnbigl,N-2,0] = X[wnbigl,n-4,0]
	X[wnbigl,N-1,0] = X[wnbigl,n-4,0]
	
	X[wnbigl,N-3,1] = X[wnbigl,N-4,1]
	X[wnbigl,N-2,1] = X[wnbigl,N-4,1]
	X[wnbigl,N-1,1] = X[wnbigl,N-4,1]
	endif

return
END

function arrows_a,u,v,n,length, $
                nsteps=nsteps,seed=seed, $
                dx=dx,dy=dy
on_error,2                      ;Return to caller if an error occurs
su=size(u)
nx=su[1]
ny=su[2]

if (n_elements(dx) le 0) then dx = 1.
if (not keyword_set(dy)) then dy = 1.
lmax=sqrt(max(u^2+v^2))		;Max vector length
lthx=dy*length/lmax/nsteps
lthy=dx*length/lmax/nsteps
xt=randomu(seed,n)		;Starting position
yt=randomu(seed,n)
x=fltarr(n,nsteps+3,2)
x[*,0,0]=xt
x[*,0,1]=yt
for i=1L,nsteps-1 do begin
  xt[*]=(nx-1)*x[*,i-1,0]
  yt[*]=(ny-1)*x[*,i-1,1]
  ut=vel_mybi_a(u,xt,yt)
  vt=vel_mybi_a(v,xt,yt)
  x[*,i,0]=x[*,i-1,0]+ut*lthx
  x[*,i,1]=x[*,i-1,1]+vt*lthy
  ;; Reset the points located outside the drawing window:
  bad=where(x[*,i,0] lt 0)
  if (bad[0] ge 0) then begin
    ;; Interpolate to get the correct point on the boundary
    x[bad,i,1] = x[bad,i-1,1] - $
        x[bad,i-1,0]*(x[bad,i,1]-x[bad,i-1,1])/(x[bad,i,0]-x[bad,i-1,0])
    x[bad,i,0] = 0
  endif
  bad=where(x[*,i,0] gt 1)
  if (bad[0] ge 0) then begin
    ;; Interpolate to get the correct point on the boundary
    x[bad,i,1] = x[bad,i-1,1] + $
        (1-x[bad,i-1,0])*(x[bad,i,1]-x[bad,i-1,1])/(x[bad,i,0]-x[bad,i-1,0])
    x[bad,i,0] = 1
  endif
  bad=where(x[*,i,1] lt 0)
  if (bad[0] ge 0) then begin
    ;; Interpolate to get the correct point on the boundary
    x[bad,i,0] = x[bad,i-1,0] - $
        x[bad,i-1,1]*(x[bad,i,0]-x[bad,i-1,0])/(x[bad,i,1]-x[bad,i-1,1])
    x[bad,i,1] = 0
  endif
  bad=where(x[*,i,1] gt 1)
  if (bad[0] ge 0) then begin
    ;; Interpolate to get the correct point on the boundary
    x[bad,i,0] = x[bad,i-1,0] + $
        (1-x[bad,i-1,1])*(x[bad,i,0]-x[bad,i-1,0])/(x[bad,i,1]-x[bad,i-1,1])
    x[bad,i,1] = 1
  endif
end
ARRHEAD_A,X
return,x
end


PRO VEL_A,U,W,xx,yy, $
          LENGTH=length, XMAX=xmax, $
          NVECS=nvecs, NSTEPS=nsteps, $
          TITLE=title, OVERPLOT=overplot, $
          SEED=seed, NOERASE=noerase, $
          COLOR=color, $
          _EXTRA=extra
;+
; NAME:
;	VEL
;
; PURPOSE:
;	Draw a velocity (flow) field with arrows following the field 
;	proportional in length to the field strength.  Arrows are composed 
;	of a number of small segments that follow the streamlines.
;
; CATEGORY:
;	Graphics, two-dimensional.
;
; CALLING SEQUENCE:
;	VEL, U, V
;
; INPUTS:
;	U:	The X component at each point of the vector field.  This 
;		parameter must be a 2D array.
;
;	V:	The Y component at each point of the vector field.  This 
;		parameter must have the same dimensions as U.
;
; KEYWORD PARAMETERS:
;	NVECS:	The number of vectors (arrows) to draw.  If this keyword is
;		omitted, 200 vectors are drawn.
;
;	XMAX:	X axis size as a fraction of Y axis size.  The default is 1.0.
;		This argument is ignored when !p.multi is set.
;
;	LENGTH:	The length of each arrow line segment expressed as a fraction 
;		of the longest vector divided by the number of steps.  The 
;		default is 0.1.
;
;	NSTEPS:	The number of shoots or line segments for each arrow.  The
;		default is 10.
;
;	TITLE:	A string containing the title for the plot.
;	
; OUTPUTS:
;	No explicit outputs.  A velocity field graph is drawn on the current
;	graphics device.
;
; COMMON BLOCKS:
;	None.
;
; SIDE EFFECTS:
;	A plot is drawn on the current graphics device.
;
; RESTRICTIONS:
;	none
;
; PROCEDURE:
;	NVECS random points within the (u,v) arrays are selected.
;	For each "shot" the field (as bilinearly interpolated) at each
;	point is followed using a vector of LENGTH length, tracing
;	a line with NSTEPS segments.  An arrow head is drawn at the end.
;
; MODIFICATION HISTORY:
;	Neal Hurlburt, April, 1988.
;	12/2/92	- modified to handle !p.multi (jiy-RSI)
;       7/12/94 HJM - Fixed error in weighting factors in function
;                     vel_mybi() which produced incorrect velocity vectors.
;       sometimes - ab added xx and yy arguments and introduces
;                   keywords OVERPLOT, NOERASE and SEED
;       8/7/99  - wd improved the xx and yy argument handling and fixed
;                 a bug for different x- and y-axis ranges.
;       31/8/99 - wd switched loop indices to type long integer
;-

on_error,2                      ;Return to caller if an error occurs
if n_elements(Nvecs) le 0 then nvecs=200
if n_elements(nsteps) le 0 then nsteps = 10
if n_elements(length) le 0 then length=.1
if n_elements(title) le 0 then title='Velocity Field'
if n_elements(seed) le 0 then seed=3.11
if n_elements(color) le 0 then begin
  if !d.name eq 'PS' then color=0 else color=255
endif
;
if n_elements(xx) le 0 then begin ; Mimic the old behaviour
  X=ARROWS_A(U,W,Nvecs,LENGTH, nsteps=nsteps,seed=seed)
  if (!p.multi[1] eq 0 and !p.multi[1] eq 0) then begin
    if (n_elements(xmax) eq 0) then xmax = 1.0
    IF XMAX GT 1. THEN position=[0.20,(0.5-0.30/XMAX),0.90,(0.5+0.40/XMAX)]$
    else position=[(0.5-0.30*XMAX),0.20,(0.5+0.40*XMAX),0.90]
    plot,[0,1,1,0,0],[0,0,1,1,0],title=title,pos=position
  endif else begin
    plot,[0,1,1,0,0],[0,0,1,1,0],title=title
  endelse
  FOR I=0L,Nvecs-1 DO PLOTS,X[I,*,0],X[I,*,1],_EXTRA=extra
endif else begin
  x1=min(xx) & dxx=max(xx)-x1
  y1=min(yy) & dyy=max(yy)-y1
  if keyword_set(noerase) then begin
    if not keyword_set(overplot) then plot,x1+dxx*[0,1,1,0,0],y1+dyy*[0,0,1,1,0],$
        title=title,/nodata,/noerase,color=color
  end else begin
    if not keyword_set(overplot) then plot,x1+dxx*[0,1,1,0,0],y1+dyy*[0,0,1,1,0],$
        title=title,/nodata,color=color
  end
  X=ARROWS_A(U,W,Nvecs,LENGTH, nsteps=nsteps,seed=seed,dx=dxx,dy=dyy)
  FOR I=0L,Nvecs-1 DO PLOTS,x1+dxx*X[I,*,0],y1+dyy*X[I,*,1],noclip=0,color=color
endelse
RETURN
end


PRO VEL,ux,uy,xx,xy, $
          _EXTRA=extra
;; Redefine VEL as a wrapper to the above defined function `vel_a'. It
;; is better to call `vel_a' in an IDL program, since then you are
;; sure what you get.
  vel_a, ux,uy,xx,xy, _EXTRA=extra
  RETURN
end