-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtvcircle.pro
201 lines (162 loc) · 6.01 KB
/
tvcircle.pro
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
Pro Tvcircle, radius, xc, yc, color, COLOR = TheColor, $
DATA= data, FILL=fill,_Extra = _extra
;+
; NAME:
; TVCIRCLE
; PURPOSE:
; Draw circle(s) of specified radius centered on the cursor, or
; at specified position(s)
;
; CALLING SEQUENCE:
; TVCIRCLE, rad, x, y, color, [ /DATA, /FILL, _EXTRA = ]
;
; INPUTS:
; RAD - radius of circle(s) to be drawn, scalar
;
; OPTIONAL INPUT:
; X - x position for circle center, vector or scalar
; Y - y position for circle center, vector or scalar
; If X and Y are not specified, and the device has a cursor,
; then program will draw a circle at the current cursor position
; COLOR - intensity value(s) (0 - !D.N_COLORS) used to draw the circle(s)
; If COLORS is a scalar then all circle are drawn with the same
; color value. Otherwise, the Nth circle is drawn with the
; Nth value of color. Default = !P.COLOR.
;
; OPTIONAL KEYWORD INPUTS:
; DATA - if this keyword is set and non-zero, then the circle width and
; X,Y position center are interpreted as being in DATA
; coordinates. Note that data coordinates must be previously
; defined (with a PLOT or CONTOUR call). TVCIRCLE will
; internally convert to device coordinates before drawing the
; circle, in order to maintain optimal smoothness.
; FILL - If set, fill the circle using POLYFILL
;
; Any keyword recognized by PLOTS (or POLYFILL if /FILL is set)
; is also recognized by TVCIRCLE. In particular, the color,
; linestyle, and thickness of the circles is controlled by the
; COLOR, LINESTYLE, and THICK keywords. If POLYFILL is set
; then available keywords are LINE_FILL and FILL_PATTERN.
; OUTPUTS:
; None
;
; RESTRICTIONS:
; (1) TVCIRCLE does not check whether it writes off of the edge of the
; display
; (2) Some round-off error may occur when non-integral values are
; supplied for both the radius and the center coordinates
; (3) TVCIRCLE does not accept /NORMAL coordinates, only data coordinates
; (if /DATA is set) or device coordinates (the default)
; EXAMPLE:
; (1) Draw circles of radius 9 pixels at the positions specified by
; X,Y vectors, using double thickness lines
;
; IDL> tvcircle, 9, x, y, THICK = 2
;
; Now fill in the circles using the LINE_FILL method
;
; IDL> tvcircle, 9, x, y, /FILL, /LINE_FILL
; METHOD:
; The method used is that of Michener's, modified to take into account
; the fact that IDL plots arrays faster than single points. See
; "Fundamental of Interactive Computer Graphics" by Foley and Van Dam"
; p. 445 for the algorithm.
;
; REVISON HISTORY:
; Original version written by B. Pfarr STX 10-88
; Major rewrite adapted from CIRCLE by Allyn Saroyan LNLL
; Wayne Landsman STX Sep. 91
; Added DATA keyword Wayne Landsman HSTX June 1993
; Added FILL keyword. R. S. Hill, HSTX, 4-Nov-1993
; Always convert to device coords, add _EXTRA keyword, allow vector
; colors. Wayne Landsman, HSTX, May 1995
; Allow one to set COLOR = 0, W. Landsman, HSTX, November 1995
; Check if data axes reversed. P. Mangifico, W. Landsman May 1996
;-
On_Error, 2 ; Return to caller
if ( N_params() LT 1) then begin
print, 'Syntax - TVCIRCLE, rad, [ xc, yc, color, /DATA, /FILL, _EXTRA= ]'
return
endif
if N_elements(radius) NE 1 then message, $
'ERROR - Circle radius (first parameter) must be a scalar'
if N_elements(TheColor) EQ 0 then begin
IF N_Elements( Color ) EQ 0 THEN Color = !P.COLOR
endif else color = TheColor
if N_params() LT 3 then begin
if (!D.WINDOW EQ -1) then message, $
'ERROR - Cursor not available for device ' + !D.NAME
cursor, xc, yc, /DEVICE, /NOWAIT
if (xc LT 0) or (yc LT 0) then begin
message,'Position cursor in window ' + strtrim(!D.WINDOW,2) + $
' -- then hit mouse button',/INF
cursor, xc, yc, /DEVICE, /WAIT
message,'Circle is centered at (' + strtrim(xc,2) + ',' + $
strtrim(yc,2) + ')',/INF
endif
endif
N_circle = min( [ N_elements(xc), N_elements(yc) ] )
if keyword_set( DATA ) then begin
coord = abs(convert_coord(radius,0,/data,/to_dev) - $
convert_coord(0,0,/data,/to_dev))
irad = round( coord(0) )
endif else irad = round(radius)
x = 0
y = irad
d = 3 - 2 * irad
; Find the x and y coordinates for one eighth of a circle.
; The maximum number of these coordinates is the radius of the circle.
xHalfQuad = Make_Array( irad + 1, /Int, /NoZero )
yHalfQuad = xHalfQuad
path = 0
WHILE x lt y $
DO BEGIN
xHalfQuad(path) = x
yHalfQuad(path) = y
path = path + 1
IF d lt 0 $
THEN d = d + (4*x) + 6 $
ELSE BEGIN
d = d + (4*(x-y)) + 10
y = y - 1
END
x = x + 1
END
IF x eq y $
THEN BEGIN ; Fill in last point
xHalfQuad(path) = x
yHalfQuad(path) = y
path = path + 1
END ; Filling in last point
; Shrink the arrays to their correct size
xHalfQuad = xHalfQuad( 0:path-1 )
yHalfQuad = yHalfQuad( 0:path-1 )
; Convert the eighth circle into a quadrant
xQuad = [ xHalfQuad, Rotate(yHalfQuad, 5) ]
yQuad = [ yHalfQuad, Rotate(xHalfQuad, 5) ]
; Prepare for converting the quadrants into a full circle
xQuadRev = Rotate( xQuad(0:2*path-2), 5 )
yQuadRev = Rotate( yQuad(0:2*path-2), 5 )
; Create full-circle coordinates
x = [ xQuad, xQuadRev, -xQuad(1:*), -xQuadRev ]
y = [ yQuad, -yQuadRev, -yQuad(1:*), yQuadRev ]
; Plot the coordinates about the given center
if keyword_set(data) then begin ;Convert to device coordinates
coord = convert_coord( xc, yc, /DATA, /TO_DEVICE)
xcen = round(coord(0,*)) & ycen = round(coord(1,*))
endif else begin
xcen = round(xc) & ycen = round(yc)
endelse
Ncolor1 = N_elements(color) -1
for i = 0l, N_circle-1 do begin
j = i < Ncolor1
if keyword_set(fill) then begin
polyfill, x+xcen(i), y + ycen(i), COLOR=color(j), /DEV, $
_Extra = _extra
endif else begin
PlotS, x + xcen(i), y+ ycen(i), COLOR = Color(j), /DEV, $
_Extra = _extra
endelse
endfor
Return
End; TVcircle