Viewing contents of file '../idllib/contrib/groupk/mrk_line.pro'
;+
; NAME:
; MRK_LINE
;
; PURPOSE:
; Allows the USER to interactively position a line on an existing plot.
;
; CATEGORY:
; Graphics.
;
; CALLING SEQUENCE:
;
; Result = MRK_LINE( [Window] )
;
; OPTIONAL INPUTS:
;
; Window: Index of the plot window that the line is to be drawn in.
;
; OPTIONAL INPUT KEYWORD PARAMETERS:
;
; STATUS: Set this keyword to display the coordinates of the current
; cursor position in the lower left-hand corner of the plot
; window. (0=Default)
;
; ERASE: Set this keyword to erase the line and status coordinates
; after the position of the line has been selected. (0=Default)
;
; HELP: Set this keyword to display a instruction window on how
; to interactively position the line on the plot. (0=Default)
;
; VERTICAL: Set this keyword to position a vertical line. (0=Default)
;
; HORIZONTAL: Set this keyword to position a horizontal line. (0=Default)
;
; DATA: Set this keyword to display and return line position in
; data coordinates. (1=Default)
;
; NORMAL: Set this keyword to display and return line position in
; normalized coordinates. (0=Default)
;
; DEVICE: Set this keyword to display and return line position in
; device coordinates. (0=Default)
;
; OUTPUTS:
; Returns the position of the line in the coordinates specified by the
; USER (DATA=Default) as a (2,2) dimensioned array or a scalar if
; the horizontal or vertical keyword is set. If a vertical line is selected,
; then the X-coordinate of that line is returned. If a horizontal line is
; selected then the Y-coordinate of that line is returned. Otherwise, the
; (*,0) array specifies the position, (X0,Y0) of the "LEFT" endpoint, and
; the (*,1) array specifies the position, (X1,Y1) of the "RIGHT" endpoint.
;
; EXAMPLE:
; plot,indgen(100)
; x_position = MRK_LINE(/VERTICAL,/HELP)
;
; MODIFICATION HISTORY:
; Written by: Han Wen, June 1995.
; 07-SEP-1996 Draw an ARBITRARY line by default.
; 10-SEP-1996 Display status before setting point.
;-
function MRK_LINE, Window, STATUS=Status, ERASE=Erase, HELP=Help, $
VERTICAL=Vertical, HORIZONTAL=Horizontal, $
NORMAL=Normal_, DEVICE=Device_, DATA=Data_
NP=N_PARAMS()
if !D.WINDOW eq -1 then message,'No existing plot.'
if NP eq 0 then Window=!D.WINDOW
wset, Window
wshow, Window
if (NOT KEYWORD_SET(Normal_)) and $
(NOT KEYWORD_SET(Device_)) and $
(NOT KEYWORD_SET(Data_)) then Data_ = 1
LINESTYLE = 0 ; solid line
COLOR = !D.N_COLORS-1 ; white (B-W Linear)
statline = ''
; Save original window
orig_plot = tvrd()
Orientation = 0
if KEYWORD_SET( Horizontal) then Orientation = 1
if KEYWORD_SET( Vertical ) then Orientation = 2
; Display Help instructions
if KEYWORD_SET( Help ) then begin
object = 'line'
instr = ['1. Place the mouse pointer within the plot',$
'area and then press and hold mouse button 1.',$
'',$
'2. Move the mouse until the '+object+' is in',$
'the desired location.', $
'',$
'3. Release the mouse button.']
xmsg, instr, TITLE='Mrk_Line Instruction',/NOBUTTON, $
/LEFT, /TOP, MSG_ID=Msg_ID, /ALIGN
endif
DEVICE, GET_GRAPHICS_FUNCTION=GXsave, $
SET_GRAPHICS_FUNCTION=6 ; Exclusive OR existing pixels
; Define active plot region
Xleft = !X.MARGIN(0)*!D.X_CH_SIZE
Xright = !D.X_SIZE - !X.MARGIN(1)*!D.X_CH_SIZE
Ybottom = !Y.MARGIN(0)*!D.Y_CH_SIZE
Ytop = !D.Y_SIZE - !Y.MARGIN(1)*!D.Y_CH_SIZE
Rmargin = [[Xleft,Ybottom],[Xright,Ytop]]
Rmargin = CONVERT_COORD( Rmargin, /DEVICE, TO_DATA=Data_, $
TO_DEVICE=Device_, TO_NORMAL=Normal_ )
R = Rmargin
; Make sure first point is within the plot region
repeat begin
repeat begin
CURSOR,X0,Y0,/CHANGE,DATA=Data_,DEVICE=Device_,NORMAL=Normal_
DX = (X0 - Rmargin(0,0))*(Rmargin(0,1) - X0)
DY = (Y0 - Rmargin(1,0))*(Rmargin(1,1) - Y0)
if KEYWORD_SET(STATUS) then begin
XYOUTS,0,0,/NORMAL,statline ; erase old status line
statline = '('+arr2str(X0,4)+','+arr2str(Y0,4)+')'
XYOUTS,0,0,/NORMAL,statline
endif
endrep until (!ERR eq 1)
endrep until (DX gt 0) and (DY gt 0)
; Draw first line
CASE Orientation OF
0 : BEGIN
R(*,0) = [X0,Y0,0]
R(*,1) = [X0,Y0,0]
END
1 : R(1,*) = Y0
2 : R(0,*) = X0
ENDCASE
plots,R,DATA=Data_,DEVICE=Device_,NORMAL=Normal_,$
LINESTYLE=LINESTYLE, COLOR=COLOR
if KEYWORD_SET(STATUS) then begin
XYOUTS,0,0,/NORMAL,statline ; erase old status line
statline = '('+arr2str(X0,4)+','+arr2str(Y0,4)+')'
XYOUTS,0,0,/NORMAL,statline
endif
Rlast = CONVERT_COORD( X0,Y0, DATA=Data_, DEVICE=Device_,$
NORMAL=Normal_, /TO_DEVICE)
Rsign = SIGN(Rlast(0)) or SIGN(Rlast(1))
; Loop until USER releases mouse button 1
while (!err) or (Rsign lt 0) do begin
CURSOR, X1,Y1, /CHANGE, DATA=Data_,DEVICE=Device_,NORMAL=Normal_
Rcurr = CONVERT_COORD( X1,Y1, DATA=Data_, $
DEVICE=Device_, NORMAL=Normal_, /TO_DEVICE)
Rcurr = ROUND(Rcurr) ; Round to nearest pixel
dR = TOTAL(ABS(Rcurr - Rlast))
Rsign = SIGN(Rcurr(0)) or SIGN(Rcurr(1))
if (dR gt 0) and (Rsign gt 0) then begin
; Make sure coordinates are within plot region
X1 = X1 > Rmargin(0,0)
X1 = X1 < Rmargin(0,1)
Y1 = Y1 > Rmargin(1,0)
Y1 = Y1 < Rmargin(1,1)
; erase previous line then draw a new one
plots,R,DATA=Data_,DEVICE=Device_,NORMAL=Normal_,$
LINESTYLE=LINESTYLE, COLOR=COLOR
CASE Orientation OF
0 : R(*,1) = [X1,Y1,0]
1 : R(1,*) = Y1
2 : R(0,*) = X1
ENDCASE
plots,R,DATA=Data_,DEVICE=Device_,NORMAL=Normal_,$
LINESTYLE=LINESTYLE, COLOR=COLOR
if KEYWORD_SET(STATUS) then begin
XYOUTS,0,0,/NORMAL,statline ; erase old status line
statline = '('+arr2str(X1,4)+$
','+arr2str(Y1,4)+')'
XYOUTS,0,0,/NORMAL,statline ; draw new status line
endif
Rlast = Rcurr
endif
endwhile
; Restore plot window
DEVICE,SET_GRAPHICS_FUNCTION=GXsave ; Restore previous graphics fcn
tv, orig_plot
if NOT KEYWORD_SET(ERASE) then $
plots,R,DATA=Data_,DEVICE=Device_,NORMAL=Normal_,$
LINESTYLE=LINESTYLE, COLOR=COLOR
if KEYWORD_SET(Help) then WIDGET_CONTROL,Msg_ID, /DESTROY
wshow,Window
; Return position of line
CASE Orientation OF
0 : BEGIN
R0 = R(0:1,0)
R1 = R(0:1,1)
if (X0 gt X1) then R = [[R1],[R0]] else R = [[R0],[R1]]
return, R
END
1 : return, Y1
2 : return, X1
ENDCASE
end