; Copyright (c) 1998-2000 A.P. Hitchcock  All rights reserved
;+
;NAME:
;	AX_ROTATE
;
;LAST CHANGED: ----------------------------------- 02-jan-02
;
;PURPOSE:
;	This procedure rotates 2-d data (images) about a user defined point.
; It depends on geting data from AXIS2000 data buffers
;
;CATEGORY:
;	AXIS: image processing
;
;CALLING SEQUENCE:
;	AX_ROTATE, TMP, ANGLE=ANGLE, CENTRE=CENTRE, PIXELSIZE=PIXELSIZE, MINVAL=MINVAL
;
;CALLED FROM AXIS:
;	(images~rotate)
;
; INPUT:
; TMP -  image
;
;KEYWORDS:
; ANGLE		rotation angle
; CENTRE	[x,y] - centre for rotation in data units
; PIXELSIZE	size of pixels to mesh to (in microns)
; MAXDIST	maximum distance from centre to a corner (sets size of output image)
; MINVAL	if = 1 then set outside regions to minimum in image
;
; OUTPUT
;	rotated 2-d structure is placed in buffer 0
;
;COMMON BLOCKS:
;	@AXIS_COM	standard set of common blocks
;
;MODIFICATION HISTORY:
; (15-nov-01 aph) isolated from axis2000
; (25-nov-01 aph) make added region have the average color of the image
; (31-dec-01 aph) introduce keywords to allow operation without user input
;			give option for minimum or average color for extending image
;			change from function to procedure; add max_distance keyword
; (02-jan-02 aph) remove pivot keyword in call to ROT
;-

PRO ax_rotate,tmp, angle=angle, centre=centre, pixelsize=pixelsize, maxdist=maxdist, minval=minval
@axis_com
on_error,2

HANDLE_VALUE, Data(CurBuf), tmp
IF n_tags(tmp) EQ 0 THEN RETURN
IF tmp.t NE '2d' then WIDGET_CONTROL, Uprompt, SET_VALUE='Rotate: only for images'
SetGraf, 'MainImg'
if NOT keyword_set(centre) then begin
	WIDGET_CONTROL, Uprompt, SET_VALUE='Rotate: set centre of rotation'
	num_in = dialog_message(/question,'Define numerically ? ', title='Centre of rotation', /default_no)
	if num_in EQ 'Yes' then begin
		xc = get_num(Prompt = 'X_centre', val = ax_centre(0), group = axis_ID)
		yc = get_num(Prompt = 'Y_centre', val = ax_centre(1), group = axis_ID)
	endif else begin
	   	WIDGET_CONTROL, Uprompt, SET_VALUE='use cursor to select center of rotation'
		CURSOR, xc, yc, /UP, /Data
	endelse
endif else begin
	xc = centre[0]
	yc = centre[1]
endelse
	centre = [xc,yc]
	ax_centre = [xc,yc]		; store for future use
ind = Dindex(xc,yc,tmp)

; ------------ determine rotation angle
if NOT keyword_set(angle) then begin
	angle = get_num(Prompt = 'Angle (deg)', Val = ax_angle, group = AXIS_ID)
endif
ax_angle = angle	; save for later use

; ----------  extend image to map max possible field in which to rotate
if NOT keyword_set(maxDist) then begin
	img_ll = [tmp.x(0),tmp.y(0)]
	img_lr = [tmp.x(n_elements(tmp.x)-1),tmp.y(0)]
	img_ul = [tmp.x(0), tmp.y(n_elements(tmp.y)-1)]
	img_ur = [tmp.x(n_elements(tmp.x)-1), tmp.y(n_elements(tmp.y)-1)]
	del_ll = distance(centre,img_ll)
	del_lr = distance(centre,img_lr)
	del_ul = distance(centre,img_ul)
	del_ur = distance(centre,img_ur)
	maxDist = max([del_ll, del_lr, del_ul, del_ur])
	maxDist = get_num(Prompt = 'maxDist from rotation centre', val = maxDist, group = axis_ID)
endif

; ----------- determine pixel size (square)
if NOT keyword_set(pixelsize) then begin
	pix_siz = tmp.x(1) - tmp.x(0)		; ASSUMES square pixels !!
	pix_siz = get_num(Prompt = 'pixel size (um)', val = pix_siz, group = axis_ID)
endif else pix_siz = pixelsize
npix = 2*maxDist/pix_siz+1

; ----------- determine image value for out-of-bound regions
if keyword_set(minval) then val_extend = min(tmp.d) else begin
	WIDGET_CONTROL, Uprompt, $
	    SET_VALUE='Rotate: extend value: 0 = minimum, 1 = average, 2 = 10% below minimum'
	test = get_num(Prompt = 'extend value: 0 = min, 1 = avg, 2 = min-10%', val = 0, group = axis_ID)
	t1 = min(tmp.d, max = t2) & low = t1 - 0.1*(t2-t1)   ; INITIALLY PUT THE FLOOR BELOW ALL SIGNAL
	t =  median(tmp.d) & avg_d = t(0)					  ; NOW USE floor or AVERAGE, depending on user choice
	val_extend = min(tmp.d)
	if test EQ 1 then val_extend = avg_d
	if test EQ 2 then val_extend = low
endelse
img_d = make_array(npix, npix, /float, value=val_extend)
n_xoff = abs(fix((maxDist - abs(xc - tmp.x(0)))/pix_siz))
n_yoff = abs(fix((maxDist - abs(yc - tmp.y(0)))/pix_siz))
img_d(n_xoff: n_xoff+n_elements(tmp.x)-1, n_yoff:n_yoff+n_elements(tmp.y)-1) = tmp.d
img_x = -1.*maxDist + pix_siz*findgen(npix)
img_y = -1.*maxDist + pix_siz*findgen(npix)
R_img = ROT(img_d, angle,1.0, ind(0)+n_xoff, ind(1)+n_yoff, /INTERP, $
     missing = val_extend, cubic = -0.5)    ; angle in DEGREE CLOCKWISE
text = string(format='("R ",F5.1," ")',angle) + tmp.dl
tmp = {t:'2d',x:img_x, y:img_y, e: tmp.e, d: R_img, xl:tmp.xl, yl:tmp.yl, dl:text}
CurBuf = 0
HANDLE_VALUE, Data(CurBuf), tmp, /set
Label(CurBuf) = tmp.dl
PlotBuf,CurBuf
return
end

