aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/cursor/grcaxes.x
blob: f2f69e4f2dbe5d62afb3f863c370418bf86281da (plain) (blame)
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<gset.h>
include	<gio.h>
include	"gtr.h"
include	"grc.h"

define	LEN_POLYLINE	128		# polyline for axes and ticks
define	NTICKS		6		# default rough ticks on an axis
define	SZ_TICKFORMAT	6		# "%0.Xg"
define	SZ_TICKLABEL	10		# encoded tick label
define	TICKLEN		0.03		# tick length, ndc units
define	LABELOFFSET	1.5		# offset to tick label in ticklen units


# GRC_AXES -- Draw and label the axes of the viewport.  This is a simple
# routine not intended to be competitive with GLABAX.  We draw a box around
# the edge of the screen, find and label the ticks within the plotting area.

procedure grc_axes (stream, sx, sy, raster, rx, ry)

int	stream			#I graphics stream
real	sx, sy			#I screen coords of cursor
int	raster			#I raster number
real	rx, ry			#I raster coords of cursor

char	tickformat[SZ_TICKFORMAT], ticklabel[SZ_TICKLABEL]
pointer tr, w, ap, save_op
int	xt, yt, nwords, nticks, wcs, lt_save
real	xb, xe, x1, dx, x, y, lw_save
real	yb, ye, y1, dy, aspect_ratio, xticklen, yticklen

int	gt_ndigits()
pointer	gtr_init()
real	ttygetr()

errchk	gtr_init, ttygetr, realloc, gax_start
include	"gtr.com"

begin
	tr = gtr_init (stream)

	# Draw the axes with a solid polyline of width 2.0.
	ap = TR_PLAP(tr)
	lt_save = PL_LTYPE(ap);	PL_LTYPE(ap) = GL_SOLID
	lw_save = PL_WIDTH(ap);	PL_WIDTH(ap) = 2.0

	# Select a WCS.
	call grc_scrtowcs (stream, sx, sy, raster, rx, ry, x1, y1, wcs)
	w = TR_WCSPTR(tr,wcs)

	# Get the coordinates of the axes corners and the tick parameters.
	call gax_findticks (w, xb,xe,yb,ye, x1,dx,xt, y1,dy,yt)

	# Mark the position in the frame buffer.  The axes drawing instructions
	# will be appended to the frame buffer by the drawing routines.  When
	# we get all done we will move these instructions to the scratch buffer
	# and reset the frame buffer pointers, since we do not want the axes
	# to be a permanent part of the plot.

	save_op = TR_OP(tr)

	# Compute the X and Y tick lengths in NDC coordinates, corrected for
	# the aspect ratio and workstation transformation.

	aspect_ratio = ttygetr (TR_TTY(tr), "ar")
	if (aspect_ratio < .001)
	    aspect_ratio = 1.0
	xticklen = TICKLEN / xscale * aspect_ratio
	yticklen = TICKLEN / yscale

	# Construct the polyline to draw the first two axes and ticks.  We
	# start at the lower left and draw to the lower right then upper right.

	nticks = int ((xe - xb) / dx)			# Bottom axis.
	call gax_start (xb, yb)
	call gax_draw (x1, yb)
	call gax_tick (0., yticklen)

	for (x=x1+dx;  nticks > 0;  nticks=nticks-1) {
	    call gax_draw (min(x,xe), yb)
	    call gax_tick (0., yticklen)
	    x = x + dx
	}

	nticks = int ((ye - yb) / dy)			# Right axis.
	call gax_draw (xe, yb)
	call gax_draw (xe, y1)
	call gax_tick (-xticklen, 0.)

	for (y=y1+dy;  nticks > 0;  nticks=nticks-1) {
	    call gax_draw (xe, min(y,ye))
	    call gax_tick (-xticklen, 0.)
	    y = y + dy
	}

	call gax_draw (xe, ye)
	call gax_flush (stream)

	# Construct the polyline to draw the second two axes and ticks.  We
	# start at the lower left and draw to the upper left then upper right.

	nticks = int ((ye - yb) / dy)			# Left axis.
	call gax_start (xb, yb)
	call gax_draw (xb, y1)
	call gax_tick (xticklen, 0.)

	for (y=y1+dy;  nticks > 0;  nticks=nticks-1) {
	    call gax_draw (xb, min(y,ye))
	    call gax_tick (xticklen, 0.)
	    y = y + dy
	}

	nticks = int ((xe - xb) / dx)			# Top axis.
	call gax_draw (xb, ye)
	call gax_draw (x1, ye)
	call gax_tick (0., -yticklen)

	for (x=x1+dx;  nticks > 0;  nticks=nticks-1) {
	    call gax_draw (min(x,xe), ye)
	    call gax_tick (0., -yticklen)
	    x = x + dx
	}

	call gax_draw (xe, ye)
	call gax_flush (stream)

	# Label the ticks on the bottom axis.  The tick labels are centered
	# just above each tick.

	nticks = int ((xe - xb) / dx) + 1
	call sprintf (tickformat, SZ_TICKFORMAT, "%%0.%dg")
	    call pargi (max (1, gt_ndigits (xb, xe, dx)) + 1)

	for (x=x1;  nticks > 0;  nticks=nticks-1) {
	    call glb_encode (x, ticklabel, SZ_TICKLABEL, tickformat, dx)
	    call gax_ndc (x, yb, sx, sy)
	    call gax_text (stream, sx, sy + (yticklen * LABELOFFSET),
		ticklabel, GT_CENTER, GT_BOTTOM)
	    x = x + dx
	}

	# Label the ticks on the left axis.  The tick labels are left justified
	# just to the right of each tick.

	nticks = int ((ye - yb) / dy) + 1
	call sprintf (tickformat, SZ_TICKFORMAT, "%%0.%dg")
	    call pargi (max (1, gt_ndigits (yb, ye, dy)) + 1)

	for (y=y1;  nticks > 0;  nticks=nticks-1) {
	    call glb_encode (y, ticklabel, SZ_TICKLABEL, tickformat, dy)
	    call gax_ndc (xb, y, sx, sy)
	    call gax_text (stream, sx + (xticklen * LABELOFFSET), sy,
		ticklabel, GT_LEFT, GT_CENTER)
	    y = y + dy
	}

	# Restore the default polyline attributes.
	PL_LTYPE(ap) = lt_save
	PL_WIDTH(ap) = lw_save

	# Move the axes drawing and labelling instructions to the scratch
	# buffer and fix up the frame buffer pointers.

	nwords = TR_OP(tr) - save_op
	if (nwords > TR_LENSCRATCHBUF(tr)) {
	    call realloc (TR_SCRATCHBUF(tr), nwords, TY_SHORT)
	    TR_LENSCRATCHBUF(tr) = nwords
	}

	call amovs (Mems[save_op], Mems[TR_SCRATCHBUF(tr)], nwords)
	TR_OPSB(tr) = TR_SCRATCHBUF(tr) + nwords
	TR_OP(tr) = save_op
	TR_IP(tr) = save_op
	TR_LASTOP(tr) = save_op
end


# GAX_FINDTICKS -- Get the coordinates of the endpoints of the axes, the first
# tick on each axis, and the tick spacing on each axis.  If log scaling is in
# use on an axis we shall work in log coordinate units, which are linear.

procedure gax_findticks (w, wx1,wx2,wy1,wy2, x1,dx,xt, y1,dy,yt)

pointer	w			# window descriptor
real	wx1,wx2,wy1,wy2		# endpoints of axes
real	x1,dx			# tick start and spacing in X
int	xt			# type of scaling in X
real	y1,dy			# tick start and spacing in Y
int	yt			# type of scaling in Y

pointer	wp
real	ct[LEN_CT]
common	/ftkgcm/ wp, ct

real	sx1, sx2, sy1, sy2
real	elogr()

begin
	wp = w

	# Set up WCS/NDC coordinate transformations.
	call grc_settran (w, ct)

	# Get NDC coords of the corners of the screen.
	call grc_scrtondc (0.001, 0.001, sx1, sy1)
	call grc_scrtondc (0.999, 0.999, sx2, sy2)

	# Move in a bit if the graphics viewport lies within the screen area.
	# This depends upon the workstation transformation, of course.
	sx1 = max (WCS_SX1(w), sx1)
	sx2 = min (WCS_SX2(w), sx2)
	sy1 = max (WCS_SY1(w), sy1)
	sy2 = min (WCS_SY2(w), sy2)

	# Compute world coordinates of the viewport (of the axes to be drawn).
	call grc_ndctowcs (ct, sx1, sy1, wx1, wy1)
	call grc_ndctowcs (ct, sx2, sy2, wx2, wy2)

	# Find the ticks.  If log scaling is in use on an axis we shall find
	# and draw the ticks in log coordinates.

	switch (WCS_XTRAN(w)) {
	case GW_LOG:
	    wx1 = log10 (wx1)
	    wx2 = log10 (wx2)
	case GW_ELOG:
	    wx1 = elogr (wx1)
	    wx2 = elogr (wx2)
	}
	call gtickr (wx1, wx2, NTICKS, NO, x1, dx)

	switch (WCS_YTRAN(w)) {
	case GW_LOG:
	    wy1 = log10 (wy1)
	    wy2 = log10 (wy2)
	case GW_ELOG:
	    wy1 = elogr (wy1)
	    wy2 = elogr (wy2)
	}
	call gtickr (wy1, wy2, NTICKS, NO, y1, dy)

	xt = WCS_XTRAN(w)
	yt = WCS_YTRAN(w)
end


# GAX_NDC -- Convert a pair of world or log-world coordinates to NDC
# coordinates.  GAX_FINDTICKS must be called first to set up transformation.

procedure gax_ndc (wx, wy, sx, sy)

real	wx, wy			# world coords (input)
real	sx, sy			# ndc coords (output)

pointer	wp
real	ct[LEN_CT]
common	/ftkgcm/ wp, ct

real	x, y
real	aelogr()

begin
	# Get X in world coordinates.
	switch (WCS_XTRAN(wp)) {
	case GW_LOG:
	    x = 10.0 ** wx
	case GW_ELOG:
	    x = aelogr (wx)
	default:
	    x = wx
	}

	# Get Y in world coordinates.
	switch (WCS_YTRAN(wp)) {
	case GW_LOG:
	    y = 10.0 ** wy
	case GW_ELOG:
	    y = aelogr (wy)
	default:
	    y = wy
	}

	# Transform to NDC coordinates and return.
	call grc_wcstondc (ct, x, y, sx, sy)
end


# GAX_DRAW -- Add a point to the output polyline for an axis.  The polyline
# is built up in NDC coordinates for output to GTR_POLYLINE.  In addition to
# the draw routine, entry points are provided for start, flush, and tick
# drawing.

procedure gax_draw (wx, wy)

real	wx, wy			# world or log-world coords to draw to
real	sx, sy
pointer	polyline, op
common	/gaxdcm/ polyline, op

begin
	# Transform to NDC coords and add the point to the polyline.
	call gax_ndc (wx, wy, sx, sy)
	Memr[op] = sx
	op = op + 1
	Memr[op] = sy
	op = op + 1
end


# GAX_TICK -- Draw a tick at the current position.  The offsets to draw the
# tick are given in NDC coordinates.

procedure gax_tick (dx, dy)

real	dx, dy			# tick offset in NDC coords for gax_tick
real	x, y
pointer	polyline, op
common	/gaxdcm/ polyline, op

begin
	x = Memr[op-2]
	y = Memr[op-1]

	Memr[op] = x + dx
	op = op + 1
	Memr[op] = y + dy
	op = op + 1

	Memr[op] = x
	op = op + 1
	Memr[op] = y
	op = op + 1
end


# GAX_START -- Start a new polyline at the indicated point in world coords.
# The polyline buffer is of a fixed length with no bounds checking.

procedure gax_start (wx, wy)

real	wx, wy			# world or log-world coords to draw to
pointer	polyline, op

errchk	malloc
common	/gaxdcm/ polyline, op

begin
	call malloc (polyline, LEN_POLYLINE, TY_REAL)
	op = polyline
	call gax_draw (wx, wy)
end


# GAX_FLUSH -- Flush the buffered polyline and free space on the heap.

procedure gax_flush (stream)

int	stream			# graphics stream
pointer	polyline, op
common	/gaxdcm/ polyline, op

begin
	call grc_polyline (stream, Memr[polyline], (op - polyline) / 2)
	call mfree (polyline, TY_REAL)
end


# GAX_TEXT -- Draw a text string (tick label) of size 1.0 with the indicated
# justification.

procedure gax_text (stream, sx, sy, text, hjustify, vjustify)

int	stream			# graphics stream
real	sx, sy			# text coordinates, NDC
char	text[ARB]		# text string to be drawn
int	hjustify		# horizontal justification
int	vjustify		# vertical justification

pointer	tr, tx
int	save_tx[LEN_TX]
errchk	gtr_init
pointer	gtr_init()

begin
	tr = gtr_init (stream)
	tx = TR_TXAP(tr)
	call amovi (Memi[tx], save_tx, LEN_TX)

	TX_UP(tx) = 90
	TX_SIZE(tx) = 1.0
	TX_PATH(tx) = GT_RIGHT
	TX_SPACING(tx) = 0
	TX_HJUSTIFY(tx) = hjustify
	TX_VJUSTIFY(tx) = vjustify
	TX_FONT(tx) = GT_BOLD
	TX_QUALITY(tx) = GT_NORMAL
	TX_COLOR(tx) = 1

	call grc_text (stream, sx, sy, text)
	call amovi (save_tx, Memi[tx], LEN_TX)
end