📄 rdplot.pro
字号:
endif
endif else Print = 0
;;;
; FULL-SCREEN CURSOR SETUP SECTION =======================================
;;;
;;;;
; If using the full-screen cursor:
; Determine the data range for the full screen.
; Blank out the regular cross cursor if the CROSS keyword is not set.
; Set up the linestyle, thickness, clipping, and color parameters for the
; oplot commands.
; Set up the graphics to be XOR with the overplotted crosshair, and figure
; out the color to use for plotting the crosshair {details below}.
;
if FullCursor then begin
Yfull = convert_coord([0.0,1.0], [0.0,1.0], /NORMAL, /TO_DATA)
Xfull = Yfull[0,*]
Yfull = Yfull[1,*]
device, GET_GRAPHICS=OldGraphics, SET_GRAPHICS=6
if not(keyword_set(Cross)) then device, CURSOR_IMAGE=intarr(16)
if not(keyword_set(Linestyle)) then Linestyle = 0
if not(keyword_set(Thick)) then Thick = 1
NoClip = keyword_set(NoClip)
;;;
; I think the best way to make the fullscreen cursor work is to use the XOR
; graphics function - overplotting a line will XOR with the data already on
; the screen, then overplotting the same line again will XOR again, effectively
; erasing the line and returning the device to its original state/appearance.
; But first, let me present a quick primer on plotting colors in IDL and the
; related color tables and translation table:
; Normally, when a color N (a number between 0 and 255 which refers to a
; particular color in the currently loaded IDL color table) is used in one of
; the plotting or tv commands, the value that is actually sent to the display is
; the value in the N-th bin of the translation table. E.g., if the background
; color is 0, then the actual (device) color value of the background is the
; value in the zeroth bin of the translation table. Similarly, if the user
; wants to plot the color defined by number 147 in the IDL color table, the
; actual (device) color value of that color is the value in the 147th bin
; of the translation table.
; So in the following example, let's pretend we have the following situation:
; IDL> PRINT, !D.N_Colors
; 222
; IDL> PRINT, !P.Background
; 0
; IDL> DEVICE, TRANSLATION=TTab
; IDL> PRINT, TTab[0]
; 34
; IDL> PRINT, TTab[147]
; 181
; When we set DEVICE,SET_GRAPHICS=6, and do an overplot, it performs an XOR
; function between the overplot's translated color value and the background's
; translated color value.
; If we want the resulting color to be the IDL color 147, then we have to
; overplot with the color whose translated color value XOR'ed with the
; background's translated color value (34) will equal 181, which is the
; translated color value of the desired IDL color 147.
;
; Symbolically:
; * TTab[Desired Color] = TTab[OPLOT color] XOR TTab[Background]
; * OPLOT Color = where( TTab eq (TTab[Desired Color] XOR TTab[Background]) )
;
; Numerically {using the above example}:
; * OPLOT Color = where( TTab eq (TTab[147] XOR TTab[0]) )
; * OPLOT Color = where( TTab eq (181 XOR 34) )
; * OPLOT Color = where( TTab eq 151 )
;
; Fine.
; HOWEVER...since the translation table often does NOT contain the full range
; of possible numbers (e.g., 0 to 255), the result of the XOR function between
; the background and the oplot color may be a value that does NOT appear in the
; translation table. This is particularly a problem for colors near the bottom
; of the translation table where the result of the XOR function may be less than
; the lowest value in TTab.
; To fix this problem, I bypass the translation table, and directly send the
; device color (e.g., the value 151 in the above example) to the OPLOT command.
; There is still some bug here - sometimes the color still isn't right. I'll
; have to talk to the IDL support people about this {as soon as our support
; license is renewed!}
; NOTE: Took a while to figure out how to make the full cursor work with
; both a specified cursor color and a non-black background. We stick
; with the XOR graphics function. However, we need to deal with the
; complex case of an indexed color model (Decompositon off) for the
; TrueColor and DirectColor visual classes. For TrueColor, we get
; the RGB triplet stored in the color table at the indices specified
; by Color and BackGround and convert them to 24-bit decomposed color
; indices. Then we turn on color decomposition. Before we exit, we
; turn it back off. For DirectColor, we just need to XOR the 8-bit
; color table indices.
;
; CHECK FOR THE VISUAL CLASS AND COLOR DECOMPOSITION STATE...
device, Get_Visual_Name=VisualName, Get_Decomposed=Decomposed
; SET COLOR KEYWORDS IF NOT DEFINED...
if ((size(Color))[1] eq 0) then $ ; if undefined
Color = Decomposed ? !D.N_Colors - 1 : !D.Table_Size - 1
if (N_elements(BACKGROUND) eq 0) then BackGround = !P.BackGround
; Are we using a TrueColor or DirectColor visual class...
if (VisualName eq 'TrueColor') OR (VisualName eq 'DirectColor') then begin
if (VisualName eq 'TrueColor') AND not(Decomposed) then begin
; For TrueColor with color decomposition off, we need to...
; Turn on Color Decomposition...
device, Decomposed=1
; Get the RGB triplets stored in our color table...
tvlct, rct, gct, bct, /GET
; Find the corresponding 24-bit decomposed color indices...
CTab = long(rct) + ishft(long(gct),8) + ishft(long(bct),16)
DevColor = CTab[Color]
DevBack = CTab[BackGround]
endif else begin
; If TrueColor or Directcolor with Decomposition On, or
; DirectColor with Decomposition Off...
DevColor = Color
DevBack = BackGround
endelse
endif else begin
; If we're not using TrueColor or DirectColor, then we'll
; access the translation table...
device, TRANSLATION=TTab, BYPASS_TRANSLATION=1
if (Color ge !D.Table_size) then $
message, /INFO, $
'Trying to draw cursor with color table index GT Table Size'
DevColor = TTab[Color < (!D.Table_size - 1)]
if (BackGround ge !D.Table_size) then $
message, /INFO, $
'Specified background has color table index GT Table Size'
DevBack = TTab[BackGround < (!D.Table_size - 1)]
endelse
OColor = DevColor xor DevBack
endif
;;;
; FINALLY...THE PLOT READING SECTION ====================================
;;;
;;;
; If the cursor is beyond the boundaries of the window (device coordinates of
; X=-1 and Y=-1), then wait until the cursor is moved into the window.
;
cursor, X, Y, /NOWAIT, /DEVICE
if ((X lt 0) or (Y lt 0)) then cursor, X, Y, /CHANGE
;;;
; Begin the loop that will repeat until a button is clicked (or a change if
; that is what the user wanted). Err0 is used to keep track if the procedure
; was entered with a key already down, then it will be non-zero until that
; key has been released, at which point it will be permanantly set to zero.
; NOTE: Robishaw's edits make Err0 obsolete so these lines are commented.
; Wait for a change (movement or key click). Delete the old lines, and
; if we don't exit the loop, repeat and draw new lines.
;
cursor, X, Y, /NOWAIT, DATA=Data, DEVICE=Device, NORMAL=Normal
;Err0 = !mouse.button
NClicks = 0l
repeat begin ; here we go!
;;;
; This wait is a kludge to prevent ghosts from being left when /FULLCURSOR
; is set.
;
if FullCursor then wait, 0 ; black magic
;;;
; If doing a full-screen cursor, overplot two full-screen lines intersecting
; at that position.
;
if FullCursor then begin
XY = convert_coord(X,Y, DATA=Data,DEVICE=Device,NORMAL=Normal, /TO_DATA)
Xdata = XY[0] * [1.0,1.0]
Ydata = XY[1] * [1.0,1.0]
oplot,Xdata,Yfull,LINE=Linestyle,THICK=Thick,NOCLIP=NoClip,COLOR=OColor
oplot,Xfull,Ydata,LINE=Linestyle,THICK=Thick,NOCLIP=NoClip,COLOR=OColor
endif
;;;
; If printing out data values, do so.
; !mouse.button=1 is the signal for a new line.
;
if (Print gt 0) then begin
if ShowX then begin
if UseXV then Xst = XVSt[(X+0.5) > 0 < XVtop] else Xst = strtrim(X,2)
XSt = XTitle + string(Xst + Blanks, FORMAT=XVfmt)
endif else Xst = ''
if ShowY then begin
if UseYV then Yst = YVSt[(Y+0.5) > 0 < YVtop] else Yst = strtrim(Y,2)
YSt = YTitle + string(Yst + Blanks, FORMAT=YVfmt)
endif else Yst = ''
print, Xst, Yst, format='($,2A,%"\R")'
; If left button pressed, then print out a new line; accumulate
; position if /ACCUMULATE set...
if (!mouse.button eq 1) and $
not(Down or Wait or Change or NoWait) then begin ; new line?
print, format='($,%"\n")'
NClicks = NClicks + 1l
if Arg_Present(y) then begin
if keyword_set(ACCUMULATE) and (NClicks gt 1) then begin
xout = [xout,x]
yout = [yout,y]
endif else begin
xout = x
yout = y
endelse
endif
endif
; If button is held down, don't continue until button is released...
if ( (!mouse.button eq 1) and not(Wait or Change or NoWait) ) $
; if entered with a button down, wait for next down click before
; returning...
or ( (!mouse.button gt 1) and Down) then begin
while (!mouse.button gt 0) do begin
wait, 0.1
cursor, XX, YY, /NOWAIT
endwhile
endif
endif
;Err0 = Err0 < !mouse.button
;;;
; Check to see that the cursor's current position is really the last measured
; position (the mouse could have moved during a delay in the last section). If
; so, then go on. If not, then wait for some change in the mouse's status
; before going on.
; In either case, once we are going on, then if doing a full-screen cursor,
; overplot the previous lines {the XOR graphics function will return the plot
; to its original appearance}. Repeat until exit signal.
;
; There are a few cases where we just want to exit immediately...
InstantOut = ( NoWait ) OR $ ; if /NoWait is set
; if /WAIT is set and *any* button is pressed, even if
; a button is being held down when the routine is called...
( Wait AND (!mouse.button gt 0) ) OR $
; if /CHANGE is set and *any* button is pressed...
( Change AND (NClicks gt 0) )
if not(InstantOut) then begin
cursor, XX, YY, /NOWAIT, DATA=Data, DEVICE=Device, NORMAL=Normal
if ((XX eq X) and (YY eq Y)) then $
cursor, XX, YY, /CHANGE, DATA=Data, DEVICE=Device, NORMAL=Normal
; Load the new XX and YY values into the X and Y variables...
X = XX
Y = YY
endif
; Erase the full cursor...
if FullCursor then begin
oplot,Xdata,Yfull,LINE=Linestyle,THICK=Thick,NOCLIP=NoClip,COLOR=OColor
oplot,Xfull,Ydata,LINE=Linestyle,THICK=Thick,NOCLIP=NoClip,COLOR=OColor
endif
; Handle case of /CHANGE but cursor was moved rather than a button
; clicked; we use kludge of incrementing NClicks counter...
; this will force the new position to be printed...
if Change AND (NClicks eq 0) then begin
XOut = X
YOut = Y
NClicks = NClicks + 1
ExitFlag = 0
continue
endif
Err = !mouse.button
ExitFlag = (Down AND (Err gt 0)) OR (Err gt 1) OR InstantOut
endrep until ExitFlag
;;;
; If exit click was at a position different from last left-click, then add
; this to the list of positions...
;
if (NClicks gt 0) then begin
last_left_click = keyword_set(ACCUMULATE) ? NClicks-1 : 0
if not((X eq XOut[last_left_click]) and $
(Y eq YOut[last_left_click])) then begin
XOut = [XOut,X]
YOut = [YOut,Y]
endif
endif else begin
XOut = X
YOut = Y
endelse
if (Print gt 0) then print
;LABEL_DONE:
;;;
; Done! Go back to the default Graphics and cursor in case they were changed.
; Also erase the plot ranges if they originally were not defined.
;
if FullCursor then device,/CURSOR_CROSSHAIR,SET_GRAPHICS=OldGraphics,Bypass=0
; If the color decomposition was off when we started, shut it off again...
if (VisualName eq 'TrueColor') and not(Decomposed) then device, Decomposed=0
if UndefinedPlot then begin
!X.CRange = 0
!Y.CRange = 0
endif
;;;
; Assign X & Y to the accumulated values if /ACCUMULATE is set...
if keyword_set(ACCUMULATE) and Arg_Present(Y) then begin
X = temporary(XOut)
Y = temporary(YOut)
endif
end ; RDPLOT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -