aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/glabax/glbgtick.x
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /sys/gio/glabax/glbgtick.x
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'sys/gio/glabax/glbgtick.x')
-rw-r--r--sys/gio/glabax/glbgtick.x252
1 files changed, 252 insertions, 0 deletions
diff --git a/sys/gio/glabax/glbgtick.x b/sys/gio/glabax/glbgtick.x
new file mode 100644
index 00000000..cc70fd3a
--- /dev/null
+++ b/sys/gio/glabax/glbgtick.x
@@ -0,0 +1,252 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <gio.h>
+include "glabax.h"
+
+# GLB_GETTICK -- Get the position and type of the next tick on an axis.
+# Ticks are accessed sequentially. There are three types of tick scalings,
+# LINEAR, LOG, and ELOG. The tick scaling need not necessarily agree with
+# the WCS scaling, hence linear tick scaling might be used on a nonlinear
+# coordinate system. If the scaling is linear then the first tick need not
+# fall at the endpoint of the axis. If log (or elog) scaling is in use then
+# the axis will have been rounded out to a decade and the first tick will
+# necessarily fall on the axis endpoint. The scalings are described by the
+# following parameters:
+#
+# (variables)
+# nleft number of minor ticks left to next major tick
+# step(x,y) displacement between minor ticks (world coords)
+#
+# (constants)
+# tick1(x,y) world coords of the first tick on an axis
+# nminor number of minor ticks between major ticks
+# istep(x,y) initial step (actual step may differ)
+# kstep(x,y) adjustment to step at major ticks
+#
+# KSTEP is unity if the scaling is linear. The log scalings have a KSTEP of
+# either 10.0 or 0.1. A negative KSTEP value is used to flag ELOG scaling.
+# ELOG, or extended range log scaling, is a log scaling which is defined for
+# X <=0 as well as x > 0. This function is logarithmic for values less than
+# -10 or greater than 10, and linear in the range [-10:+10]. This complicates
+# tick computation because the usual 8 minor ticks per decade characteristic
+# of log scaling are not appropriate in the linear regime. If the scaling
+# is ELOG then we ignore NMINOR and ISTEP in the linear range, changing the
+# values of these parameters temporarily to reflect 4 minor ticks with a tick
+# spacing of 2.0.
+#
+# (Note to the reader: don't feel discouraged if you don't understand this
+# (stuff, it is so complicated I don't understand it either! Having to deal
+# (with linear, log, and elog scaling with both major and minor ticks,
+# (sometimes no minor ticks, with the axis starting at any part of the scale
+# (seems an inherently difficult problem to program compactly. Barring
+# (programming each case separately, the best approach I could come up with was
+# (to walkthrough the code separately for each case, from all initial
+# (conditions, until it works for all cases. If you have problems determine
+# (the initial conditions (the case) and do a similar walkthough. Of course,
+# (if you make a change affecting one case, you may well make the code fail for
+# (a different case.
+
+int procedure glb_gettick (gp, ax, x, y, major_tick)
+
+pointer gp # graphics descriptor
+pointer ax # axis descriptor
+real x, y # coordinates of next tick (output)
+int major_tick # YES if next tick is a major tick
+
+int i, axis, wcs, w, scaling, nminor, expon
+real kstep, step, astep, ten, sx, sy, tolerance, pos, norm_pos
+bool glb_eq()
+define logscale_ 91
+
+begin
+ if (AX_DRAWTICKS(ax) == NO)
+ return (EOF)
+
+ tolerance = TOL
+ scaling = AX_SCALING(ax)
+ nminor = AX_NMINOR(ax)
+ kstep = AX_KSTEP(ax)
+
+ if (AX_HORIZONTAL(ax) == YES)
+ axis = 1
+ else
+ axis = 2
+
+ # Count down a minor tick. If nleft is negative then we are being
+ # called for the first time for this axis.
+
+ if (AX_NLEFT(ax) < 0) {
+
+ # Initialize everything and return coords of the first tick.
+ AX_KSTEP(ax) = AX_IKSTEP(ax)
+ AX_NLEFT(ax) = AX_INLEFT(ax)
+ do i = 1, 2 {
+ AX_POS(ax,i) = AX_TICK1(ax,i)
+ AX_STEP(ax,i) = AX_ISTEP(ax,i)
+ }
+
+ step = AX_STEP(ax,axis)
+ astep = abs (step)
+
+ if (AX_NLEFT(ax) == 0) {
+ # Note that there may not be any minor ticks.
+ major_tick = YES
+ AX_NLEFT(ax) = nminor
+ if (nminor > 0)
+ if (scaling == ELOG && (astep >= .99 && astep < 2.0)) {
+ # Elog scaling in linear region.
+ AX_NLEFT(ax) = 4
+ if (step < 0)
+ step = -2.0
+ else
+ step = 2.0
+ AX_STEP(ax,axis) = step
+ }
+ } else {
+ AX_NLEFT(ax) = AX_NLEFT(ax) - 1
+ major_tick = NO
+ }
+
+ # Elog scaling in linear region. KSTEP must be inverted as we
+ # pass through the origin. This normally occurs upon entry to the
+ # linear region, but if we start out at +/- 10 we must set KSTEP
+ # to its linear value during setup.
+
+ if (scaling == ELOG && glb_eq(step,2.0))
+ AX_KSTEP(ax) = -10.0
+
+ } else {
+ # All ticks after the first tick.
+ do i = 1, 2
+ AX_POS(ax,i) = AX_POS(ax,i) + AX_STEP(ax,i)
+ AX_NLEFT(ax) = AX_NLEFT(ax) - 1
+
+ # If we are log scaling the ticks will never have more than 2
+ # digits of precision. Try to correct for the accumulation of
+ # error by rounding. When log scaling the error increases by
+ # a factor of ten in each decade and can get quite large if
+ # the log scale covers a large range.
+
+ if (scaling != LINEAR) {
+ pos = AX_POS(ax,axis)
+ call fp_normr (pos, norm_pos, expon)
+ pos = nint (norm_pos * 10.0) / 10.0
+ pos = pos * (10.0 ** expon)
+ AX_POS(ax,axis) = pos
+ }
+
+ if (AX_NLEFT(ax) < 0) {
+ # Next tick is a major tick. If log scaling we must reset
+ # the tick parameters for the next decade.
+
+ major_tick = YES
+ AX_NLEFT(ax) = nminor
+
+ # The following handles the special case of ELOG scaling in
+ # the linear regime when the number of minor ticks is zero.
+ # The step size in such a case is 9 to some power in the log
+ # region and +/- 10 in the linear region.
+
+ if (scaling == ELOG && nminor == 0) {
+ pos = AX_POS(ax,axis)
+ if (step < 0)
+ ten = -10.
+ else
+ ten = 10.
+
+ if (glb_eq (pos, 10.0)) {
+ if (glb_eq (step, 10.0)) {
+ if (step < 0)
+ AX_STEP(ax,axis) = -9.
+ else
+ AX_STEP(ax,axis) = 9.
+ goto logscale_
+ } else
+ step = ten
+ } else if (glb_eq (pos, 0.0)) {
+ step = ten
+ if (pos / step < 0)
+ AX_KSTEP(ax) = -0.1
+ else
+ AX_KSTEP(ax) = -10.0
+ } else
+ goto logscale_
+ AX_STEP(ax,axis) = step
+
+ } else if (scaling != LINEAR) {
+ # Adjust the tick step by the kstep factor, provided we
+ # are not at the origin in ELOG scaling (the step is 1
+ # on either side of the origin for ELOG scaling). Reset
+ # the step size to 1.0 if ELOG scaling and just coming out
+ # of the linear regime.
+logscale_
+ step = AX_STEP(ax,axis)
+ if (scaling != ELOG || abs(AX_POS(ax,axis)) > 0.1) {
+ if (scaling == ELOG && glb_eq (step, 2.0))
+ AX_STEP(ax,axis) = step / 2.0
+
+ do i = 1, 2
+ AX_STEP(ax,i) = AX_STEP(ax,i) * abs (AX_KSTEP(ax))
+ }
+
+ # Adjust the step size to 2.0 if ELOG scaling and in the
+ # linear regime (initial step size of 1).
+
+ step = AX_STEP(ax,axis)
+ if (scaling == ELOG && glb_eq(step,1.0)) {
+ if (step < 0)
+ step = -2.0
+ else
+ step = 2.0
+ AX_STEP(ax,axis) = step
+ }
+
+ # If elog scaling and we have just entered the linear
+ # regime, adjust the number of ticks and the KSTEP factor.
+
+ if (scaling == ELOG && glb_eq(step,2.0)) {
+ # Elog scaling in linear region. KSTEP must be
+ # inverted as we pass through the origin.
+
+ if (abs(AX_POS(ax,axis)) > 0.1)
+ AX_KSTEP(ax) = -10.0
+
+ if (nminor > 0)
+ AX_NLEFT(ax) = 4
+ }
+ }
+ } else
+ major_tick = NO
+ }
+
+ x = AX_POS(ax,1)
+ y = AX_POS(ax,2)
+
+ # Return EOF if tick falls beyond end of axis. The comparison is made
+ # in NDC coords to avoid having to check if the WCS is increasing or
+ # decreasing and to avoid the problems of comparing unnormalized
+ # floating point numbers.
+
+ wcs = GP_WCS(gp)
+ w = GP_WCSPTR(gp,wcs)
+
+ call gctran (gp, x,y, sx,sy, wcs, 0)
+ if (sx - WCS_SX2(w) > tolerance || sy - WCS_SY2(w) > tolerance)
+ return (EOF)
+ else
+ return (OK)
+end
+
+
+# GLB_EQ -- Compare two (near normalized) floating point numbers for
+# equality, using the absolute value of the first argument.
+
+bool procedure glb_eq (a, b)
+
+real a # compare absolute value of this number
+real b # to this positive number
+
+begin
+ return (abs (abs(a) - b) < 0.1)
+end