aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/lib
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 /pkg/images/lib
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'pkg/images/lib')
-rw-r--r--pkg/images/lib/coomap.key33
-rw-r--r--pkg/images/lib/geofit.gx1605
-rw-r--r--pkg/images/lib/geofit.x2539
-rw-r--r--pkg/images/lib/geofiti.x2521
-rw-r--r--pkg/images/lib/geogmap.gx494
-rw-r--r--pkg/images/lib/geogmap.h37
-rw-r--r--pkg/images/lib/geogmap.x905
-rw-r--r--pkg/images/lib/geogmapi.x905
-rw-r--r--pkg/images/lib/geograph.gx1379
-rw-r--r--pkg/images/lib/geograph.x1740
-rw-r--r--pkg/images/lib/geomap.h109
-rw-r--r--pkg/images/lib/geomap.key31
-rw-r--r--pkg/images/lib/geoset.x61
-rw-r--r--pkg/images/lib/imcopy.x106
-rw-r--r--pkg/images/lib/liststr.gx427
-rw-r--r--pkg/images/lib/liststr.x766
-rw-r--r--pkg/images/lib/mkpkg72
-rw-r--r--pkg/images/lib/rgbckgrd.x661
-rw-r--r--pkg/images/lib/rgccwcs.x221
-rw-r--r--pkg/images/lib/rgcontour.x475
-rw-r--r--pkg/images/lib/rgfft.x269
-rw-r--r--pkg/images/lib/rglltran.x42
-rw-r--r--pkg/images/lib/rgmerge.x1023
-rw-r--r--pkg/images/lib/rgsort.x162
-rw-r--r--pkg/images/lib/rgtransform.x947
-rw-r--r--pkg/images/lib/rgwrdstr.x53
-rw-r--r--pkg/images/lib/rgxymatch.x97
-rw-r--r--pkg/images/lib/xymatch.x175
-rw-r--r--pkg/images/lib/xyxymatch.h35
-rw-r--r--pkg/images/lib/zzdebug.x430
30 files changed, 18320 insertions, 0 deletions
diff --git a/pkg/images/lib/coomap.key b/pkg/images/lib/coomap.key
new file mode 100644
index 00000000..2a44520a
--- /dev/null
+++ b/pkg/images/lib/coomap.key
@@ -0,0 +1,33 @@
+ Interactive Keystroke Commands
+
+? Print options
+f Fit data and graph fit with the current graph type (g,x,r,y,s)
+g Graph the data and the current fit
+x,r Graph the xi fit residuals versus x and y respectively
+y,s Graph the eta fit residuals versus x and y respectively
+d,u Delete or undelete the data point nearest the cursor
+o Overplot the next graph
+c Toggle the line of constant x and y plotting option
+t Plot a line of constant x and y through nearest data point
+l Print xishift, etashift, xscale, yscale, xrotate, yrotate
+q Exit the interactive surface fitting code
+
+ Interactive Colon Commands
+
+The parameters are listed or set with the following commands which may be
+abbreviated. To list the value of a parameter type the command alone.
+
+:show List parameters
+:projection Sky projection (lin,tan,arc,sin,tnx, ...)
+:refpoint Sky projection reference point
+:fit [value] Fit geometry (shift,xyscale,rotate,rscale,rxyscale,general)
+:function [value] Fitting function (chebyshev,legendre,polynomial)
+:order [value] Xi and Eta fitting orders in x and y
+:xxorder [value] Xi fitting function order in x
+:xyorder [value] Xi fitting function order in y
+:yxorder [value] Eta fitting function order in x
+:yyorder [value] Eta fitting function order in y
+:xxterms [y/n] Include cross-terms in xi fit
+:yxterms [y/n] Include cross-terms in eta fit
+:maxiter [value] Maximum number of rejection operations
+:reject [value] K-sigma rejection threshold
diff --git a/pkg/images/lib/geofit.gx b/pkg/images/lib/geofit.gx
new file mode 100644
index 00000000..7aae63a9
--- /dev/null
+++ b/pkg/images/lib/geofit.gx
@@ -0,0 +1,1605 @@
+# Copyright(c) 1986 Assocation of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <math.h>
+include <math/gsurfit.h>
+include "geomap.h"
+
+$for (r)
+
+# GEO_MINIT -- Initialize the fitting routines.
+
+procedure geo_minit (fit, projection, geometry, function, xxorder, xyorder,
+ xxterms, yxorder, yyorder, yxterms, maxiter, reject)
+
+pointer fit #I pointer to the fit structure
+int projection #I the coordinate projection type
+int geometry #I the fitting geometry
+int function #I fitting function
+int xxorder #I order of x fit in x
+int xyorder #I order of x fit in y
+int xxterms #I include cross terms in x fit
+int yxorder #I order of y fit in x
+int yyorder #I order of y fit in y
+int yxterms #I include cross-terms in y fit
+int maxiter #I the maximum number of rejection interations
+double reject #I rejection threshold in sigma
+
+begin
+ # Allocate the space.
+ call malloc (fit, LEN_GEOMAP, TY_STRUCT)
+
+ # Set function and order.
+ GM_PROJECTION(fit) = projection
+ GM_PROJSTR(fit) = EOS
+ GM_FIT(fit) = geometry
+ GM_FUNCTION(fit) = function
+ GM_XXORDER(fit) = xxorder
+ GM_XYORDER(fit) = xyorder
+ GM_XXTERMS(fit) = xxterms
+ GM_YXORDER(fit) = yxorder
+ GM_YYORDER(fit) = yyorder
+ GM_YXTERMS(fit) = yxterms
+
+ # Set rejection parameters.
+ GM_XRMS(fit) = 0.0d0
+ GM_YRMS(fit) = 0.0d0
+ GM_MAXITER(fit) = maxiter
+ GM_REJECT(fit) = reject
+ GM_NREJECT(fit) = 0
+ GM_REJ(fit) = NULL
+
+ # Set origin parameters.
+ GM_XO(fit) = INDEFD
+ GM_YO(fit) = INDEFD
+ GM_XOREF(fit) = INDEFD
+ GM_YOREF(fit) = INDEFD
+end
+
+
+# GEO_FREE -- Release the fitting space.
+
+procedure geo_free (fit)
+
+pointer fit #I pointer to the fitting structure
+
+begin
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call mfree (fit, TY_STRUCT)
+end
+
+$endfor
+
+
+$for (rd)
+
+# GEO_FIT -- Fit the surface in batch.
+
+procedure geo_fit$t (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, npts,
+ xerrmsg, yerrmsg, maxch)
+
+pointer fit #I pointer to fitting structure
+pointer sx1, sy1 #U pointer to linear surface
+pointer sx2, sy2 #U pointer to higher order correction
+PIXEL xref[ARB] #I x reference array
+PIXEL yref[ARB] #I y reference array
+PIXEL xin[ARB] #I x array
+PIXEL yin[ARB] #I y array
+PIXEL wts[ARB] #I weight array
+int npts #I the number of data points
+char xerrmsg[ARB] #O the x fit error message
+char yerrmsg[ARB] #O the y fit error message
+int maxch #I maximum size of the error message
+
+pointer sp, xresidual, yresidual
+errchk geo_fxy$t(), geo_mreject$t(), geo_ftheta$t(), geo_fmagnify$t()
+errchk geo_flinear$t()
+
+begin
+ call smark (sp)
+ call salloc (xresidual, npts, TY_PIXEL)
+ call salloc (yresidual, npts, TY_PIXEL)
+
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_ftheta$t (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Mem$t[xresidual], Mem$t[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnify$t (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Mem$t[xresidual], Mem$t[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinear$t (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Mem$t[xresidual], Mem$t[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxy$t (fit, sx1, sx2, xref, yref, xin, wts,
+ Mem$t[xresidual], npts, YES, xerrmsg, maxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxy$t (fit, sy1, sy2, xref, yref, yin, wts,
+ Mem$t[yresidual], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mreject$t (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin,
+ wts, Mem$t[xresidual], Mem$t[yresidual], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+
+ call sfree (sp)
+end
+
+
+# GEO_FTHETA -- Compute the shift and rotation angle required to match one
+# set of coordinates to another.
+
+procedure geo_ftheta$t (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+PIXEL xref[npts] #I reference image x values
+PIXEL yref[npts] #I reference image y values
+PIXEL xin[npts] #I input image x values
+PIXEL yin[npts] #I input image y values
+PIXEL wts[npts] #I array of weights
+PIXEL xresid[npts] #O x fit residuals
+PIXEL yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, num, denom, theta, det
+double ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+PIXEL xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_PIXEL)
+
+ # Initialize the fit.
+$if (datatype == r)
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+$else
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+$endif
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+
+ } else {
+
+ # Compute the sums required to compute the rotation angle.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ if (det < 0.0d0) {
+ cthetax = -ctheta
+ sthetay = -stheta
+ } else {
+ cthetax = ctheta
+ sthetay = stheta
+ }
+ sthetax = stheta
+ cthetay = ctheta
+
+ # Compute the x fit coefficients.
+$if (datatype == r)
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+$else
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+$endif
+
+ # Compute the y fit coefficients.
+$if (datatype == r)
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+$else
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+$endif
+
+ # Compute the residuals
+$if (datatype == r)
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+$else
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+$endif
+ call asub$t (xin, xresid, xresid, npts)
+ call asub$t (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= PIXEL(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FMAGNIFY -- Compute the shift, the rotation angle, and the magnification
+# factor which is assumed to be the same in x and y, required to match one
+# set of coordinates to another.
+
+procedure geo_fmagnify$t (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+PIXEL xref[npts] #I reference image x values
+PIXEL yref[npts] #I reference image y values
+PIXEL xin[npts] #I input image x values
+PIXEL yin[npts] #I input image y values
+PIXEL wts[npts] #I array of weights
+PIXEL xresid[npts] #O x fit residuals
+PIXEL yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, det, theta
+double mag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+PIXEL xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_PIXEL)
+
+ # Initialize the fit.
+$if (datatype == r)
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+$else
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+$endif
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+
+ # Compute the sums.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the magnification factor.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ num = denom * ctheta + num * stheta
+ denom = sxrxr + syryr
+ if (denom <= 0.0d0) {
+ mag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ mag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ if (det < 0.0d0) {
+ cthetax = -mag * ctheta
+ sthetay = -mag * stheta
+ } else {
+ cthetax = mag * ctheta
+ sthetay = mag * stheta
+ }
+ sthetax = mag * stheta
+ cthetay = mag * ctheta
+
+ # Compute the x fit coefficients.
+$if (datatype == r)
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+$else
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+$endif
+
+ # Compute the y fit coefficients.
+$if (datatype == r)
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+$else
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+$endif
+
+ # Compute the residuals
+$if (datatype == r)
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+$else
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+$endif
+ call asub$t (xin, xresid, xresid, npts)
+ call asub$t (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= PIXEL(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FLINEAR -- Compute the shift, the rotation angle, and the x and y scale
+# factors required to match one set of coordinates to another.
+
+procedure geo_flinear$t (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+PIXEL xref[npts] #I reference image x values
+PIXEL yref[npts] #I reference image y values
+PIXEL xin[npts] #I input image x values
+PIXEL yin[npts] #I input image y values
+PIXEL wts[npts] #I array of weights
+PIXEL xresid[npts] #O x fit residuals
+PIXEL yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, theta
+double xmag, ymag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+PIXEL xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_PIXEL)
+
+ # Initialize the fit.
+$if (datatype == r)
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+$else
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+$endif
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 3) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = 2.0d0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi)
+ denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - sxrxr *
+ (syrxi + syryi) * (syrxi - syryi)
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom) / 2.0d0
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+ ctheta = cos (theta)
+ stheta = sin (theta)
+
+ # Compute the x magnification factor.
+ num = sxrxi * ctheta - sxryi * stheta
+ denom = sxrxr
+ if (denom <= 0.0d0) {
+ xmag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ xmag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the y magnification factor.
+ num = syrxi * stheta + syryi * ctheta
+ denom = syryr
+ if (denom <= 0.0d0) {
+ ymag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ ymag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ cthetax = xmag * ctheta
+ sthetax = ymag * stheta
+ sthetay = xmag * stheta
+ cthetay = ymag * ctheta
+
+ # Compute the x fit coefficients.
+$if (datatype == r)
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+$else
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+$endif
+
+ # Compute the y fit coefficients.
+$if (datatype == r)
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+$else
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+$endif
+
+ # Compute the residuals
+$if (datatype == r)
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+$else
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+$endif
+ call asub$t (xin, xresid, xresid, npts)
+ call asub$t (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= PIXEL(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FXY -- Fit the surface.
+
+procedure geo_fxy$t (fit, sf1, sf2, x, y, z, wts, resid, npts, xfit, errmsg,
+ maxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sf1 #U pointer to linear surface
+pointer sf2 #U pointer to higher order surface
+PIXEL x[npts] #I reference image x values
+PIXEL y[npts] #I reference image y values
+PIXEL z[npts] #I z values
+PIXEL wts[npts] #I array of weights
+PIXEL resid[npts] #O fitted residuals
+int npts #I number of points
+int xfit #I X fit ?
+char errmsg[ARB] #O returned error message
+int maxch #I maximum number of characters in error message
+
+int i, ier, ncoeff
+pointer sp, zfit, savefit, coeff
+PIXEL xmin, xmax, ymin, ymax
+bool fp_equald()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (zfit, npts, TY_PIXEL)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_PIXEL)
+ call salloc (coeff, 3, TY_PIXEL)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Initalize fit
+$if (datatype == r)
+ if (sf1 != NULL)
+ call gsfree (sf1)
+ if (sf2 != NULL)
+ call gsfree (sf2)
+
+ if (xfit == YES) {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sf1, Memr[savefit])
+ call gsfree (sf1)
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubr (z, x, Memr[zfit], npts)
+ call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier)
+ call gscoeff (sf1, Memr[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff]
+ Memr[savefit+GS_SAVECOEFF+1] = 1.0
+ Memr[savefit+GS_SAVECOEFF+2] = 0.0
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (xmax + xmin) /
+ 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = 0.0
+ }
+ call gsfree (sf1)
+ call gsrestore (sf1, Memr[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ if (IS_INDEFD(GM_XO(fit)))
+ call gsset (sf1, GSXREF, INDEFR)
+ else
+ call gsset (sf1, GSXREF, real (GM_XO(fit)))
+ if (IS_INDEFD(GM_YO(fit)))
+ call gsset (sf1, GSYREF, INDEFR)
+ else
+ call gsset (sf1, GSYREF, real (GM_YO(fit)))
+ if (IS_INDEFD(GM_ZO(fit)))
+ call gsset (sf1, GSZREF, INDEFR)
+ else
+ call gsset (sf1, GSZREF, real (GM_ZO(fit)))
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 ||
+ GM_XXTERMS(fit) == GS_XFULL)
+ call gsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit),
+ GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+
+ } else {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sf1, Memr[savefit])
+ call gsfree (sf1)
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubr (z, y, Memr[zfit], npts)
+ call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier)
+ call gscoeff (sf1, Memr[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff]
+ Memr[savefit+GS_SAVECOEFF+1] = 0.0
+ Memr[savefit+GS_SAVECOEFF+2] = 1.0
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (ymin + ymax) /
+ 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = 0.0
+ Memr[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0
+ }
+ call gsfree (sf1)
+ call gsrestore (sf1, Memr[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin,
+ xmax, ymin, ymax)
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin,
+ xmax, ymin, ymax)
+ if (IS_INDEFD(GM_XO(fit)))
+ call gsset (sf1, GSXREF, INDEFR)
+ else
+ call gsset (sf1, GSXREF, real (GM_XO(fit)))
+ if (IS_INDEFD(GM_YO(fit)))
+ call gsset (sf1, GSYREF, INDEFR)
+ else
+ call gsset (sf1, GSYREF, real (GM_YO(fit)))
+ if (IS_INDEFD(GM_ZO(fit)))
+ call gsset (sf1, GSZREF, INDEFR)
+ else
+ call gsset (sf1, GSZREF, real (GM_ZO(fit)))
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 ||
+ GM_YXTERMS(fit) == GS_XFULL)
+ call gsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit),
+ GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+
+ }
+
+ }
+
+$else
+ if (sf1 != NULL)
+ call dgsfree (sf1)
+ if (sf2 != NULL)
+ call dgsfree (sf2)
+
+ if (xfit == YES) {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sf1, Memd[savefit])
+ call dgsfree (sf1)
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubd (z, x, Memd[zfit], npts)
+ call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier)
+ call dgscoeff (sf1, Memd[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff]
+ Memd[savefit+GS_SAVECOEFF+1] = 1.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 0.0d0
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (xmax + xmin) /
+ 2.0d0
+ Memd[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 0.0d0
+ }
+ call dgsfree (sf1)
+ call dgsrestore (sf1, Memd[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsset (sf1, GSXREF, GM_XO(fit))
+ call dgsset (sf1, GSYREF, GM_YO(fit))
+ call dgsset (sf1, GSZREF, GM_ZO(fit))
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 ||
+ GM_XXTERMS(fit) == GS_XFULL)
+ call dgsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit),
+ GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+
+ } else {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sf1, Memd[savefit])
+ call dgsfree (sf1)
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubd (z, y, Memd[zfit], npts)
+ call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier)
+ call dgscoeff (sf1, Memd[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff]
+ Memd[savefit+GS_SAVECOEFF+1] = 0.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 1.0d0
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (ymin + ymax) /
+ 2.0d0
+ Memd[savefit+GS_SAVECOEFF+1] = 0.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0d0
+ }
+ call dgsfree (sf1)
+ call dgsrestore (sf1, Memd[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsset (sf1, GSXREF, GM_XO(fit))
+ call dgsset (sf1, GSYREF, GM_YO(fit))
+ call dgsset (sf1, GSZREF, GM_ZO(fit))
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 ||
+ GM_YXTERMS(fit) == GS_XFULL)
+ call dgsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit),
+ GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+ }
+
+$endif
+
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+
+$if (datatype == r)
+ call gsvector (sf1, x, y, resid, npts)
+$else
+ call dgsvector (sf1, x, y, resid, npts)
+$endif
+ call asub$t (z, resid, resid, npts)
+
+ # Calculate higher order fit.
+ if (sf2 != NULL) {
+$if (datatype == r)
+ call gsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier)
+$else
+ call dgsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier)
+$endif
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch,
+ "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+$if (datatype == r)
+ call gsvector (sf2, x, y, Mem$t[zfit], npts)
+$else
+ call dgsvector (sf2, x, y, Mem$t[zfit], npts)
+$endif
+ call asub$t (resid, Mem$t[zfit], resid, npts)
+ }
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= PIXEL(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # calculate the rms of the fit
+ if (xfit == YES) {
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * resid[i] ** 2
+ } else {
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * resid[i] ** 2
+ }
+
+ GM_NPTS(fit) = npts
+
+ call sfree (sp)
+end
+
+
+# GEO_MREJECT -- Reject points from the fit.
+
+procedure geo_mreject$t (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts,
+ xresid, yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit structure
+pointer sx1, sy1 #I pointers to the linear surface
+pointer sx2, sy2 #I pointers to the higher order surface
+PIXEL xref[npts] #I reference image x values
+PIXEL yref[npts] #I yreference values
+PIXEL xin[npts] #I x values
+PIXEL yin[npts] #I yvalues
+PIXEL wts[npts] #I weights
+PIXEL xresid[npts] #I residuals
+PIXEL yresid[npts] #I yresiduals
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x error message
+int xmaxch #I maximum number of characters in the x error message
+char yerrmsg[ARB] #O the output y error message
+int ymaxch #I maximum number of characters in the y error message
+
+int i
+int nreject, niter
+pointer sp, twts
+PIXEL cutx, cuty
+errchk geo_fxy$t(), geo_ftheta$t(), geo_fmagnify$t(), geo_flinear$t()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (twts, npts, TY_PIXEL)
+
+ # Allocate space for the residuals.
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call malloc (GM_REJ(fit), npts, TY_INT)
+ GM_NREJECT(fit) = 0
+
+ # Initialize the temporary weights array and the number of rejected
+ # points.
+ call amov$t (wts, Mem$t[twts], npts)
+ nreject = 0
+
+ niter = 0
+ repeat {
+
+ # Compute the rejection limits.
+ if ((npts - GM_NWTS0(fit)) > 1) {
+ cutx = GM_REJECT(fit) * sqrt (GM_XRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ cuty = GM_REJECT(fit) * sqrt (GM_YRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ } else {
+ cutx = MAX_REAL
+ cuty = MAX_REAL
+ }
+
+ # Reject points from the fit.
+ do i = 1, npts {
+ if (Mem$t[twts+i-1] > 0.0 && ((abs (xresid[i]) > cutx) ||
+ (abs (yresid[i]) > cuty))) {
+ Mem$t[twts+i-1] = PIXEL(0.0)
+ nreject = nreject + 1
+ Memi[GM_REJ(fit)+nreject-1] = i
+ }
+ }
+ if ((nreject - GM_NREJECT(fit)) <= 0)
+ break
+ GM_NREJECT(fit) = nreject
+
+ # Compute number of deleted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= 0.0)
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Recompute the X and Y fit.
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_ftheta$t (fit, sx1, sy1, xref, yref, xin, yin,
+ Mem$t[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnify$t (fit, sx1, sy1, xref, yref, xin, yin,
+ Mem$t[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinear$t (fit, sx1, sy1, xref, yref, xin, yin,
+ Mem$t[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxy$t (fit, sx1, sx2, xref, yref, xin, Mem$t[twts],
+ xresid, npts, YES, xerrmsg, xmaxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxy$t (fit, sy1, sy2, xref, yref, yin, Mem$t[twts],
+ yresid, npts, NO, yerrmsg, ymaxch)
+ }
+
+ # Compute the x fit rms.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + Mem$t[twts+i-1] * xresid[i] ** 2
+
+ # Compute the y fit rms.
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + Mem$t[twts+i-1] * yresid[i] ** 2
+
+ niter = niter + 1
+
+ } until (niter >= GM_MAXITER(fit))
+
+ call sfree (sp)
+end
+
+
+# GEO_MMFREE - Free the space used to fit the surfaces.
+
+procedure geo_mmfree$t (sx1, sy1, sx2, sy2)
+
+pointer sx1 #U pointer to the x fits
+pointer sy1 #U pointer to the y fit
+pointer sx2 #U pointer to the higher order x fit
+pointer sy2 #U pointer to the higher order y fit
+
+begin
+$if (datatype == r)
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+ if (sx2 != NULL)
+ call gsfree (sx2)
+ if (sy2 != NULL)
+ call gsfree (sy2)
+$else
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+ if (sx2 != NULL)
+ call dgsfree (sx2)
+ if (sy2 != NULL)
+ call dgsfree (sy2)
+$endif
+end
+
+$endfor
diff --git a/pkg/images/lib/geofit.x b/pkg/images/lib/geofit.x
new file mode 100644
index 00000000..0eb82a48
--- /dev/null
+++ b/pkg/images/lib/geofit.x
@@ -0,0 +1,2539 @@
+# Copyright(c) 1986 Assocation of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <math.h>
+include <math/gsurfit.h>
+include "geomap.h"
+
+
+
+# GEO_MINIT -- Initialize the fitting routines.
+
+procedure geo_minit (fit, projection, geometry, function, xxorder, xyorder,
+ xxterms, yxorder, yyorder, yxterms, maxiter, reject)
+
+pointer fit #I pointer to the fit structure
+int projection #I the coordinate projection type
+int geometry #I the fitting geometry
+int function #I fitting function
+int xxorder #I order of x fit in x
+int xyorder #I order of x fit in y
+int xxterms #I include cross terms in x fit
+int yxorder #I order of y fit in x
+int yyorder #I order of y fit in y
+int yxterms #I include cross-terms in y fit
+int maxiter #I the maximum number of rejection interations
+double reject #I rejection threshold in sigma
+
+begin
+ # Allocate the space.
+ call malloc (fit, LEN_GEOMAP, TY_STRUCT)
+
+ # Set function and order.
+ GM_PROJECTION(fit) = projection
+ GM_PROJSTR(fit) = EOS
+ GM_FIT(fit) = geometry
+ GM_FUNCTION(fit) = function
+ GM_XXORDER(fit) = xxorder
+ GM_XYORDER(fit) = xyorder
+ GM_XXTERMS(fit) = xxterms
+ GM_YXORDER(fit) = yxorder
+ GM_YYORDER(fit) = yyorder
+ GM_YXTERMS(fit) = yxterms
+
+ # Set rejection parameters.
+ GM_XRMS(fit) = 0.0d0
+ GM_YRMS(fit) = 0.0d0
+ GM_MAXITER(fit) = maxiter
+ GM_REJECT(fit) = reject
+ GM_NREJECT(fit) = 0
+ GM_REJ(fit) = NULL
+
+ # Set origin parameters.
+ GM_XO(fit) = INDEFD
+ GM_YO(fit) = INDEFD
+ GM_XOREF(fit) = INDEFD
+ GM_YOREF(fit) = INDEFD
+end
+
+
+# GEO_FREE -- Release the fitting space.
+
+procedure geo_free (fit)
+
+pointer fit #I pointer to the fitting structure
+
+begin
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call mfree (fit, TY_STRUCT)
+end
+
+
+
+
+
+
+# GEO_FIT -- Fit the surface in batch.
+
+procedure geo_fitr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, npts,
+ xerrmsg, yerrmsg, maxch)
+
+pointer fit #I pointer to fitting structure
+pointer sx1, sy1 #U pointer to linear surface
+pointer sx2, sy2 #U pointer to higher order correction
+real xref[ARB] #I x reference array
+real yref[ARB] #I y reference array
+real xin[ARB] #I x array
+real yin[ARB] #I y array
+real wts[ARB] #I weight array
+int npts #I the number of data points
+char xerrmsg[ARB] #O the x fit error message
+char yerrmsg[ARB] #O the y fit error message
+int maxch #I maximum size of the error message
+
+pointer sp, xresidual, yresidual
+errchk geo_fxyr(), geo_mrejectr(), geo_fthetar(), geo_fmagnifyr()
+errchk geo_flinearr()
+
+begin
+ call smark (sp)
+ call salloc (xresidual, npts, TY_REAL)
+ call salloc (yresidual, npts, TY_REAL)
+
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin, wts,
+ Memr[xresidual], npts, YES, xerrmsg, maxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin, wts,
+ Memr[yresidual], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin,
+ wts, Memr[xresidual], Memr[yresidual], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+
+ call sfree (sp)
+end
+
+
+# GEO_FTHETA -- Compute the shift and rotation angle required to match one
+# set of coordinates to another.
+
+procedure geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+real xref[npts] #I reference image x values
+real yref[npts] #I reference image y values
+real xin[npts] #I input image x values
+real yin[npts] #I input image y values
+real wts[npts] #I array of weights
+real xresid[npts] #O x fit residuals
+real yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, num, denom, theta, det
+double ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+real xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+
+ } else {
+
+ # Compute the sums required to compute the rotation angle.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ if (det < 0.0d0) {
+ cthetax = -ctheta
+ sthetay = -stheta
+ } else {
+ cthetax = ctheta
+ sthetay = stheta
+ }
+ sthetax = stheta
+ cthetay = ctheta
+
+ # Compute the x fit coefficients.
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+
+ # Compute the y fit coefficients.
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+
+ # Compute the residuals
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+ call asubr (xin, xresid, xresid, npts)
+ call asubr (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FMAGNIFY -- Compute the shift, the rotation angle, and the magnification
+# factor which is assumed to be the same in x and y, required to match one
+# set of coordinates to another.
+
+procedure geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+real xref[npts] #I reference image x values
+real yref[npts] #I reference image y values
+real xin[npts] #I input image x values
+real yin[npts] #I input image y values
+real wts[npts] #I array of weights
+real xresid[npts] #O x fit residuals
+real yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, det, theta
+double mag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+real xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+
+ # Compute the sums.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the magnification factor.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ num = denom * ctheta + num * stheta
+ denom = sxrxr + syryr
+ if (denom <= 0.0d0) {
+ mag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ mag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ if (det < 0.0d0) {
+ cthetax = -mag * ctheta
+ sthetay = -mag * stheta
+ } else {
+ cthetax = mag * ctheta
+ sthetay = mag * stheta
+ }
+ sthetax = mag * stheta
+ cthetay = mag * ctheta
+
+ # Compute the x fit coefficients.
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+
+ # Compute the y fit coefficients.
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+
+ # Compute the residuals
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+ call asubr (xin, xresid, xresid, npts)
+ call asubr (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FLINEAR -- Compute the shift, the rotation angle, and the x and y scale
+# factors required to match one set of coordinates to another.
+
+procedure geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+real xref[npts] #I reference image x values
+real yref[npts] #I reference image y values
+real xin[npts] #I input image x values
+real yin[npts] #I input image y values
+real wts[npts] #I array of weights
+real xresid[npts] #O x fit residuals
+real yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, theta
+double xmag, ymag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+real xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 3) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = 2.0d0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi)
+ denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - sxrxr *
+ (syrxi + syryi) * (syrxi - syryi)
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom) / 2.0d0
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+ ctheta = cos (theta)
+ stheta = sin (theta)
+
+ # Compute the x magnification factor.
+ num = sxrxi * ctheta - sxryi * stheta
+ denom = sxrxr
+ if (denom <= 0.0d0) {
+ xmag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ xmag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the y magnification factor.
+ num = syrxi * stheta + syryi * ctheta
+ denom = syryr
+ if (denom <= 0.0d0) {
+ ymag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ ymag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ cthetax = xmag * ctheta
+ sthetax = ymag * stheta
+ sthetay = xmag * stheta
+ cthetay = ymag * ctheta
+
+ # Compute the x fit coefficients.
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+
+ # Compute the y fit coefficients.
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+
+ # Compute the residuals
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+ call asubr (xin, xresid, xresid, npts)
+ call asubr (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FXY -- Fit the surface.
+
+procedure geo_fxyr (fit, sf1, sf2, x, y, z, wts, resid, npts, xfit, errmsg,
+ maxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sf1 #U pointer to linear surface
+pointer sf2 #U pointer to higher order surface
+real x[npts] #I reference image x values
+real y[npts] #I reference image y values
+real z[npts] #I z values
+real wts[npts] #I array of weights
+real resid[npts] #O fitted residuals
+int npts #I number of points
+int xfit #I X fit ?
+char errmsg[ARB] #O returned error message
+int maxch #I maximum number of characters in error message
+
+int i, ier, ncoeff
+pointer sp, zfit, savefit, coeff
+real xmin, xmax, ymin, ymax
+bool fp_equald()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (zfit, npts, TY_REAL)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+ call salloc (coeff, 3, TY_REAL)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Initalize fit
+ if (sf1 != NULL)
+ call gsfree (sf1)
+ if (sf2 != NULL)
+ call gsfree (sf2)
+
+ if (xfit == YES) {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sf1, Memr[savefit])
+ call gsfree (sf1)
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubr (z, x, Memr[zfit], npts)
+ call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier)
+ call gscoeff (sf1, Memr[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff]
+ Memr[savefit+GS_SAVECOEFF+1] = 1.0
+ Memr[savefit+GS_SAVECOEFF+2] = 0.0
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (xmax + xmin) /
+ 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = 0.0
+ }
+ call gsfree (sf1)
+ call gsrestore (sf1, Memr[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ if (IS_INDEFD(GM_XO(fit)))
+ call gsset (sf1, GSXREF, INDEFR)
+ else
+ call gsset (sf1, GSXREF, real (GM_XO(fit)))
+ if (IS_INDEFD(GM_YO(fit)))
+ call gsset (sf1, GSYREF, INDEFR)
+ else
+ call gsset (sf1, GSYREF, real (GM_YO(fit)))
+ if (IS_INDEFD(GM_ZO(fit)))
+ call gsset (sf1, GSZREF, INDEFR)
+ else
+ call gsset (sf1, GSZREF, real (GM_ZO(fit)))
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 ||
+ GM_XXTERMS(fit) == GS_XFULL)
+ call gsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit),
+ GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+
+ } else {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sf1, Memr[savefit])
+ call gsfree (sf1)
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubr (z, y, Memr[zfit], npts)
+ call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier)
+ call gscoeff (sf1, Memr[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff]
+ Memr[savefit+GS_SAVECOEFF+1] = 0.0
+ Memr[savefit+GS_SAVECOEFF+2] = 1.0
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (ymin + ymax) /
+ 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = 0.0
+ Memr[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0
+ }
+ call gsfree (sf1)
+ call gsrestore (sf1, Memr[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin,
+ xmax, ymin, ymax)
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin,
+ xmax, ymin, ymax)
+ if (IS_INDEFD(GM_XO(fit)))
+ call gsset (sf1, GSXREF, INDEFR)
+ else
+ call gsset (sf1, GSXREF, real (GM_XO(fit)))
+ if (IS_INDEFD(GM_YO(fit)))
+ call gsset (sf1, GSYREF, INDEFR)
+ else
+ call gsset (sf1, GSYREF, real (GM_YO(fit)))
+ if (IS_INDEFD(GM_ZO(fit)))
+ call gsset (sf1, GSZREF, INDEFR)
+ else
+ call gsset (sf1, GSZREF, real (GM_ZO(fit)))
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 ||
+ GM_YXTERMS(fit) == GS_XFULL)
+ call gsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit),
+ GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+
+ }
+
+ }
+
+
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+
+ call gsvector (sf1, x, y, resid, npts)
+ call asubr (z, resid, resid, npts)
+
+ # Calculate higher order fit.
+ if (sf2 != NULL) {
+ call gsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier)
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch,
+ "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+ call gsvector (sf2, x, y, Memr[zfit], npts)
+ call asubr (resid, Memr[zfit], resid, npts)
+ }
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # calculate the rms of the fit
+ if (xfit == YES) {
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * resid[i] ** 2
+ } else {
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * resid[i] ** 2
+ }
+
+ GM_NPTS(fit) = npts
+
+ call sfree (sp)
+end
+
+
+# GEO_MREJECT -- Reject points from the fit.
+
+procedure geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts,
+ xresid, yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit structure
+pointer sx1, sy1 #I pointers to the linear surface
+pointer sx2, sy2 #I pointers to the higher order surface
+real xref[npts] #I reference image x values
+real yref[npts] #I yreference values
+real xin[npts] #I x values
+real yin[npts] #I yvalues
+real wts[npts] #I weights
+real xresid[npts] #I residuals
+real yresid[npts] #I yresiduals
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x error message
+int xmaxch #I maximum number of characters in the x error message
+char yerrmsg[ARB] #O the output y error message
+int ymaxch #I maximum number of characters in the y error message
+
+int i
+int nreject, niter
+pointer sp, twts
+real cutx, cuty
+errchk geo_fxyr(), geo_fthetar(), geo_fmagnifyr(), geo_flinearr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (twts, npts, TY_REAL)
+
+ # Allocate space for the residuals.
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call malloc (GM_REJ(fit), npts, TY_INT)
+ GM_NREJECT(fit) = 0
+
+ # Initialize the temporary weights array and the number of rejected
+ # points.
+ call amovr (wts, Memr[twts], npts)
+ nreject = 0
+
+ niter = 0
+ repeat {
+
+ # Compute the rejection limits.
+ if ((npts - GM_NWTS0(fit)) > 1) {
+ cutx = GM_REJECT(fit) * sqrt (GM_XRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ cuty = GM_REJECT(fit) * sqrt (GM_YRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ } else {
+ cutx = MAX_REAL
+ cuty = MAX_REAL
+ }
+
+ # Reject points from the fit.
+ do i = 1, npts {
+ if (Memr[twts+i-1] > 0.0 && ((abs (xresid[i]) > cutx) ||
+ (abs (yresid[i]) > cuty))) {
+ Memr[twts+i-1] = real(0.0)
+ nreject = nreject + 1
+ Memi[GM_REJ(fit)+nreject-1] = i
+ }
+ }
+ if ((nreject - GM_NREJECT(fit)) <= 0)
+ break
+ GM_NREJECT(fit) = nreject
+
+ # Compute number of deleted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= 0.0)
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Recompute the X and Y fit.
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin,
+ Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin,
+ Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin,
+ Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin, Memr[twts],
+ xresid, npts, YES, xerrmsg, xmaxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin, Memr[twts],
+ yresid, npts, NO, yerrmsg, ymaxch)
+ }
+
+ # Compute the x fit rms.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + Memr[twts+i-1] * xresid[i] ** 2
+
+ # Compute the y fit rms.
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + Memr[twts+i-1] * yresid[i] ** 2
+
+ niter = niter + 1
+
+ } until (niter >= GM_MAXITER(fit))
+
+ call sfree (sp)
+end
+
+
+# GEO_MMFREE - Free the space used to fit the surfaces.
+
+procedure geo_mmfreer (sx1, sy1, sx2, sy2)
+
+pointer sx1 #U pointer to the x fits
+pointer sy1 #U pointer to the y fit
+pointer sx2 #U pointer to the higher order x fit
+pointer sy2 #U pointer to the higher order y fit
+
+begin
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+ if (sx2 != NULL)
+ call gsfree (sx2)
+ if (sy2 != NULL)
+ call gsfree (sy2)
+end
+
+
+
+# GEO_FIT -- Fit the surface in batch.
+
+procedure geo_fitd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, npts,
+ xerrmsg, yerrmsg, maxch)
+
+pointer fit #I pointer to fitting structure
+pointer sx1, sy1 #U pointer to linear surface
+pointer sx2, sy2 #U pointer to higher order correction
+double xref[ARB] #I x reference array
+double yref[ARB] #I y reference array
+double xin[ARB] #I x array
+double yin[ARB] #I y array
+double wts[ARB] #I weight array
+int npts #I the number of data points
+char xerrmsg[ARB] #O the x fit error message
+char yerrmsg[ARB] #O the y fit error message
+int maxch #I maximum size of the error message
+
+pointer sp, xresidual, yresidual
+errchk geo_fxyd(), geo_mrejectd(), geo_fthetad(), geo_fmagnifyd()
+errchk geo_flineard()
+
+begin
+ call smark (sp)
+ call salloc (xresidual, npts, TY_DOUBLE)
+ call salloc (yresidual, npts, TY_DOUBLE)
+
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin, wts,
+ Memd[xresidual], npts, YES, xerrmsg, maxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin, wts,
+ Memd[yresidual], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin,
+ wts, Memd[xresidual], Memd[yresidual], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+
+ call sfree (sp)
+end
+
+
+# GEO_FTHETA -- Compute the shift and rotation angle required to match one
+# set of coordinates to another.
+
+procedure geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+double xref[npts] #I reference image x values
+double yref[npts] #I reference image y values
+double xin[npts] #I input image x values
+double yin[npts] #I input image y values
+double wts[npts] #I array of weights
+double xresid[npts] #O x fit residuals
+double yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, num, denom, theta, det
+double ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+double xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+
+ } else {
+
+ # Compute the sums required to compute the rotation angle.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ if (det < 0.0d0) {
+ cthetax = -ctheta
+ sthetay = -stheta
+ } else {
+ cthetax = ctheta
+ sthetay = stheta
+ }
+ sthetax = stheta
+ cthetay = ctheta
+
+ # Compute the x fit coefficients.
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+
+ # Compute the y fit coefficients.
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+
+ # Compute the residuals
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+ call asubd (xin, xresid, xresid, npts)
+ call asubd (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FMAGNIFY -- Compute the shift, the rotation angle, and the magnification
+# factor which is assumed to be the same in x and y, required to match one
+# set of coordinates to another.
+
+procedure geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+double xref[npts] #I reference image x values
+double yref[npts] #I reference image y values
+double xin[npts] #I input image x values
+double yin[npts] #I input image y values
+double wts[npts] #I array of weights
+double xresid[npts] #O x fit residuals
+double yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, det, theta
+double mag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+double xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+
+ # Compute the sums.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the magnification factor.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ num = denom * ctheta + num * stheta
+ denom = sxrxr + syryr
+ if (denom <= 0.0d0) {
+ mag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ mag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ if (det < 0.0d0) {
+ cthetax = -mag * ctheta
+ sthetay = -mag * stheta
+ } else {
+ cthetax = mag * ctheta
+ sthetay = mag * stheta
+ }
+ sthetax = mag * stheta
+ cthetay = mag * ctheta
+
+ # Compute the x fit coefficients.
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+
+ # Compute the y fit coefficients.
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+
+ # Compute the residuals
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+ call asubd (xin, xresid, xresid, npts)
+ call asubd (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FLINEAR -- Compute the shift, the rotation angle, and the x and y scale
+# factors required to match one set of coordinates to another.
+
+procedure geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+double xref[npts] #I reference image x values
+double yref[npts] #I reference image y values
+double xin[npts] #I input image x values
+double yin[npts] #I input image y values
+double wts[npts] #I array of weights
+double xresid[npts] #O x fit residuals
+double yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, theta
+double xmag, ymag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+double xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 3) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = 2.0d0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi)
+ denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - sxrxr *
+ (syrxi + syryi) * (syrxi - syryi)
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom) / 2.0d0
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+ ctheta = cos (theta)
+ stheta = sin (theta)
+
+ # Compute the x magnification factor.
+ num = sxrxi * ctheta - sxryi * stheta
+ denom = sxrxr
+ if (denom <= 0.0d0) {
+ xmag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ xmag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the y magnification factor.
+ num = syrxi * stheta + syryi * ctheta
+ denom = syryr
+ if (denom <= 0.0d0) {
+ ymag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ ymag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ cthetax = xmag * ctheta
+ sthetax = ymag * stheta
+ sthetay = xmag * stheta
+ cthetay = ymag * ctheta
+
+ # Compute the x fit coefficients.
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+
+ # Compute the y fit coefficients.
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+
+ # Compute the residuals
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+ call asubd (xin, xresid, xresid, npts)
+ call asubd (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FXY -- Fit the surface.
+
+procedure geo_fxyd (fit, sf1, sf2, x, y, z, wts, resid, npts, xfit, errmsg,
+ maxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sf1 #U pointer to linear surface
+pointer sf2 #U pointer to higher order surface
+double x[npts] #I reference image x values
+double y[npts] #I reference image y values
+double z[npts] #I z values
+double wts[npts] #I array of weights
+double resid[npts] #O fitted residuals
+int npts #I number of points
+int xfit #I X fit ?
+char errmsg[ARB] #O returned error message
+int maxch #I maximum number of characters in error message
+
+int i, ier, ncoeff
+pointer sp, zfit, savefit, coeff
+double xmin, xmax, ymin, ymax
+bool fp_equald()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (zfit, npts, TY_DOUBLE)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+ call salloc (coeff, 3, TY_DOUBLE)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Initalize fit
+ if (sf1 != NULL)
+ call dgsfree (sf1)
+ if (sf2 != NULL)
+ call dgsfree (sf2)
+
+ if (xfit == YES) {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sf1, Memd[savefit])
+ call dgsfree (sf1)
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubd (z, x, Memd[zfit], npts)
+ call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier)
+ call dgscoeff (sf1, Memd[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff]
+ Memd[savefit+GS_SAVECOEFF+1] = 1.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 0.0d0
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (xmax + xmin) /
+ 2.0d0
+ Memd[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 0.0d0
+ }
+ call dgsfree (sf1)
+ call dgsrestore (sf1, Memd[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsset (sf1, GSXREF, GM_XO(fit))
+ call dgsset (sf1, GSYREF, GM_YO(fit))
+ call dgsset (sf1, GSZREF, GM_ZO(fit))
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 ||
+ GM_XXTERMS(fit) == GS_XFULL)
+ call dgsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit),
+ GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+
+ } else {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sf1, Memd[savefit])
+ call dgsfree (sf1)
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubd (z, y, Memd[zfit], npts)
+ call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier)
+ call dgscoeff (sf1, Memd[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff]
+ Memd[savefit+GS_SAVECOEFF+1] = 0.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 1.0d0
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (ymin + ymax) /
+ 2.0d0
+ Memd[savefit+GS_SAVECOEFF+1] = 0.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0d0
+ }
+ call dgsfree (sf1)
+ call dgsrestore (sf1, Memd[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsset (sf1, GSXREF, GM_XO(fit))
+ call dgsset (sf1, GSYREF, GM_YO(fit))
+ call dgsset (sf1, GSZREF, GM_ZO(fit))
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 ||
+ GM_YXTERMS(fit) == GS_XFULL)
+ call dgsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit),
+ GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+ }
+
+
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+
+ call dgsvector (sf1, x, y, resid, npts)
+ call asubd (z, resid, resid, npts)
+
+ # Calculate higher order fit.
+ if (sf2 != NULL) {
+ call dgsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier)
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch,
+ "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+ call dgsvector (sf2, x, y, Memd[zfit], npts)
+ call asubd (resid, Memd[zfit], resid, npts)
+ }
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # calculate the rms of the fit
+ if (xfit == YES) {
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * resid[i] ** 2
+ } else {
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * resid[i] ** 2
+ }
+
+ GM_NPTS(fit) = npts
+
+ call sfree (sp)
+end
+
+
+# GEO_MREJECT -- Reject points from the fit.
+
+procedure geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts,
+ xresid, yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit structure
+pointer sx1, sy1 #I pointers to the linear surface
+pointer sx2, sy2 #I pointers to the higher order surface
+double xref[npts] #I reference image x values
+double yref[npts] #I yreference values
+double xin[npts] #I x values
+double yin[npts] #I yvalues
+double wts[npts] #I weights
+double xresid[npts] #I residuals
+double yresid[npts] #I yresiduals
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x error message
+int xmaxch #I maximum number of characters in the x error message
+char yerrmsg[ARB] #O the output y error message
+int ymaxch #I maximum number of characters in the y error message
+
+int i
+int nreject, niter
+pointer sp, twts
+double cutx, cuty
+errchk geo_fxyd(), geo_fthetad(), geo_fmagnifyd(), geo_flineard()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (twts, npts, TY_DOUBLE)
+
+ # Allocate space for the residuals.
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call malloc (GM_REJ(fit), npts, TY_INT)
+ GM_NREJECT(fit) = 0
+
+ # Initialize the temporary weights array and the number of rejected
+ # points.
+ call amovd (wts, Memd[twts], npts)
+ nreject = 0
+
+ niter = 0
+ repeat {
+
+ # Compute the rejection limits.
+ if ((npts - GM_NWTS0(fit)) > 1) {
+ cutx = GM_REJECT(fit) * sqrt (GM_XRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ cuty = GM_REJECT(fit) * sqrt (GM_YRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ } else {
+ cutx = MAX_REAL
+ cuty = MAX_REAL
+ }
+
+ # Reject points from the fit.
+ do i = 1, npts {
+ if (Memd[twts+i-1] > 0.0 && ((abs (xresid[i]) > cutx) ||
+ (abs (yresid[i]) > cuty))) {
+ Memd[twts+i-1] = double(0.0)
+ nreject = nreject + 1
+ Memi[GM_REJ(fit)+nreject-1] = i
+ }
+ }
+ if ((nreject - GM_NREJECT(fit)) <= 0)
+ break
+ GM_NREJECT(fit) = nreject
+
+ # Compute number of deleted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= 0.0)
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Recompute the X and Y fit.
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin,
+ Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin,
+ Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin,
+ Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin, Memd[twts],
+ xresid, npts, YES, xerrmsg, xmaxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin, Memd[twts],
+ yresid, npts, NO, yerrmsg, ymaxch)
+ }
+
+ # Compute the x fit rms.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + Memd[twts+i-1] * xresid[i] ** 2
+
+ # Compute the y fit rms.
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + Memd[twts+i-1] * yresid[i] ** 2
+
+ niter = niter + 1
+
+ } until (niter >= GM_MAXITER(fit))
+
+ call sfree (sp)
+end
+
+
+# GEO_MMFREE - Free the space used to fit the surfaces.
+
+procedure geo_mmfreed (sx1, sy1, sx2, sy2)
+
+pointer sx1 #U pointer to the x fits
+pointer sy1 #U pointer to the y fit
+pointer sx2 #U pointer to the higher order x fit
+pointer sy2 #U pointer to the higher order y fit
+
+begin
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+ if (sx2 != NULL)
+ call dgsfree (sx2)
+ if (sy2 != NULL)
+ call dgsfree (sy2)
+end
+
+
diff --git a/pkg/images/lib/geofiti.x b/pkg/images/lib/geofiti.x
new file mode 100644
index 00000000..9f11da2b
--- /dev/null
+++ b/pkg/images/lib/geofiti.x
@@ -0,0 +1,2521 @@
+# Copyright(c) 1986 Assocation of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <math.h>
+include <math/gsurfit.h>
+include "geomap.h"
+
+
+
+# GEO_MINIT -- Initialize the fitting routines.
+
+procedure geo_minit (fit, projection, geometry, function, xxorder, xyorder,
+ xxterms, yxorder, yyorder, yxterms, maxiter, reject)
+
+pointer fit #I pointer to the fit structure
+int projection #I the coordinate projection type
+int geometry #I the fitting geometry
+int function #I fitting function
+int xxorder #I order of x fit in x
+int xyorder #I order of x fit in y
+int xxterms #I include cross terms in x fit
+int yxorder #I order of y fit in x
+int yyorder #I order of y fit in y
+int yxterms #I include cross-terms in y fit
+int maxiter #I the maximum number of rejection interations
+double reject #I rejection threshold in sigma
+
+begin
+ # Allocate the space.
+ call malloc (fit, LEN_GEOMAP, TY_STRUCT)
+
+ # Set function and order.
+ GM_PROJECTION(fit) = projection
+ GM_PROJSTR(fit) = EOS
+ GM_FIT(fit) = geometry
+ GM_FUNCTION(fit) = function
+ GM_XXORDER(fit) = xxorder
+ GM_XYORDER(fit) = xyorder
+ GM_XXTERMS(fit) = xxterms
+ GM_YXORDER(fit) = yxorder
+ GM_YYORDER(fit) = yyorder
+ GM_YXTERMS(fit) = yxterms
+
+ # Set rejection parameters.
+ GM_XRMS(fit) = 0.0d0
+ GM_YRMS(fit) = 0.0d0
+ GM_MAXITER(fit) = maxiter
+ GM_REJECT(fit) = reject
+ GM_NREJECT(fit) = 0
+ GM_REJ(fit) = NULL
+
+ # Set origin parameters.
+ GM_XO(fit) = INDEFD
+ GM_YO(fit) = INDEFD
+ GM_XOREF(fit) = INDEFD
+ GM_YOREF(fit) = INDEFD
+end
+
+
+# GEO_FREE -- Release the fitting space.
+
+procedure geo_free (fit)
+
+pointer fit #I pointer to the fitting structure
+
+begin
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call mfree (fit, TY_STRUCT)
+end
+
+
+
+
+
+
+# GEO_FIT -- Fit the surface in batch.
+
+procedure geo_fitr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, npts,
+ xerrmsg, yerrmsg, maxch)
+
+pointer fit #I pointer to fitting structure
+pointer sx1, sy1 #U pointer to linear surface
+pointer sx2, sy2 #U pointer to higher order correction
+real xref[ARB] #I x reference array
+real yref[ARB] #I y reference array
+real xin[ARB] #I x array
+real yin[ARB] #I y array
+real wts[ARB] #I weight array
+int npts #I the number of data points
+char xerrmsg[ARB] #O the x fit error message
+char yerrmsg[ARB] #O the y fit error message
+int maxch #I maximum size of the error message
+
+pointer sp, xresidual, yresidual
+errchk geo_fxyr(), geo_mrejectr(), geo_fthetar(), geo_fmagnifyr()
+errchk geo_flinearr()
+
+begin
+ call smark (sp)
+ call salloc (xresidual, npts, TY_REAL)
+ call salloc (yresidual, npts, TY_REAL)
+
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin, wts,
+ Memr[xresidual], npts, YES, xerrmsg, maxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin, wts,
+ Memr[yresidual], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin,
+ wts, Memr[xresidual], Memr[yresidual], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+
+ call sfree (sp)
+end
+
+
+# GEO_FTHETA -- Compute the shift and rotation angle required to match one
+# set of coordinates to another.
+
+procedure geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+real xref[npts] #I reference image x values
+real yref[npts] #I reference image y values
+real xin[npts] #I input image x values
+real yin[npts] #I input image y values
+real wts[npts] #I array of weights
+real xresid[npts] #O x fit residuals
+real yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, num, denom, theta, det
+double ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+real xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+
+ } else {
+
+ # Compute the sums required to compute the rotation angle.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ if (det < 0.0d0) {
+ cthetax = -ctheta
+ sthetay = -stheta
+ } else {
+ cthetax = ctheta
+ sthetay = stheta
+ }
+ sthetax = stheta
+ cthetay = ctheta
+
+ # Compute the x fit coefficients.
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+
+ # Compute the y fit coefficients.
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+
+ # Compute the residuals
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+ call asubr (xin, xresid, xresid, npts)
+ call asubr (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FMAGNIFY -- Compute the shift, the rotation angle, and the magnification
+# factor which is assumed to be the same in x and y, required to match one
+# set of coordinates to another.
+
+procedure geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+real xref[npts] #I reference image x values
+real yref[npts] #I reference image y values
+real xin[npts] #I input image x values
+real yin[npts] #I input image y values
+real wts[npts] #I array of weights
+real xresid[npts] #O x fit residuals
+real yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, det, theta
+double mag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+real xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+
+ # Compute the sums.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the magnification factor.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ num = denom * ctheta + num * stheta
+ denom = sxrxr + syryr
+ if (denom <= 0.0d0) {
+ mag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ mag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ if (det < 0.0d0) {
+ cthetax = -mag * ctheta
+ sthetay = -mag * stheta
+ } else {
+ cthetax = mag * ctheta
+ sthetay = mag * stheta
+ }
+ sthetax = mag * stheta
+ cthetay = mag * ctheta
+
+ # Compute the x fit coefficients.
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+
+ # Compute the y fit coefficients.
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+
+ # Compute the residuals
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+ call asubr (xin, xresid, xresid, npts)
+ call asubr (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FLINEAR -- Compute the shift, the rotation angle, and the x and y scale
+# factors required to match one set of coordinates to another.
+
+procedure geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+real xref[npts] #I reference image x values
+real yref[npts] #I reference image y values
+real xin[npts] #I input image x values
+real yin[npts] #I input image y values
+real wts[npts] #I array of weights
+real xresid[npts] #O x fit residuals
+real yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, theta
+double xmag, ymag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+real xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 3) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = 2.0d0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi)
+ denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - sxrxr *
+ (syrxi + syryi) * (syrxi - syryi)
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom) / 2.0d0
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+ ctheta = cos (theta)
+ stheta = sin (theta)
+
+ # Compute the x magnification factor.
+ num = sxrxi * ctheta - sxryi * stheta
+ denom = sxrxr
+ if (denom <= 0.0d0) {
+ xmag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ xmag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the y magnification factor.
+ num = syrxi * stheta + syryi * ctheta
+ denom = syryr
+ if (denom <= 0.0d0) {
+ ymag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ ymag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ cthetax = xmag * ctheta
+ sthetax = ymag * stheta
+ sthetay = xmag * stheta
+ cthetay = ymag * ctheta
+
+ # Compute the x fit coefficients.
+ call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sx1, Memr[savefit])
+ call gsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymax + ymin) / 2
+ Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sx1, Memr[savefit])
+
+ # Compute the y fit coefficients.
+ call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sy1, Memr[savefit])
+ call gsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymax + ymin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call gsrestore (sy1, Memr[savefit])
+
+ # Compute the residuals
+ call gsvector (sx1, xref, yref, xresid, npts)
+ call gsvector (sy1, xref, yref, yresid, npts)
+ call asubr (xin, xresid, xresid, npts)
+ call asubr (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FXY -- Fit the surface.
+
+procedure geo_fxyr (fit, sf1, sf2, x, y, z, wts, resid, npts, xfit, errmsg,
+ maxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sf1 #U pointer to linear surface
+pointer sf2 #U pointer to higher order surface
+real x[npts] #I reference image x values
+real y[npts] #I reference image y values
+real z[npts] #I z values
+real wts[npts] #I array of weights
+real resid[npts] #O fitted residuals
+int npts #I number of points
+int xfit #I X fit ?
+char errmsg[ARB] #O returned error message
+int maxch #I maximum number of characters in error message
+
+int i, ier, ncoeff
+pointer sp, zfit, savefit, coeff
+real xmin, xmax, ymin, ymax
+bool fp_equald()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (zfit, npts, TY_REAL)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL)
+ call salloc (coeff, 3, TY_REAL)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Initalize fit
+ if (sf1 != NULL)
+ call gsfree (sf1)
+ if (sf2 != NULL)
+ call gsfree (sf2)
+
+ if (xfit == YES) {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sf1, Memr[savefit])
+ call gsfree (sf1)
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubr (z, x, Memr[zfit], npts)
+ call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier)
+ call gscoeff (sf1, Memr[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff]
+ Memr[savefit+GS_SAVECOEFF+1] = 1.0
+ Memr[savefit+GS_SAVECOEFF+2] = 0.0
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (xmax + xmin) /
+ 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0
+ Memr[savefit+GS_SAVECOEFF+2] = 0.0
+ }
+ call gsfree (sf1)
+ call gsrestore (sf1, Memr[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gsset (sf1, GSXREF, GM_XO(fit))
+ call gsset (sf1, GSYREF, GM_YO(fit))
+ call gsset (sf1, GSZREF, GM_ZO(fit))
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 ||
+ GM_XXTERMS(fit) == GS_XFULL)
+ call gsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit),
+ GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+
+ } else {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gssave (sf1, Memr[savefit])
+ call gsfree (sf1)
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubr (z, y, Memr[zfit], npts)
+ call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier)
+ call gscoeff (sf1, Memr[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff]
+ Memr[savefit+GS_SAVECOEFF+1] = 0.0
+ Memr[savefit+GS_SAVECOEFF+2] = 1.0
+ } else {
+ Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (ymin + ymax) /
+ 2.0
+ Memr[savefit+GS_SAVECOEFF+1] = 0.0
+ Memr[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0
+ }
+ call gsfree (sf1)
+ call gsrestore (sf1, Memr[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call gsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin,
+ xmax, ymin, ymax)
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin,
+ xmax, ymin, ymax)
+ call gsset (sf1, GSXREF, GM_XO(fit))
+ call gsset (sf1, GSYREF, GM_YO(fit))
+ call gsset (sf1, GSZREF, GM_ZO(fit))
+ call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 ||
+ GM_YXTERMS(fit) == GS_XFULL)
+ call gsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit),
+ GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+
+ }
+
+ }
+
+
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+
+ call gsvector (sf1, x, y, resid, npts)
+ call asubr (z, resid, resid, npts)
+
+ # Calculate higher order fit.
+ if (sf2 != NULL) {
+ call gsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier)
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch,
+ "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+ call gsvector (sf2, x, y, Memr[zfit], npts)
+ call asubr (resid, Memr[zfit], resid, npts)
+ }
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # calculate the rms of the fit
+ if (xfit == YES) {
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * resid[i] ** 2
+ } else {
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * resid[i] ** 2
+ }
+
+ GM_NPTS(fit) = npts
+
+ call sfree (sp)
+end
+
+
+# GEO_MREJECT -- Reject points from the fit.
+
+procedure geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts,
+ xresid, yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit structure
+pointer sx1, sy1 #I pointers to the linear surface
+pointer sx2, sy2 #I pointers to the higher order surface
+real xref[npts] #I reference image x values
+real yref[npts] #I yreference values
+real xin[npts] #I x values
+real yin[npts] #I yvalues
+real wts[npts] #I weights
+real xresid[npts] #I residuals
+real yresid[npts] #I yresiduals
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x error message
+int xmaxch #I maximum number of characters in the x error message
+char yerrmsg[ARB] #O the output y error message
+int ymaxch #I maximum number of characters in the y error message
+
+int i
+int nreject, niter
+pointer sp, twts
+real cutx, cuty
+errchk geo_fxyr(), geo_fthetar(), geo_fmagnifyr(), geo_flinearr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (twts, npts, TY_REAL)
+
+ # Allocate space for the residuals.
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call malloc (GM_REJ(fit), npts, TY_INT)
+ GM_NREJECT(fit) = 0
+
+ # Initialize the temporary weights array and the number of rejected
+ # points.
+ call amovr (wts, Memr[twts], npts)
+ nreject = 0
+
+ niter = 0
+ repeat {
+
+ # Compute the rejection limits.
+ if ((npts - GM_NWTS0(fit)) > 1) {
+ cutx = GM_REJECT(fit) * sqrt (GM_XRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ cuty = GM_REJECT(fit) * sqrt (GM_YRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ } else {
+ cutx = MAX_REAL
+ cuty = MAX_REAL
+ }
+
+ # Reject points from the fit.
+ do i = 1, npts {
+ if (Memr[twts+i-1] > 0.0 && ((abs (xresid[i]) > cutx) ||
+ (abs (yresid[i]) > cuty))) {
+ Memr[twts+i-1] = real(0.0)
+ nreject = nreject + 1
+ Memi[GM_REJ(fit)+nreject-1] = i
+ }
+ }
+ if ((nreject - GM_NREJECT(fit)) <= 0)
+ break
+ GM_NREJECT(fit) = nreject
+
+ # Compute number of deleted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= 0.0)
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Recompute the X and Y fit.
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin,
+ Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin,
+ Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin,
+ Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin, Memr[twts],
+ xresid, npts, YES, xerrmsg, xmaxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin, Memr[twts],
+ yresid, npts, NO, yerrmsg, ymaxch)
+ }
+
+ # Compute the x fit rms.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + Memr[twts+i-1] * xresid[i] ** 2
+
+ # Compute the y fit rms.
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + Memr[twts+i-1] * yresid[i] ** 2
+
+ niter = niter + 1
+
+ } until (niter >= GM_MAXITER(fit))
+
+ call sfree (sp)
+end
+
+
+# GEO_MMFREE - Free the space used to fit the surfaces.
+
+procedure geo_mmfreer (sx1, sy1, sx2, sy2)
+
+pointer sx1 #U pointer to the x fits
+pointer sy1 #U pointer to the y fit
+pointer sx2 #U pointer to the higher order x fit
+pointer sy2 #U pointer to the higher order y fit
+
+begin
+ if (sx1 != NULL)
+ call gsfree (sx1)
+ if (sy1 != NULL)
+ call gsfree (sy1)
+ if (sx2 != NULL)
+ call gsfree (sx2)
+ if (sy2 != NULL)
+ call gsfree (sy2)
+end
+
+
+
+# GEO_FIT -- Fit the surface in batch.
+
+procedure geo_fitd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, npts,
+ xerrmsg, yerrmsg, maxch)
+
+pointer fit #I pointer to fitting structure
+pointer sx1, sy1 #U pointer to linear surface
+pointer sx2, sy2 #U pointer to higher order correction
+double xref[ARB] #I x reference array
+double yref[ARB] #I y reference array
+double xin[ARB] #I x array
+double yin[ARB] #I y array
+double wts[ARB] #I weight array
+int npts #I the number of data points
+char xerrmsg[ARB] #O the x fit error message
+char yerrmsg[ARB] #O the y fit error message
+int maxch #I maximum size of the error message
+
+pointer sp, xresidual, yresidual
+errchk geo_fxyd(), geo_mrejectd(), geo_fthetad(), geo_fmagnifyd()
+errchk geo_flineard()
+
+begin
+ call smark (sp)
+ call salloc (xresidual, npts, TY_DOUBLE)
+ call salloc (yresidual, npts, TY_DOUBLE)
+
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin, wts,
+ Memd[xresidual], npts, YES, xerrmsg, maxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin, wts,
+ Memd[yresidual], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin,
+ wts, Memd[xresidual], Memd[yresidual], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+
+ call sfree (sp)
+end
+
+
+# GEO_FTHETA -- Compute the shift and rotation angle required to match one
+# set of coordinates to another.
+
+procedure geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+double xref[npts] #I reference image x values
+double yref[npts] #I reference image y values
+double xin[npts] #I input image x values
+double yin[npts] #I input image y values
+double wts[npts] #I array of weights
+double xresid[npts] #O x fit residuals
+double yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, num, denom, theta, det
+double ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+double xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+
+ } else {
+
+ # Compute the sums required to compute the rotation angle.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ if (det < 0.0d0) {
+ cthetax = -ctheta
+ sthetay = -stheta
+ } else {
+ cthetax = ctheta
+ sthetay = stheta
+ }
+ sthetax = stheta
+ cthetay = ctheta
+
+ # Compute the x fit coefficients.
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+
+ # Compute the y fit coefficients.
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+
+ # Compute the residuals
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+ call asubd (xin, xresid, xresid, npts)
+ call asubd (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FMAGNIFY -- Compute the shift, the rotation angle, and the magnification
+# factor which is assumed to be the same in x and y, required to match one
+# set of coordinates to another.
+
+procedure geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+double xref[npts] #I reference image x values
+double yref[npts] #I reference image y values
+double xin[npts] #I input image x values
+double yin[npts] #I input image y values
+double wts[npts] #I array of weights
+double xresid[npts] #O x fit residuals
+double yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, det, theta
+double mag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+double xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 2) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+
+ # Compute the sums.
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = sxrxi * syryi
+ denom = syrxi * sxryi
+ if (fp_equald (num, denom))
+ det = 0.0d0
+ else
+ det = num - denom
+ if (det < 0.0d0) {
+ num = syrxi + sxryi
+ denom = -sxrxi + syryi
+ } else {
+ num = syrxi - sxryi
+ denom = sxrxi + syryi
+ }
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom)
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the magnification factor.
+ ctheta = cos (theta)
+ stheta = sin (theta)
+ num = denom * ctheta + num * stheta
+ denom = sxrxr + syryr
+ if (denom <= 0.0d0) {
+ mag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ mag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ if (det < 0.0d0) {
+ cthetax = -mag * ctheta
+ sthetay = -mag * stheta
+ } else {
+ cthetax = mag * ctheta
+ sthetay = mag * stheta
+ }
+ sthetax = mag * stheta
+ cthetay = mag * ctheta
+
+ # Compute the x fit coefficients.
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+
+ # Compute the y fit coefficients.
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+
+ # Compute the residuals
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+ call asubd (xin, xresid, xresid, npts)
+ call asubd (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FLINEAR -- Compute the shift, the rotation angle, and the x and y scale
+# factors required to match one set of coordinates to another.
+
+procedure geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid,
+ yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sx1 #U pointer to linear x fit surface
+pointer sy1 #U pointer to linear y fit surface
+double xref[npts] #I reference image x values
+double yref[npts] #I reference image y values
+double xin[npts] #I input image x values
+double yin[npts] #I input image y values
+double wts[npts] #I array of weights
+double xresid[npts] #O x fit residuals
+double yresid[npts] #O y fit residuals
+int npts #I number of points
+char xerrmsg[ARB] #O returned x fit error message
+int xmaxch #I maximum number of characters in x fit error message
+char yerrmsg[ARB] #O returned y fit error message
+int ymaxch #I maximum number of characters in y fit error message
+
+int i
+double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0
+double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, theta
+double xmag, ymag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay
+double xmin, xmax, ymin, ymax
+pointer sp, savefit
+bool fp_equald()
+
+begin
+ # Allocate some working space
+ call smark (sp)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+
+ # Initialize the fit.
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+
+ # Determine the minimum and maximum values.
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Compute the sums required to determine the offsets.
+ sw = 0.0d0
+ sxr = 0.0d0
+ syr = 0.0d0
+ sxi = 0.0d0
+ syi = 0.0d0
+ do i = 1, npts {
+ sw = sw + wts[i]
+ sxr = sxr + wts[i] * xref[i]
+ syr = syr + wts[i] * yref[i]
+ sxi = sxi + wts[i] * xin[i]
+ syi = syi + wts[i] * yin[i]
+ }
+
+ # Do the fit.
+ if (sw < 3) {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for X and Y fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for X and Y fits.")
+ call error (1, "Too few data points for X and Y fits.")
+ } else {
+ call sprintf (xerrmsg, xmaxch,
+ "Too few data points for XI and ETA fits.")
+ call sprintf (yerrmsg, ymaxch,
+ "Too few data points for XI and ETA fits.")
+ call error (1, "Too few data points for XI and ETA fits.")
+ }
+ } else {
+ xr0 = sxr / sw
+ yr0 = syr / sw
+ xi0 = sxi / sw
+ yi0 = syi / sw
+ sxrxr = 0.0d0
+ syryr = 0.0d0
+ syrxi = 0.0d0
+ sxryi = 0.0d0
+ sxrxi = 0.0d0
+ syryi = 0.0d0
+ do i = 1, npts {
+ sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0)
+ syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0)
+ syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0)
+ sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0)
+ sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0)
+ syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0)
+ }
+
+ # Compute the rotation angle.
+ num = 2.0d0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi)
+ denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - sxrxr *
+ (syrxi + syryi) * (syrxi - syryi)
+ if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) {
+ theta = 0.0d0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ theta = atan2 (num, denom) / 2.0d0
+ if (theta < 0.0d0)
+ theta = theta + TWOPI
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+ ctheta = cos (theta)
+ stheta = sin (theta)
+
+ # Compute the x magnification factor.
+ num = sxrxi * ctheta - sxryi * stheta
+ denom = sxrxr
+ if (denom <= 0.0d0) {
+ xmag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ xmag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the y magnification factor.
+ num = syrxi * stheta + syryi * ctheta
+ denom = syryr
+ if (denom <= 0.0d0) {
+ ymag = 1.0
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "Warning singular X fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.")
+ call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.")
+ }
+ } else {
+ ymag = num / denom
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (xerrmsg, xmaxch, "X fit ok.")
+ call sprintf (yerrmsg, ymaxch, "Y fit ok.")
+ } else {
+ call sprintf (xerrmsg, xmaxch, "XI fit ok.")
+ call sprintf (yerrmsg, ymaxch, "ETA fit ok.")
+ }
+ }
+
+ # Compute the polynomial coefficients.
+ cthetax = xmag * ctheta
+ sthetax = ymag * stheta
+ sthetay = xmag * stheta
+ cthetay = ymag * ctheta
+
+ # Compute the x fit coefficients.
+ call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sx1, Memd[savefit])
+ call dgsfree (sx1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax)
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 *
+ sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sx1, Memd[savefit])
+
+ # Compute the y fit coefficients.
+ call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sy1, Memd[savefit])
+ call dgsfree (sy1)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay)
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 *
+ cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay *
+ (ymin + ymax) / 2.0
+ Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0
+ Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0
+ }
+ call dgsrestore (sy1, Memd[savefit])
+
+ # Compute the residuals
+ call dgsvector (sx1, xref, yref, xresid, npts)
+ call dgsvector (sy1, xref, yref, yresid, npts)
+ call asubd (xin, xresid, xresid, npts)
+ call asubd (yin, yresid, yresid, npts)
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Compute the rms of the x and y fits.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2
+
+ GM_NPTS(fit) = npts
+
+ }
+
+ call sfree (sp)
+end
+
+
+# GEO_FXY -- Fit the surface.
+
+procedure geo_fxyd (fit, sf1, sf2, x, y, z, wts, resid, npts, xfit, errmsg,
+ maxch)
+
+pointer fit #I pointer to the fit sturcture
+pointer sf1 #U pointer to linear surface
+pointer sf2 #U pointer to higher order surface
+double x[npts] #I reference image x values
+double y[npts] #I reference image y values
+double z[npts] #I z values
+double wts[npts] #I array of weights
+double resid[npts] #O fitted residuals
+int npts #I number of points
+int xfit #I X fit ?
+char errmsg[ARB] #O returned error message
+int maxch #I maximum number of characters in error message
+
+int i, ier, ncoeff
+pointer sp, zfit, savefit, coeff
+double xmin, xmax, ymin, ymax
+bool fp_equald()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (zfit, npts, TY_DOUBLE)
+ call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE)
+ call salloc (coeff, 3, TY_DOUBLE)
+
+ # Determine the minimum and maximum values
+ if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) {
+ xmin = GM_XMIN(fit) - 0.5d0
+ xmax = GM_XMAX(fit) + 0.5d0
+ } else {
+ xmin = GM_XMIN(fit)
+ xmax = GM_XMAX(fit)
+ }
+ if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) {
+ ymin = GM_YMIN(fit) - 0.5d0
+ ymax = GM_YMAX(fit) + 0.5d0
+ } else {
+ ymin = GM_YMIN(fit)
+ ymax = GM_YMAX(fit)
+ }
+
+ # Initalize fit
+ if (sf1 != NULL)
+ call dgsfree (sf1)
+ if (sf2 != NULL)
+ call dgsfree (sf2)
+
+ if (xfit == YES) {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sf1, Memd[savefit])
+ call dgsfree (sf1)
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubd (z, x, Memd[zfit], npts)
+ call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier)
+ call dgscoeff (sf1, Memd[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff]
+ Memd[savefit+GS_SAVECOEFF+1] = 1.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 0.0d0
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (xmax + xmin) /
+ 2.0d0
+ Memd[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 0.0d0
+ }
+ call dgsfree (sf1)
+ call dgsrestore (sf1, Memd[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsset (sf1, GSXREF, GM_XO(fit))
+ call dgsset (sf1, GSYREF, GM_YO(fit))
+ call dgsset (sf1, GSZREF, GM_ZO(fit))
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 ||
+ GM_XXTERMS(fit) == GS_XFULL)
+ call dgsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit),
+ GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+
+ } else {
+
+ switch (GM_FIT(fit)) {
+
+ case GM_SHIFT:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgssave (sf1, Memd[savefit])
+ call dgsfree (sf1)
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call asubd (z, y, Memd[zfit], npts)
+ call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier)
+ call dgscoeff (sf1, Memd[coeff], ncoeff)
+ if (GM_FUNCTION(fit) == GS_POLYNOMIAL) {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff]
+ Memd[savefit+GS_SAVECOEFF+1] = 0.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = 1.0d0
+ } else {
+ Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (ymin + ymax) /
+ 2.0d0
+ Memd[savefit+GS_SAVECOEFF+1] = 0.0d0
+ Memd[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0d0
+ }
+ call dgsfree (sf1)
+ call dgsrestore (sf1, Memd[savefit])
+ sf2 = NULL
+
+ case GM_XYSCALE:
+ call dgsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ sf2 = NULL
+
+ default:
+ call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsset (sf1, GSXREF, GM_XO(fit))
+ call dgsset (sf1, GSYREF, GM_YO(fit))
+ call dgsset (sf1, GSZREF, GM_ZO(fit))
+ call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier)
+ if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 ||
+ GM_YXTERMS(fit) == GS_XFULL)
+ call dgsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit),
+ GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin,
+ ymax)
+ else
+ sf2 = NULL
+ }
+ }
+
+
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+
+ call dgsvector (sf1, x, y, resid, npts)
+ call asubd (z, resid, resid, npts)
+
+ # Calculate higher order fit.
+ if (sf2 != NULL) {
+ call dgsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier)
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for X fit.")
+ call error (1, "Too few data points for X fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for XI fit.")
+ call error (1, "Too few data points for XI fit.")
+ }
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call sprintf (errmsg, maxch,
+ "Too few data points for Y fit.")
+ call error (1, "Too few data points for Y fit.")
+ } else {
+ call sprintf (errmsg, maxch,
+ "Too few data points for ETA fit.")
+ call error (1, "Too few data points for ETA fit.")
+ }
+ }
+ } else if (ier == SINGULAR) {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular X fit.")
+ else
+ call sprintf (errmsg, maxch, "Warning singular XI fit.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Warning singular Y fit.")
+ else
+ call sprintf (errmsg, maxch,
+ "Warning singular ETA fit.")
+ }
+ } else {
+ if (xfit == YES) {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "X fit ok.")
+ else
+ call sprintf (errmsg, maxch, "XI fit ok.")
+ } else {
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (errmsg, maxch, "Y fit ok.")
+ else
+ call sprintf (errmsg, maxch, "ETA fit ok.")
+ }
+ }
+ call dgsvector (sf2, x, y, Memd[zfit], npts)
+ call asubd (resid, Memd[zfit], resid, npts)
+ }
+
+ # Compute the number of zero weighted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # calculate the rms of the fit
+ if (xfit == YES) {
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * resid[i] ** 2
+ } else {
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * resid[i] ** 2
+ }
+
+ GM_NPTS(fit) = npts
+
+ call sfree (sp)
+end
+
+
+# GEO_MREJECT -- Reject points from the fit.
+
+procedure geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts,
+ xresid, yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch)
+
+pointer fit #I pointer to the fit structure
+pointer sx1, sy1 #I pointers to the linear surface
+pointer sx2, sy2 #I pointers to the higher order surface
+double xref[npts] #I reference image x values
+double yref[npts] #I yreference values
+double xin[npts] #I x values
+double yin[npts] #I yvalues
+double wts[npts] #I weights
+double xresid[npts] #I residuals
+double yresid[npts] #I yresiduals
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x error message
+int xmaxch #I maximum number of characters in the x error message
+char yerrmsg[ARB] #O the output y error message
+int ymaxch #I maximum number of characters in the y error message
+
+int i
+int nreject, niter
+pointer sp, twts
+double cutx, cuty
+errchk geo_fxyd(), geo_fthetad(), geo_fmagnifyd(), geo_flineard()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (twts, npts, TY_DOUBLE)
+
+ # Allocate space for the residuals.
+ if (GM_REJ(fit) != NULL)
+ call mfree (GM_REJ(fit), TY_INT)
+ call malloc (GM_REJ(fit), npts, TY_INT)
+ GM_NREJECT(fit) = 0
+
+ # Initialize the temporary weights array and the number of rejected
+ # points.
+ call amovd (wts, Memd[twts], npts)
+ nreject = 0
+
+ niter = 0
+ repeat {
+
+ # Compute the rejection limits.
+ if ((npts - GM_NWTS0(fit)) > 1) {
+ cutx = GM_REJECT(fit) * sqrt (GM_XRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ cuty = GM_REJECT(fit) * sqrt (GM_YRMS(fit) / (npts -
+ GM_NWTS0(fit) - 1))
+ } else {
+ cutx = MAX_REAL
+ cuty = MAX_REAL
+ }
+
+ # Reject points from the fit.
+ do i = 1, npts {
+ if (Memd[twts+i-1] > 0.0 && ((abs (xresid[i]) > cutx) ||
+ (abs (yresid[i]) > cuty))) {
+ Memd[twts+i-1] = double(0.0)
+ nreject = nreject + 1
+ Memi[GM_REJ(fit)+nreject-1] = i
+ }
+ }
+ if ((nreject - GM_NREJECT(fit)) <= 0)
+ break
+ GM_NREJECT(fit) = nreject
+
+ # Compute number of deleted points.
+ GM_NWTS0(fit) = 0
+ do i = 1, npts {
+ if (wts[i] <= 0.0)
+ GM_NWTS0(fit) = GM_NWTS0(fit) + 1
+ }
+
+ # Recompute the X and Y fit.
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin,
+ Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin,
+ Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin,
+ Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch,
+ yerrmsg, ymaxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ GM_ZO(fit) = GM_XOREF(fit)
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin, Memd[twts],
+ xresid, npts, YES, xerrmsg, xmaxch)
+ GM_ZO(fit) = GM_YOREF(fit)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin, Memd[twts],
+ yresid, npts, NO, yerrmsg, ymaxch)
+ }
+
+ # Compute the x fit rms.
+ GM_XRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_XRMS(fit) = GM_XRMS(fit) + Memd[twts+i-1] * xresid[i] ** 2
+
+ # Compute the y fit rms.
+ GM_YRMS(fit) = 0.0d0
+ do i = 1, npts
+ GM_YRMS(fit) = GM_YRMS(fit) + Memd[twts+i-1] * yresid[i] ** 2
+
+ niter = niter + 1
+
+ } until (niter >= GM_MAXITER(fit))
+
+ call sfree (sp)
+end
+
+
+# GEO_MMFREE - Free the space used to fit the surfaces.
+
+procedure geo_mmfreed (sx1, sy1, sx2, sy2)
+
+pointer sx1 #U pointer to the x fits
+pointer sy1 #U pointer to the y fit
+pointer sx2 #U pointer to the higher order x fit
+pointer sy2 #U pointer to the higher order y fit
+
+begin
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+ if (sx2 != NULL)
+ call dgsfree (sx2)
+ if (sy2 != NULL)
+ call dgsfree (sy2)
+end
+
+
diff --git a/pkg/images/lib/geogmap.gx b/pkg/images/lib/geogmap.gx
new file mode 100644
index 00000000..e52a129e
--- /dev/null
+++ b/pkg/images/lib/geogmap.gx
@@ -0,0 +1,494 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <math.h>
+include <math/gsurfit.h>
+include <gset.h>
+include "geomap.h"
+include "geogmap.h"
+
+define GHELPFILE "images$lib/geomap.key"
+define CHELPFILE "images$lib/coomap.key"
+
+$for (rd)
+
+# GEO_MGFIT -- Fit the surface using interactive graphics.
+
+procedure geo_mgfit$t (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, npts, xerrmsg, yerrmsg, maxch)
+
+pointer gd #I graphics file descriptor
+pointer fit #I pointer to the fit structure
+pointer sx1 #I pointer to the linear x surface fit
+pointer sy1 #I pointer to the linear y surface fit
+pointer sx2 #I pointer to higher order x surface fit
+pointer sy2 #I pointer to higher order y surface fit
+PIXEL xref[npts] #I the x reference coordinates
+PIXEL yref[npts] #I the y reference coordinates
+PIXEL xin[npts] #I input x coordinates
+PIXEL yin[npts] #I input y coordinates
+PIXEL wts[npts] #I array of weights
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x fit error message
+char yerrmsg[ARB] #O the output x fit error message
+int maxch #I the size of the error messages
+
+char errstr[SZ_LINE]
+int newgraph, delete, wcs, key, errcode
+pointer sp, w, gfit, xresid, yresid, cmd
+pointer gt1, gt2, gt3, gt4, gt5
+real wx, wy
+PIXEL xshift, yshift, xscale, yscale, thetax, thetay
+
+int clgcur(), errget()
+pointer gt_init()
+
+errchk geo_fxy$t(), geo_mreject$t(), geo_ftheta$t()
+errchk geo_fmagnify$t(), geo_flinear$t()
+
+begin
+ # Initialize gfit structure and working space.
+ call smark (sp)
+ call salloc (gfit, LEN_GEOGRAPH, TY_STRUCT)
+ call salloc (xresid, npts, TY_PIXEL)
+ call salloc (yresid, npts, TY_PIXEL)
+ call salloc (w, npts, TY_PIXEL)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Do initial fit.
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_ftheta$t (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Mem$t[xresid], Mem$t[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnify$t (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Mem$t[xresid], Mem$t[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinear$t (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Mem$t[xresid], Mem$t[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxy$t (fit, sx1, sx2, xref, yref, xin, wts,
+ Mem$t[xresid], npts, YES, xerrmsg, maxch)
+ call geo_fxy$t (fit, sy1, sy2, xref, yref, yin, wts,
+ Mem$t[yresid], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mreject$t (fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, Mem$t[xresid], Mem$t[yresid], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+ } then {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call error (2, "Too few points for X and Y fits.")
+ else
+ call error (2, "Too few points for XI and ETA fits.")
+ }
+
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+
+ # Set up plotting defaults.
+ GG_PLOTTYPE(gfit) = FIT
+ GG_OVERPLOT(gfit) = NO
+ GG_CONSTXY(gfit) = YES
+ newgraph = NO
+
+ # Allocate graphics tools.
+ gt1 = gt_init ()
+ gt2 = gt_init ()
+ gt3 = gt_init ()
+ gt4 = gt_init ()
+ gt5 = gt_init ()
+
+ # Set the plot title and x and y axis labels.
+ call geo_gtset (FIT, gt1, fit)
+ call geo_gtset (XXRESID, gt2, fit)
+ call geo_gtset (XYRESID, gt3, fit)
+ call geo_gtset (YXRESID, gt4, fit)
+ call geo_gtset (YYRESID, gt5, fit)
+
+ # Make the first plot.
+ call gclear (gd)
+ call geo_label (FIT, gt1, fit)
+ call geo_1graph$t (gd, gt1, fit, gfit, xref, yref, xin, yin, wts,
+ npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxy$t (gd, fit, sx1, sy1, sx2, sy2)
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+
+ # Read the cursor commands.
+ call amov$t (wts, Mem$t[w], npts)
+ while (clgcur ("cursor", wx, wy, wcs, key, Memc[cmd], SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ call amov$t (Mem$t[w], wts, npts)
+ break
+
+ case '?':
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call gpagefile (gd, GHELPFILE, "")
+ else
+ call gpagefile (gd, CHELPFILE, "")
+
+ case ':':
+ call geo_colon (gd, fit, gfit, Memc[cmd], newgraph)
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call gt_colon (Memc[cmd], gd, gt1, newgraph)
+ case XXRESID:
+ call gt_colon (Memc[cmd], gd, gt2, newgraph)
+ case XYRESID:
+ call gt_colon (Memc[cmd], gd, gt3, newgraph)
+ case YXRESID:
+ call gt_colon (Memc[cmd], gd, gt4, newgraph)
+ case YYRESID:
+ call gt_colon (Memc[cmd], gd, gt5, newgraph)
+ }
+
+ case 'l':
+ if (GG_FITERROR(gfit) == NO) {
+ call geo_lcoeff$t (sx1, sy1, xshift, yshift, xscale, yscale,
+ thetax, thetay)
+ call printf ("xshift: %.2f yshift: %.2f ")
+ call parg$t (xshift)
+ call parg$t (yshift)
+ call printf ("xmag: %0.3g ymag: %0.3g ")
+ call parg$t (xscale)
+ call parg$t (yscale)
+ call printf ("xrot: %.2f yrot: %.2f\n")
+ call parg$t (thetax)
+ call parg$t (thetay)
+ }
+
+ case 't':
+ if (GG_FITERROR(gfit) == NO && GG_PLOTTYPE(gfit) == FIT)
+ call geo_lxy$t (gd, fit, sx1, sy1, sx2, sy2, xref, yref,
+ xin, yin, npts, wx, wy)
+
+ case 'c':
+ if (GG_CONSTXY(gfit) == YES)
+ GG_CONSTXY(gfit) = NO
+ else if (GG_CONSTXY(gfit) == NO)
+ GG_CONSTXY(gfit) = YES
+
+ case 'd', 'u':
+ if (key == 'd')
+ delete = YES
+ else
+ delete = NO
+
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_1delete$t (gd, xin, yin, Mem$t[w], wts, npts, wx,
+ wy, delete)
+ case XXRESID:
+ call geo_2delete$t (gd, xref, Mem$t[xresid], Mem$t[w], wts,
+ npts, wx, wy, delete)
+ case XYRESID:
+ call geo_2delete$t (gd, yref, Mem$t[xresid], Mem$t[w], wts,
+ npts, wx, wy, delete)
+ case YXRESID:
+ call geo_2delete$t (gd, xref, Mem$t[yresid], Mem$t[w], wts,
+ npts, wx, wy, delete)
+ case YYRESID:
+ call geo_2delete$t (gd, yref, Mem$t[yresid], Mem$t[w], wts,
+ npts, wx, wy, delete)
+ }
+
+ GG_NEWFUNCTION(gfit) = YES
+
+ case 'g':
+ if (GG_PLOTTYPE(gfit) != FIT)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = FIT
+
+ case 'x':
+ if (GG_PLOTTYPE(gfit) != XXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XXRESID
+
+ case 'r':
+ if (GG_PLOTTYPE(gfit) != XYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XYRESID
+
+ case 'y':
+ if (GG_PLOTTYPE(gfit) != YXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YXRESID
+
+ case 's':
+ if (GG_PLOTTYPE(gfit) != YYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YYRESID
+
+ case 'f':
+ # do fit
+ if (GG_NEWFUNCTION(gfit) == YES) {
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_ftheta$t (fit, sx1, sy1, xref, yref, xin,
+ yin, Mem$t[w], Mem$t[xresid], Mem$t[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnify$t (fit, sx1, sy1, xref, yref, xin,
+ yin, Mem$t[w], Mem$t[xresid], Mem$t[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinear$t (fit, sx1, sy1, xref, yref, xin,
+ yin, Mem$t[w], Mem$t[xresid], Mem$t[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxy$t (fit, sx1, sx2, xref, yref, xin,
+ Mem$t[w], Mem$t[xresid], npts, YES,
+ xerrmsg, maxch)
+ call geo_fxy$t (fit, sy1, sy2, xref, yref, yin,
+ Mem$t[w], Mem$t[yresid], npts, NO,
+ yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mreject$t (fit, sx1, sy1, sx2, sy2, xref,
+ yref, xin, yin, Mem$t[w], Mem$t[xresid],
+ Mem$t[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+ } then {
+ errcode = errget (errstr, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (errstr)
+ GG_FITERROR(gfit) = YES
+ }
+ }
+
+ # plot new graph
+ if (GG_FITERROR(gfit) == YES)
+ newgraph = NO
+ else
+ newgraph = YES
+
+ case 'o':
+ GG_OVERPLOT(gfit) = YES
+
+ default:
+ call printf ("\07")
+
+ }
+
+ if (newgraph == YES) {
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_label (FIT, gt1, fit)
+ call geo_1graph$t (gd, gt1, fit, gfit, xref, yref, xin, yin,
+ Mem$t[w], npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxy$t (gd, fit, sx1, sy1, sx2, sy2)
+ case XXRESID:
+ call geo_label (XXRESID, gt2, fit)
+ call geo_2graph$t (gd, gt2, fit, gfit, xref, Mem$t[xresid],
+ Mem$t[w], npts)
+ case XYRESID:
+ call geo_label (XYRESID, gt3, fit)
+ call geo_2graph$t (gd, gt3, fit, gfit, yref, Mem$t[xresid],
+ Mem$t[w], npts)
+ case YXRESID:
+ call geo_label (YXRESID, gt4, fit)
+ call geo_2graph$t (gd, gt4, fit, gfit, xref, Mem$t[yresid],
+ Mem$t[w], npts)
+ case YYRESID:
+ call geo_label (YYRESID, gt5, fit)
+ call geo_2graph$t (gd, gt5, fit, gfit, yref, Mem$t[yresid],
+ Mem$t[w], npts)
+ }
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+ newgraph = NO
+ }
+ }
+
+ # Free space.
+ call gt_free (gt1)
+ call gt_free (gt2)
+ call gt_free (gt3)
+ call gt_free (gt4)
+ call gt_free (gt5)
+ call sfree (sp)
+
+ # Call an error if appropriate.
+ if (errcode > 0)
+ call error (2, errstr)
+end
+
+# GEO_LCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift, xexpansion, yexpansion, x and y rotations.
+
+procedure geo_lcoeff$t (sx, sy, xshift, yshift, xscale, yscale, xrot, yrot)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+PIXEL xshift #O output x shift
+PIXEL yshift #O output y shift
+PIXEL xscale #O output x scale
+PIXEL yscale #O output y scale
+PIXEL xrot #O rotation of point on x axis
+PIXEL yrot #O rotation of point on y axis
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+PIXEL xxrange, xyrange, xxmaxmin, xymaxmin
+PIXEL yxrange, yyrange, yxmaxmin, yymaxmin
+PIXEL a, b, c, d
+
+bool fp_equal$t()
+$if (datatype == r)
+int gsgeti()
+real gsgetr()
+$else
+int dgsgeti()
+double dgsgetd()
+$endif
+
+begin
+ # Allocate working space.
+ call smark (sp)
+$if (datatype == r)
+ call salloc (xcoeff, gsgeti (sx, GSNCOEFF), TY_PIXEL)
+ call salloc (ycoeff, gsgeti (sy, GSNCOEFF), TY_PIXEL)
+$else
+ call salloc (xcoeff, dgsgeti (sx, GSNCOEFF), TY_PIXEL)
+ call salloc (ycoeff, dgsgeti (sy, GSNCOEFF), TY_PIXEL)
+$endif
+
+ # Get coefficients and numbers of coefficients.
+$if (datatype == r)
+ call gscoeff (sx, Mem$t[xcoeff], nxxcoeff)
+ call gscoeff (sy, Mem$t[ycoeff], nyycoeff)
+ nxxcoeff = gsgeti (sx, GSNXCOEFF)
+ nxycoeff = gsgeti (sx, GSNYCOEFF)
+ nyxcoeff = gsgeti (sy, GSNXCOEFF)
+ nyycoeff = gsgeti (sy, GSNYCOEFF)
+$else
+ call dgscoeff (sx, Mem$t[xcoeff], nxxcoeff)
+ call dgscoeff (sy, Mem$t[ycoeff], nyycoeff)
+ nxxcoeff = dgsgeti (sx, GSNXCOEFF)
+ nxycoeff = dgsgeti (sx, GSNYCOEFF)
+ nyxcoeff = dgsgeti (sy, GSNXCOEFF)
+ nyycoeff = dgsgeti (sy, GSNYCOEFF)
+$endif
+
+ # Get the data range.
+$if (datatype == r)
+ if (gsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (gsgetr (sx, GSXMAX) - gsgetr (sx, GSXMIN)) / 2.0
+ xxmaxmin = - (gsgetr (sx, GSXMAX) + gsgetr (sx, GSXMIN)) / 2.0
+ xyrange = (gsgetr (sx, GSYMAX) - gsgetr (sx, GSYMIN)) / 2.0
+ xymaxmin = - (gsgetr (sx, GSYMAX) + gsgetr (sx, GSYMIN)) / 2.0
+$else
+ if (dgsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (dgsgetd (sx, GSXMAX) - dgsgetd (sx, GSXMIN)) / 2.0d0
+ xxmaxmin = - (dgsgetd (sx, GSXMAX) + dgsgetd (sx, GSXMIN)) / 2.0d0
+ xyrange = (dgsgetd (sx, GSYMAX) - dgsgetd (sx, GSYMIN)) / 2.0d0
+ xymaxmin = - (dgsgetd (sx, GSYMAX) + dgsgetd (sx, GSYMIN)) / 2.0d0
+$endif
+ } else {
+ xxrange = PIXEL(1.0)
+ xxmaxmin = PIXEL(0.0)
+ xyrange = PIXEL(1.0)
+ xymaxmin = PIXEL(0.0)
+ }
+
+$if (datatype == r)
+ if (gsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (gsgetr (sy, GSXMAX) - gsgetr (sy, GSXMIN)) / 2.0
+ yxmaxmin = - (gsgetr (sy, GSXMAX) + gsgetr (sy, GSXMIN)) / 2.0
+ yyrange = (gsgetr (sy, GSYMAX) - gsgetr (sy, GSYMIN)) / 2.0
+ yymaxmin = - (gsgetr (sy, GSYMAX) + gsgetr (sy, GSYMIN)) / 2.0
+$else
+ if (dgsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (dgsgetd (sy, GSXMAX) - dgsgetd (sy, GSXMIN)) / 2.0d0
+ yxmaxmin = - (dgsgetd (sy, GSXMAX) + dgsgetd (sy, GSXMIN)) / 2.0d0
+ yyrange = (dgsgetd (sy, GSYMAX) - dgsgetd (sy, GSYMIN)) / 2.0d0
+ yymaxmin = - (dgsgetd (sy, GSYMAX) + dgsgetd (sy, GSYMIN)) / 2.0d0
+$endif
+ } else {
+ yxrange = PIXEL(1.0)
+ yxmaxmin = PIXEL(0.0)
+ yyrange = PIXEL(1.0)
+ yymaxmin = PIXEL(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Mem$t[xcoeff] + Mem$t[xcoeff+1] * xxmaxmin / xxrange +
+ Mem$t[xcoeff+2] * xymaxmin / xyrange
+ yshift = Mem$t[ycoeff] + Mem$t[ycoeff+1] * yxmaxmin / yxrange +
+ Mem$t[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Mem$t[xcoeff+1] / xxrange
+ else
+ a = PIXEL(0.0)
+ if (nxycoeff > 1)
+ b = Mem$t[xcoeff+nxxcoeff] / xyrange
+ else
+ b = PIXEL(0.0)
+ if (nyxcoeff > 1)
+ c = Mem$t[ycoeff+1] / yxrange
+ else
+ c = PIXEL(0.0)
+ if (nyycoeff > 1)
+ d = Mem$t[ycoeff+nyxcoeff] / yyrange
+ else
+ d = PIXEL(0.0)
+
+ # Get the magnification factors.
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+
+ # Get the x and y axes rotation factors.
+ if (fp_equal$t (a, PIXEL(0.0)) && fp_equal$t (c, PIXEL(0.0)))
+ xrot = PIXEL(0.0)
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < PIXEL(0.0))
+ xrot = xrot + PIXEL(360.0)
+
+ if (fp_equal$t (b, PIXEL(0.0)) && fp_equal$t (d, PIXEL(0.0)))
+ yrot = PIXEL(0.0)
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < PIXEL(0.0))
+ yrot = yrot + PIXEL(360.0)
+
+ call sfree (sp)
+end
+
+$endfor
diff --git a/pkg/images/lib/geogmap.h b/pkg/images/lib/geogmap.h
new file mode 100644
index 00000000..7efc3658
--- /dev/null
+++ b/pkg/images/lib/geogmap.h
@@ -0,0 +1,37 @@
+# Structure definitions for fitting surface graphically
+
+define LEN_GEOGRAPH 10
+
+define GG_NEWFUNCTION Memi[$1] # New function
+define GG_PLOTTYPE Memi[$1+1] # Type of plot
+define GG_OVERPLOT Memi[$1+2] # Overplot previous graph?
+define GG_FITERROR Memi[$1+3] # Error fitting x function
+define GG_CONSTXY Memi[$1+4] # Plot lines of constant x-y
+
+# define plot types
+
+define FIT 1 # plot x y fit
+define XXRESID 2 # x fit residuals versus x
+define XYRESID 3 # x fit residuals versus y
+define YXRESID 4 # y fit residuals versus x
+define YYRESID 5 # y fit residuals versus y
+
+# define the permitted colon commands
+
+define GM_CMDS "|show|projection|refpoint|fitgeometry|function|\
+order|xxorder|xyorder|yxorder|yyorder|xxterms|yxterms|reject|maxiter|"
+
+define GMCMD_SHOW 1
+define GMCMD_PROJECTION 2
+define GMCMD_REFPOINT 3
+define GMCMD_GEOMETRY 4
+define GMCMD_FUNCTION 5
+define GMCMD_ORDER 6
+define GMCMD_XXORDER 7
+define GMCMD_XYORDER 8
+define GMCMD_YXORDER 9
+define GMCMD_YYORDER 10
+define GMCMD_XXTERMS 11
+define GMCMD_YXTERMS 12
+define GMCMD_REJECT 13
+define GMCMD_MAXITER 14
diff --git a/pkg/images/lib/geogmap.x b/pkg/images/lib/geogmap.x
new file mode 100644
index 00000000..9dc63610
--- /dev/null
+++ b/pkg/images/lib/geogmap.x
@@ -0,0 +1,905 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <math.h>
+include <math/gsurfit.h>
+include <gset.h>
+include "geomap.h"
+include "geogmap.h"
+
+define GHELPFILE "images$lib/geomap.key"
+define CHELPFILE "images$lib/coomap.key"
+
+
+
+# GEO_MGFIT -- Fit the surface using interactive graphics.
+
+procedure geo_mgfitr (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, npts, xerrmsg, yerrmsg, maxch)
+
+pointer gd #I graphics file descriptor
+pointer fit #I pointer to the fit structure
+pointer sx1 #I pointer to the linear x surface fit
+pointer sy1 #I pointer to the linear y surface fit
+pointer sx2 #I pointer to higher order x surface fit
+pointer sy2 #I pointer to higher order y surface fit
+real xref[npts] #I the x reference coordinates
+real yref[npts] #I the y reference coordinates
+real xin[npts] #I input x coordinates
+real yin[npts] #I input y coordinates
+real wts[npts] #I array of weights
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x fit error message
+char yerrmsg[ARB] #O the output x fit error message
+int maxch #I the size of the error messages
+
+char errstr[SZ_LINE]
+int newgraph, delete, wcs, key, errcode
+pointer sp, w, gfit, xresid, yresid, cmd
+pointer gt1, gt2, gt3, gt4, gt5
+real wx, wy
+real xshift, yshift, xscale, yscale, thetax, thetay
+
+int clgcur(), errget()
+pointer gt_init()
+
+errchk geo_fxyr(), geo_mrejectr(), geo_fthetar()
+errchk geo_fmagnifyr(), geo_flinearr()
+
+begin
+ # Initialize gfit structure and working space.
+ call smark (sp)
+ call salloc (gfit, LEN_GEOGRAPH, TY_STRUCT)
+ call salloc (xresid, npts, TY_REAL)
+ call salloc (yresid, npts, TY_REAL)
+ call salloc (w, npts, TY_REAL)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Do initial fit.
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresid], Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresid], Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresid], Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin, wts,
+ Memr[xresid], npts, YES, xerrmsg, maxch)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin, wts,
+ Memr[yresid], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, Memr[xresid], Memr[yresid], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+ } then {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call error (2, "Too few points for X and Y fits.")
+ else
+ call error (2, "Too few points for XI and ETA fits.")
+ }
+
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+
+ # Set up plotting defaults.
+ GG_PLOTTYPE(gfit) = FIT
+ GG_OVERPLOT(gfit) = NO
+ GG_CONSTXY(gfit) = YES
+ newgraph = NO
+
+ # Allocate graphics tools.
+ gt1 = gt_init ()
+ gt2 = gt_init ()
+ gt3 = gt_init ()
+ gt4 = gt_init ()
+ gt5 = gt_init ()
+
+ # Set the plot title and x and y axis labels.
+ call geo_gtset (FIT, gt1, fit)
+ call geo_gtset (XXRESID, gt2, fit)
+ call geo_gtset (XYRESID, gt3, fit)
+ call geo_gtset (YXRESID, gt4, fit)
+ call geo_gtset (YYRESID, gt5, fit)
+
+ # Make the first plot.
+ call gclear (gd)
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphr (gd, gt1, fit, gfit, xref, yref, xin, yin, wts,
+ npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyr (gd, fit, sx1, sy1, sx2, sy2)
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+
+ # Read the cursor commands.
+ call amovr (wts, Memr[w], npts)
+ while (clgcur ("cursor", wx, wy, wcs, key, Memc[cmd], SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ call amovr (Memr[w], wts, npts)
+ break
+
+ case '?':
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call gpagefile (gd, GHELPFILE, "")
+ else
+ call gpagefile (gd, CHELPFILE, "")
+
+ case ':':
+ call geo_colon (gd, fit, gfit, Memc[cmd], newgraph)
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call gt_colon (Memc[cmd], gd, gt1, newgraph)
+ case XXRESID:
+ call gt_colon (Memc[cmd], gd, gt2, newgraph)
+ case XYRESID:
+ call gt_colon (Memc[cmd], gd, gt3, newgraph)
+ case YXRESID:
+ call gt_colon (Memc[cmd], gd, gt4, newgraph)
+ case YYRESID:
+ call gt_colon (Memc[cmd], gd, gt5, newgraph)
+ }
+
+ case 'l':
+ if (GG_FITERROR(gfit) == NO) {
+ call geo_lcoeffr (sx1, sy1, xshift, yshift, xscale, yscale,
+ thetax, thetay)
+ call printf ("xshift: %.2f yshift: %.2f ")
+ call pargr (xshift)
+ call pargr (yshift)
+ call printf ("xmag: %0.3g ymag: %0.3g ")
+ call pargr (xscale)
+ call pargr (yscale)
+ call printf ("xrot: %.2f yrot: %.2f\n")
+ call pargr (thetax)
+ call pargr (thetay)
+ }
+
+ case 't':
+ if (GG_FITERROR(gfit) == NO && GG_PLOTTYPE(gfit) == FIT)
+ call geo_lxyr (gd, fit, sx1, sy1, sx2, sy2, xref, yref,
+ xin, yin, npts, wx, wy)
+
+ case 'c':
+ if (GG_CONSTXY(gfit) == YES)
+ GG_CONSTXY(gfit) = NO
+ else if (GG_CONSTXY(gfit) == NO)
+ GG_CONSTXY(gfit) = YES
+
+ case 'd', 'u':
+ if (key == 'd')
+ delete = YES
+ else
+ delete = NO
+
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_1deleter (gd, xin, yin, Memr[w], wts, npts, wx,
+ wy, delete)
+ case XXRESID:
+ call geo_2deleter (gd, xref, Memr[xresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ case XYRESID:
+ call geo_2deleter (gd, yref, Memr[xresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ case YXRESID:
+ call geo_2deleter (gd, xref, Memr[yresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ case YYRESID:
+ call geo_2deleter (gd, yref, Memr[yresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ }
+
+ GG_NEWFUNCTION(gfit) = YES
+
+ case 'g':
+ if (GG_PLOTTYPE(gfit) != FIT)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = FIT
+
+ case 'x':
+ if (GG_PLOTTYPE(gfit) != XXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XXRESID
+
+ case 'r':
+ if (GG_PLOTTYPE(gfit) != XYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XYRESID
+
+ case 'y':
+ if (GG_PLOTTYPE(gfit) != YXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YXRESID
+
+ case 's':
+ if (GG_PLOTTYPE(gfit) != YYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YYRESID
+
+ case 'f':
+ # do fit
+ if (GG_NEWFUNCTION(gfit) == YES) {
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin,
+ yin, Memr[w], Memr[xresid], Memr[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin,
+ yin, Memr[w], Memr[xresid], Memr[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin,
+ yin, Memr[w], Memr[xresid], Memr[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin,
+ Memr[w], Memr[xresid], npts, YES,
+ xerrmsg, maxch)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin,
+ Memr[w], Memr[yresid], npts, NO,
+ yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref,
+ yref, xin, yin, Memr[w], Memr[xresid],
+ Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+ } then {
+ errcode = errget (errstr, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (errstr)
+ GG_FITERROR(gfit) = YES
+ }
+ }
+
+ # plot new graph
+ if (GG_FITERROR(gfit) == YES)
+ newgraph = NO
+ else
+ newgraph = YES
+
+ case 'o':
+ GG_OVERPLOT(gfit) = YES
+
+ default:
+ call printf ("\07")
+
+ }
+
+ if (newgraph == YES) {
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphr (gd, gt1, fit, gfit, xref, yref, xin, yin,
+ Memr[w], npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyr (gd, fit, sx1, sy1, sx2, sy2)
+ case XXRESID:
+ call geo_label (XXRESID, gt2, fit)
+ call geo_2graphr (gd, gt2, fit, gfit, xref, Memr[xresid],
+ Memr[w], npts)
+ case XYRESID:
+ call geo_label (XYRESID, gt3, fit)
+ call geo_2graphr (gd, gt3, fit, gfit, yref, Memr[xresid],
+ Memr[w], npts)
+ case YXRESID:
+ call geo_label (YXRESID, gt4, fit)
+ call geo_2graphr (gd, gt4, fit, gfit, xref, Memr[yresid],
+ Memr[w], npts)
+ case YYRESID:
+ call geo_label (YYRESID, gt5, fit)
+ call geo_2graphr (gd, gt5, fit, gfit, yref, Memr[yresid],
+ Memr[w], npts)
+ }
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+ newgraph = NO
+ }
+ }
+
+ # Free space.
+ call gt_free (gt1)
+ call gt_free (gt2)
+ call gt_free (gt3)
+ call gt_free (gt4)
+ call gt_free (gt5)
+ call sfree (sp)
+
+ # Call an error if appropriate.
+ if (errcode > 0)
+ call error (2, errstr)
+end
+
+# GEO_LCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift, xexpansion, yexpansion, x and y rotations.
+
+procedure geo_lcoeffr (sx, sy, xshift, yshift, xscale, yscale, xrot, yrot)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+real xshift #O output x shift
+real yshift #O output y shift
+real xscale #O output x scale
+real yscale #O output y scale
+real xrot #O rotation of point on x axis
+real yrot #O rotation of point on y axis
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+real xxrange, xyrange, xxmaxmin, xymaxmin
+real yxrange, yyrange, yxmaxmin, yymaxmin
+real a, b, c, d
+
+bool fp_equalr()
+int gsgeti()
+real gsgetr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xcoeff, gsgeti (sx, GSNCOEFF), TY_REAL)
+ call salloc (ycoeff, gsgeti (sy, GSNCOEFF), TY_REAL)
+
+ # Get coefficients and numbers of coefficients.
+ call gscoeff (sx, Memr[xcoeff], nxxcoeff)
+ call gscoeff (sy, Memr[ycoeff], nyycoeff)
+ nxxcoeff = gsgeti (sx, GSNXCOEFF)
+ nxycoeff = gsgeti (sx, GSNYCOEFF)
+ nyxcoeff = gsgeti (sy, GSNXCOEFF)
+ nyycoeff = gsgeti (sy, GSNYCOEFF)
+
+ # Get the data range.
+ if (gsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (gsgetr (sx, GSXMAX) - gsgetr (sx, GSXMIN)) / 2.0
+ xxmaxmin = - (gsgetr (sx, GSXMAX) + gsgetr (sx, GSXMIN)) / 2.0
+ xyrange = (gsgetr (sx, GSYMAX) - gsgetr (sx, GSYMIN)) / 2.0
+ xymaxmin = - (gsgetr (sx, GSYMAX) + gsgetr (sx, GSYMIN)) / 2.0
+ } else {
+ xxrange = real(1.0)
+ xxmaxmin = real(0.0)
+ xyrange = real(1.0)
+ xymaxmin = real(0.0)
+ }
+
+ if (gsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (gsgetr (sy, GSXMAX) - gsgetr (sy, GSXMIN)) / 2.0
+ yxmaxmin = - (gsgetr (sy, GSXMAX) + gsgetr (sy, GSXMIN)) / 2.0
+ yyrange = (gsgetr (sy, GSYMAX) - gsgetr (sy, GSYMIN)) / 2.0
+ yymaxmin = - (gsgetr (sy, GSYMAX) + gsgetr (sy, GSYMIN)) / 2.0
+ } else {
+ yxrange = real(1.0)
+ yxmaxmin = real(0.0)
+ yyrange = real(1.0)
+ yymaxmin = real(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Memr[xcoeff] + Memr[xcoeff+1] * xxmaxmin / xxrange +
+ Memr[xcoeff+2] * xymaxmin / xyrange
+ yshift = Memr[ycoeff] + Memr[ycoeff+1] * yxmaxmin / yxrange +
+ Memr[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Memr[xcoeff+1] / xxrange
+ else
+ a = real(0.0)
+ if (nxycoeff > 1)
+ b = Memr[xcoeff+nxxcoeff] / xyrange
+ else
+ b = real(0.0)
+ if (nyxcoeff > 1)
+ c = Memr[ycoeff+1] / yxrange
+ else
+ c = real(0.0)
+ if (nyycoeff > 1)
+ d = Memr[ycoeff+nyxcoeff] / yyrange
+ else
+ d = real(0.0)
+
+ # Get the magnification factors.
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+
+ # Get the x and y axes rotation factors.
+ if (fp_equalr (a, real(0.0)) && fp_equalr (c, real(0.0)))
+ xrot = real(0.0)
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < real(0.0))
+ xrot = xrot + real(360.0)
+
+ if (fp_equalr (b, real(0.0)) && fp_equalr (d, real(0.0)))
+ yrot = real(0.0)
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < real(0.0))
+ yrot = yrot + real(360.0)
+
+ call sfree (sp)
+end
+
+
+
+# GEO_MGFIT -- Fit the surface using interactive graphics.
+
+procedure geo_mgfitd (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, npts, xerrmsg, yerrmsg, maxch)
+
+pointer gd #I graphics file descriptor
+pointer fit #I pointer to the fit structure
+pointer sx1 #I pointer to the linear x surface fit
+pointer sy1 #I pointer to the linear y surface fit
+pointer sx2 #I pointer to higher order x surface fit
+pointer sy2 #I pointer to higher order y surface fit
+double xref[npts] #I the x reference coordinates
+double yref[npts] #I the y reference coordinates
+double xin[npts] #I input x coordinates
+double yin[npts] #I input y coordinates
+double wts[npts] #I array of weights
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x fit error message
+char yerrmsg[ARB] #O the output x fit error message
+int maxch #I the size of the error messages
+
+char errstr[SZ_LINE]
+int newgraph, delete, wcs, key, errcode
+pointer sp, w, gfit, xresid, yresid, cmd
+pointer gt1, gt2, gt3, gt4, gt5
+real wx, wy
+double xshift, yshift, xscale, yscale, thetax, thetay
+
+int clgcur(), errget()
+pointer gt_init()
+
+errchk geo_fxyd(), geo_mrejectd(), geo_fthetad()
+errchk geo_fmagnifyd(), geo_flineard()
+
+begin
+ # Initialize gfit structure and working space.
+ call smark (sp)
+ call salloc (gfit, LEN_GEOGRAPH, TY_STRUCT)
+ call salloc (xresid, npts, TY_DOUBLE)
+ call salloc (yresid, npts, TY_DOUBLE)
+ call salloc (w, npts, TY_DOUBLE)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Do initial fit.
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresid], Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresid], Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresid], Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin, wts,
+ Memd[xresid], npts, YES, xerrmsg, maxch)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin, wts,
+ Memd[yresid], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, Memd[xresid], Memd[yresid], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+ } then {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call error (2, "Too few points for X and Y fits.")
+ else
+ call error (2, "Too few points for XI and ETA fits.")
+ }
+
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+
+ # Set up plotting defaults.
+ GG_PLOTTYPE(gfit) = FIT
+ GG_OVERPLOT(gfit) = NO
+ GG_CONSTXY(gfit) = YES
+ newgraph = NO
+
+ # Allocate graphics tools.
+ gt1 = gt_init ()
+ gt2 = gt_init ()
+ gt3 = gt_init ()
+ gt4 = gt_init ()
+ gt5 = gt_init ()
+
+ # Set the plot title and x and y axis labels.
+ call geo_gtset (FIT, gt1, fit)
+ call geo_gtset (XXRESID, gt2, fit)
+ call geo_gtset (XYRESID, gt3, fit)
+ call geo_gtset (YXRESID, gt4, fit)
+ call geo_gtset (YYRESID, gt5, fit)
+
+ # Make the first plot.
+ call gclear (gd)
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphd (gd, gt1, fit, gfit, xref, yref, xin, yin, wts,
+ npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyd (gd, fit, sx1, sy1, sx2, sy2)
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+
+ # Read the cursor commands.
+ call amovd (wts, Memd[w], npts)
+ while (clgcur ("cursor", wx, wy, wcs, key, Memc[cmd], SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ call amovd (Memd[w], wts, npts)
+ break
+
+ case '?':
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call gpagefile (gd, GHELPFILE, "")
+ else
+ call gpagefile (gd, CHELPFILE, "")
+
+ case ':':
+ call geo_colon (gd, fit, gfit, Memc[cmd], newgraph)
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call gt_colon (Memc[cmd], gd, gt1, newgraph)
+ case XXRESID:
+ call gt_colon (Memc[cmd], gd, gt2, newgraph)
+ case XYRESID:
+ call gt_colon (Memc[cmd], gd, gt3, newgraph)
+ case YXRESID:
+ call gt_colon (Memc[cmd], gd, gt4, newgraph)
+ case YYRESID:
+ call gt_colon (Memc[cmd], gd, gt5, newgraph)
+ }
+
+ case 'l':
+ if (GG_FITERROR(gfit) == NO) {
+ call geo_lcoeffd (sx1, sy1, xshift, yshift, xscale, yscale,
+ thetax, thetay)
+ call printf ("xshift: %.2f yshift: %.2f ")
+ call pargd (xshift)
+ call pargd (yshift)
+ call printf ("xmag: %0.3g ymag: %0.3g ")
+ call pargd (xscale)
+ call pargd (yscale)
+ call printf ("xrot: %.2f yrot: %.2f\n")
+ call pargd (thetax)
+ call pargd (thetay)
+ }
+
+ case 't':
+ if (GG_FITERROR(gfit) == NO && GG_PLOTTYPE(gfit) == FIT)
+ call geo_lxyd (gd, fit, sx1, sy1, sx2, sy2, xref, yref,
+ xin, yin, npts, wx, wy)
+
+ case 'c':
+ if (GG_CONSTXY(gfit) == YES)
+ GG_CONSTXY(gfit) = NO
+ else if (GG_CONSTXY(gfit) == NO)
+ GG_CONSTXY(gfit) = YES
+
+ case 'd', 'u':
+ if (key == 'd')
+ delete = YES
+ else
+ delete = NO
+
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_1deleted (gd, xin, yin, Memd[w], wts, npts, wx,
+ wy, delete)
+ case XXRESID:
+ call geo_2deleted (gd, xref, Memd[xresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ case XYRESID:
+ call geo_2deleted (gd, yref, Memd[xresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ case YXRESID:
+ call geo_2deleted (gd, xref, Memd[yresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ case YYRESID:
+ call geo_2deleted (gd, yref, Memd[yresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ }
+
+ GG_NEWFUNCTION(gfit) = YES
+
+ case 'g':
+ if (GG_PLOTTYPE(gfit) != FIT)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = FIT
+
+ case 'x':
+ if (GG_PLOTTYPE(gfit) != XXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XXRESID
+
+ case 'r':
+ if (GG_PLOTTYPE(gfit) != XYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XYRESID
+
+ case 'y':
+ if (GG_PLOTTYPE(gfit) != YXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YXRESID
+
+ case 's':
+ if (GG_PLOTTYPE(gfit) != YYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YYRESID
+
+ case 'f':
+ # do fit
+ if (GG_NEWFUNCTION(gfit) == YES) {
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin,
+ yin, Memd[w], Memd[xresid], Memd[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin,
+ yin, Memd[w], Memd[xresid], Memd[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin,
+ yin, Memd[w], Memd[xresid], Memd[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin,
+ Memd[w], Memd[xresid], npts, YES,
+ xerrmsg, maxch)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin,
+ Memd[w], Memd[yresid], npts, NO,
+ yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref,
+ yref, xin, yin, Memd[w], Memd[xresid],
+ Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+ } then {
+ errcode = errget (errstr, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (errstr)
+ GG_FITERROR(gfit) = YES
+ }
+ }
+
+ # plot new graph
+ if (GG_FITERROR(gfit) == YES)
+ newgraph = NO
+ else
+ newgraph = YES
+
+ case 'o':
+ GG_OVERPLOT(gfit) = YES
+
+ default:
+ call printf ("\07")
+
+ }
+
+ if (newgraph == YES) {
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphd (gd, gt1, fit, gfit, xref, yref, xin, yin,
+ Memd[w], npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyd (gd, fit, sx1, sy1, sx2, sy2)
+ case XXRESID:
+ call geo_label (XXRESID, gt2, fit)
+ call geo_2graphd (gd, gt2, fit, gfit, xref, Memd[xresid],
+ Memd[w], npts)
+ case XYRESID:
+ call geo_label (XYRESID, gt3, fit)
+ call geo_2graphd (gd, gt3, fit, gfit, yref, Memd[xresid],
+ Memd[w], npts)
+ case YXRESID:
+ call geo_label (YXRESID, gt4, fit)
+ call geo_2graphd (gd, gt4, fit, gfit, xref, Memd[yresid],
+ Memd[w], npts)
+ case YYRESID:
+ call geo_label (YYRESID, gt5, fit)
+ call geo_2graphd (gd, gt5, fit, gfit, yref, Memd[yresid],
+ Memd[w], npts)
+ }
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+ newgraph = NO
+ }
+ }
+
+ # Free space.
+ call gt_free (gt1)
+ call gt_free (gt2)
+ call gt_free (gt3)
+ call gt_free (gt4)
+ call gt_free (gt5)
+ call sfree (sp)
+
+ # Call an error if appropriate.
+ if (errcode > 0)
+ call error (2, errstr)
+end
+
+# GEO_LCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift, xexpansion, yexpansion, x and y rotations.
+
+procedure geo_lcoeffd (sx, sy, xshift, yshift, xscale, yscale, xrot, yrot)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+double xshift #O output x shift
+double yshift #O output y shift
+double xscale #O output x scale
+double yscale #O output y scale
+double xrot #O rotation of point on x axis
+double yrot #O rotation of point on y axis
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+double xxrange, xyrange, xxmaxmin, xymaxmin
+double yxrange, yyrange, yxmaxmin, yymaxmin
+double a, b, c, d
+
+bool fp_equald()
+int dgsgeti()
+double dgsgetd()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xcoeff, dgsgeti (sx, GSNCOEFF), TY_DOUBLE)
+ call salloc (ycoeff, dgsgeti (sy, GSNCOEFF), TY_DOUBLE)
+
+ # Get coefficients and numbers of coefficients.
+ call dgscoeff (sx, Memd[xcoeff], nxxcoeff)
+ call dgscoeff (sy, Memd[ycoeff], nyycoeff)
+ nxxcoeff = dgsgeti (sx, GSNXCOEFF)
+ nxycoeff = dgsgeti (sx, GSNYCOEFF)
+ nyxcoeff = dgsgeti (sy, GSNXCOEFF)
+ nyycoeff = dgsgeti (sy, GSNYCOEFF)
+
+ # Get the data range.
+ if (dgsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (dgsgetd (sx, GSXMAX) - dgsgetd (sx, GSXMIN)) / 2.0d0
+ xxmaxmin = - (dgsgetd (sx, GSXMAX) + dgsgetd (sx, GSXMIN)) / 2.0d0
+ xyrange = (dgsgetd (sx, GSYMAX) - dgsgetd (sx, GSYMIN)) / 2.0d0
+ xymaxmin = - (dgsgetd (sx, GSYMAX) + dgsgetd (sx, GSYMIN)) / 2.0d0
+ } else {
+ xxrange = double(1.0)
+ xxmaxmin = double(0.0)
+ xyrange = double(1.0)
+ xymaxmin = double(0.0)
+ }
+
+ if (dgsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (dgsgetd (sy, GSXMAX) - dgsgetd (sy, GSXMIN)) / 2.0d0
+ yxmaxmin = - (dgsgetd (sy, GSXMAX) + dgsgetd (sy, GSXMIN)) / 2.0d0
+ yyrange = (dgsgetd (sy, GSYMAX) - dgsgetd (sy, GSYMIN)) / 2.0d0
+ yymaxmin = - (dgsgetd (sy, GSYMAX) + dgsgetd (sy, GSYMIN)) / 2.0d0
+ } else {
+ yxrange = double(1.0)
+ yxmaxmin = double(0.0)
+ yyrange = double(1.0)
+ yymaxmin = double(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Memd[xcoeff] + Memd[xcoeff+1] * xxmaxmin / xxrange +
+ Memd[xcoeff+2] * xymaxmin / xyrange
+ yshift = Memd[ycoeff] + Memd[ycoeff+1] * yxmaxmin / yxrange +
+ Memd[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Memd[xcoeff+1] / xxrange
+ else
+ a = double(0.0)
+ if (nxycoeff > 1)
+ b = Memd[xcoeff+nxxcoeff] / xyrange
+ else
+ b = double(0.0)
+ if (nyxcoeff > 1)
+ c = Memd[ycoeff+1] / yxrange
+ else
+ c = double(0.0)
+ if (nyycoeff > 1)
+ d = Memd[ycoeff+nyxcoeff] / yyrange
+ else
+ d = double(0.0)
+
+ # Get the magnification factors.
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+
+ # Get the x and y axes rotation factors.
+ if (fp_equald (a, double(0.0)) && fp_equald (c, double(0.0)))
+ xrot = double(0.0)
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < double(0.0))
+ xrot = xrot + double(360.0)
+
+ if (fp_equald (b, double(0.0)) && fp_equald (d, double(0.0)))
+ yrot = double(0.0)
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < double(0.0))
+ yrot = yrot + double(360.0)
+
+ call sfree (sp)
+end
+
+
diff --git a/pkg/images/lib/geogmapi.x b/pkg/images/lib/geogmapi.x
new file mode 100644
index 00000000..9dc63610
--- /dev/null
+++ b/pkg/images/lib/geogmapi.x
@@ -0,0 +1,905 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <math.h>
+include <math/gsurfit.h>
+include <gset.h>
+include "geomap.h"
+include "geogmap.h"
+
+define GHELPFILE "images$lib/geomap.key"
+define CHELPFILE "images$lib/coomap.key"
+
+
+
+# GEO_MGFIT -- Fit the surface using interactive graphics.
+
+procedure geo_mgfitr (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, npts, xerrmsg, yerrmsg, maxch)
+
+pointer gd #I graphics file descriptor
+pointer fit #I pointer to the fit structure
+pointer sx1 #I pointer to the linear x surface fit
+pointer sy1 #I pointer to the linear y surface fit
+pointer sx2 #I pointer to higher order x surface fit
+pointer sy2 #I pointer to higher order y surface fit
+real xref[npts] #I the x reference coordinates
+real yref[npts] #I the y reference coordinates
+real xin[npts] #I input x coordinates
+real yin[npts] #I input y coordinates
+real wts[npts] #I array of weights
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x fit error message
+char yerrmsg[ARB] #O the output x fit error message
+int maxch #I the size of the error messages
+
+char errstr[SZ_LINE]
+int newgraph, delete, wcs, key, errcode
+pointer sp, w, gfit, xresid, yresid, cmd
+pointer gt1, gt2, gt3, gt4, gt5
+real wx, wy
+real xshift, yshift, xscale, yscale, thetax, thetay
+
+int clgcur(), errget()
+pointer gt_init()
+
+errchk geo_fxyr(), geo_mrejectr(), geo_fthetar()
+errchk geo_fmagnifyr(), geo_flinearr()
+
+begin
+ # Initialize gfit structure and working space.
+ call smark (sp)
+ call salloc (gfit, LEN_GEOGRAPH, TY_STRUCT)
+ call salloc (xresid, npts, TY_REAL)
+ call salloc (yresid, npts, TY_REAL)
+ call salloc (w, npts, TY_REAL)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Do initial fit.
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresid], Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresid], Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memr[xresid], Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin, wts,
+ Memr[xresid], npts, YES, xerrmsg, maxch)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin, wts,
+ Memr[yresid], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, Memr[xresid], Memr[yresid], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+ } then {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call error (2, "Too few points for X and Y fits.")
+ else
+ call error (2, "Too few points for XI and ETA fits.")
+ }
+
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+
+ # Set up plotting defaults.
+ GG_PLOTTYPE(gfit) = FIT
+ GG_OVERPLOT(gfit) = NO
+ GG_CONSTXY(gfit) = YES
+ newgraph = NO
+
+ # Allocate graphics tools.
+ gt1 = gt_init ()
+ gt2 = gt_init ()
+ gt3 = gt_init ()
+ gt4 = gt_init ()
+ gt5 = gt_init ()
+
+ # Set the plot title and x and y axis labels.
+ call geo_gtset (FIT, gt1, fit)
+ call geo_gtset (XXRESID, gt2, fit)
+ call geo_gtset (XYRESID, gt3, fit)
+ call geo_gtset (YXRESID, gt4, fit)
+ call geo_gtset (YYRESID, gt5, fit)
+
+ # Make the first plot.
+ call gclear (gd)
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphr (gd, gt1, fit, gfit, xref, yref, xin, yin, wts,
+ npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyr (gd, fit, sx1, sy1, sx2, sy2)
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+
+ # Read the cursor commands.
+ call amovr (wts, Memr[w], npts)
+ while (clgcur ("cursor", wx, wy, wcs, key, Memc[cmd], SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ call amovr (Memr[w], wts, npts)
+ break
+
+ case '?':
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call gpagefile (gd, GHELPFILE, "")
+ else
+ call gpagefile (gd, CHELPFILE, "")
+
+ case ':':
+ call geo_colon (gd, fit, gfit, Memc[cmd], newgraph)
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call gt_colon (Memc[cmd], gd, gt1, newgraph)
+ case XXRESID:
+ call gt_colon (Memc[cmd], gd, gt2, newgraph)
+ case XYRESID:
+ call gt_colon (Memc[cmd], gd, gt3, newgraph)
+ case YXRESID:
+ call gt_colon (Memc[cmd], gd, gt4, newgraph)
+ case YYRESID:
+ call gt_colon (Memc[cmd], gd, gt5, newgraph)
+ }
+
+ case 'l':
+ if (GG_FITERROR(gfit) == NO) {
+ call geo_lcoeffr (sx1, sy1, xshift, yshift, xscale, yscale,
+ thetax, thetay)
+ call printf ("xshift: %.2f yshift: %.2f ")
+ call pargr (xshift)
+ call pargr (yshift)
+ call printf ("xmag: %0.3g ymag: %0.3g ")
+ call pargr (xscale)
+ call pargr (yscale)
+ call printf ("xrot: %.2f yrot: %.2f\n")
+ call pargr (thetax)
+ call pargr (thetay)
+ }
+
+ case 't':
+ if (GG_FITERROR(gfit) == NO && GG_PLOTTYPE(gfit) == FIT)
+ call geo_lxyr (gd, fit, sx1, sy1, sx2, sy2, xref, yref,
+ xin, yin, npts, wx, wy)
+
+ case 'c':
+ if (GG_CONSTXY(gfit) == YES)
+ GG_CONSTXY(gfit) = NO
+ else if (GG_CONSTXY(gfit) == NO)
+ GG_CONSTXY(gfit) = YES
+
+ case 'd', 'u':
+ if (key == 'd')
+ delete = YES
+ else
+ delete = NO
+
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_1deleter (gd, xin, yin, Memr[w], wts, npts, wx,
+ wy, delete)
+ case XXRESID:
+ call geo_2deleter (gd, xref, Memr[xresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ case XYRESID:
+ call geo_2deleter (gd, yref, Memr[xresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ case YXRESID:
+ call geo_2deleter (gd, xref, Memr[yresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ case YYRESID:
+ call geo_2deleter (gd, yref, Memr[yresid], Memr[w], wts,
+ npts, wx, wy, delete)
+ }
+
+ GG_NEWFUNCTION(gfit) = YES
+
+ case 'g':
+ if (GG_PLOTTYPE(gfit) != FIT)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = FIT
+
+ case 'x':
+ if (GG_PLOTTYPE(gfit) != XXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XXRESID
+
+ case 'r':
+ if (GG_PLOTTYPE(gfit) != XYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XYRESID
+
+ case 'y':
+ if (GG_PLOTTYPE(gfit) != YXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YXRESID
+
+ case 's':
+ if (GG_PLOTTYPE(gfit) != YYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YYRESID
+
+ case 'f':
+ # do fit
+ if (GG_NEWFUNCTION(gfit) == YES) {
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetar (fit, sx1, sy1, xref, yref, xin,
+ yin, Memr[w], Memr[xresid], Memr[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin,
+ yin, Memr[w], Memr[xresid], Memr[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flinearr (fit, sx1, sy1, xref, yref, xin,
+ yin, Memr[w], Memr[xresid], Memr[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyr (fit, sx1, sx2, xref, yref, xin,
+ Memr[w], Memr[xresid], npts, YES,
+ xerrmsg, maxch)
+ call geo_fxyr (fit, sy1, sy2, xref, yref, yin,
+ Memr[w], Memr[yresid], npts, NO,
+ yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref,
+ yref, xin, yin, Memr[w], Memr[xresid],
+ Memr[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+ } then {
+ errcode = errget (errstr, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (errstr)
+ GG_FITERROR(gfit) = YES
+ }
+ }
+
+ # plot new graph
+ if (GG_FITERROR(gfit) == YES)
+ newgraph = NO
+ else
+ newgraph = YES
+
+ case 'o':
+ GG_OVERPLOT(gfit) = YES
+
+ default:
+ call printf ("\07")
+
+ }
+
+ if (newgraph == YES) {
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphr (gd, gt1, fit, gfit, xref, yref, xin, yin,
+ Memr[w], npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyr (gd, fit, sx1, sy1, sx2, sy2)
+ case XXRESID:
+ call geo_label (XXRESID, gt2, fit)
+ call geo_2graphr (gd, gt2, fit, gfit, xref, Memr[xresid],
+ Memr[w], npts)
+ case XYRESID:
+ call geo_label (XYRESID, gt3, fit)
+ call geo_2graphr (gd, gt3, fit, gfit, yref, Memr[xresid],
+ Memr[w], npts)
+ case YXRESID:
+ call geo_label (YXRESID, gt4, fit)
+ call geo_2graphr (gd, gt4, fit, gfit, xref, Memr[yresid],
+ Memr[w], npts)
+ case YYRESID:
+ call geo_label (YYRESID, gt5, fit)
+ call geo_2graphr (gd, gt5, fit, gfit, yref, Memr[yresid],
+ Memr[w], npts)
+ }
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+ newgraph = NO
+ }
+ }
+
+ # Free space.
+ call gt_free (gt1)
+ call gt_free (gt2)
+ call gt_free (gt3)
+ call gt_free (gt4)
+ call gt_free (gt5)
+ call sfree (sp)
+
+ # Call an error if appropriate.
+ if (errcode > 0)
+ call error (2, errstr)
+end
+
+# GEO_LCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift, xexpansion, yexpansion, x and y rotations.
+
+procedure geo_lcoeffr (sx, sy, xshift, yshift, xscale, yscale, xrot, yrot)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+real xshift #O output x shift
+real yshift #O output y shift
+real xscale #O output x scale
+real yscale #O output y scale
+real xrot #O rotation of point on x axis
+real yrot #O rotation of point on y axis
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+real xxrange, xyrange, xxmaxmin, xymaxmin
+real yxrange, yyrange, yxmaxmin, yymaxmin
+real a, b, c, d
+
+bool fp_equalr()
+int gsgeti()
+real gsgetr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xcoeff, gsgeti (sx, GSNCOEFF), TY_REAL)
+ call salloc (ycoeff, gsgeti (sy, GSNCOEFF), TY_REAL)
+
+ # Get coefficients and numbers of coefficients.
+ call gscoeff (sx, Memr[xcoeff], nxxcoeff)
+ call gscoeff (sy, Memr[ycoeff], nyycoeff)
+ nxxcoeff = gsgeti (sx, GSNXCOEFF)
+ nxycoeff = gsgeti (sx, GSNYCOEFF)
+ nyxcoeff = gsgeti (sy, GSNXCOEFF)
+ nyycoeff = gsgeti (sy, GSNYCOEFF)
+
+ # Get the data range.
+ if (gsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (gsgetr (sx, GSXMAX) - gsgetr (sx, GSXMIN)) / 2.0
+ xxmaxmin = - (gsgetr (sx, GSXMAX) + gsgetr (sx, GSXMIN)) / 2.0
+ xyrange = (gsgetr (sx, GSYMAX) - gsgetr (sx, GSYMIN)) / 2.0
+ xymaxmin = - (gsgetr (sx, GSYMAX) + gsgetr (sx, GSYMIN)) / 2.0
+ } else {
+ xxrange = real(1.0)
+ xxmaxmin = real(0.0)
+ xyrange = real(1.0)
+ xymaxmin = real(0.0)
+ }
+
+ if (gsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (gsgetr (sy, GSXMAX) - gsgetr (sy, GSXMIN)) / 2.0
+ yxmaxmin = - (gsgetr (sy, GSXMAX) + gsgetr (sy, GSXMIN)) / 2.0
+ yyrange = (gsgetr (sy, GSYMAX) - gsgetr (sy, GSYMIN)) / 2.0
+ yymaxmin = - (gsgetr (sy, GSYMAX) + gsgetr (sy, GSYMIN)) / 2.0
+ } else {
+ yxrange = real(1.0)
+ yxmaxmin = real(0.0)
+ yyrange = real(1.0)
+ yymaxmin = real(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Memr[xcoeff] + Memr[xcoeff+1] * xxmaxmin / xxrange +
+ Memr[xcoeff+2] * xymaxmin / xyrange
+ yshift = Memr[ycoeff] + Memr[ycoeff+1] * yxmaxmin / yxrange +
+ Memr[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Memr[xcoeff+1] / xxrange
+ else
+ a = real(0.0)
+ if (nxycoeff > 1)
+ b = Memr[xcoeff+nxxcoeff] / xyrange
+ else
+ b = real(0.0)
+ if (nyxcoeff > 1)
+ c = Memr[ycoeff+1] / yxrange
+ else
+ c = real(0.0)
+ if (nyycoeff > 1)
+ d = Memr[ycoeff+nyxcoeff] / yyrange
+ else
+ d = real(0.0)
+
+ # Get the magnification factors.
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+
+ # Get the x and y axes rotation factors.
+ if (fp_equalr (a, real(0.0)) && fp_equalr (c, real(0.0)))
+ xrot = real(0.0)
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < real(0.0))
+ xrot = xrot + real(360.0)
+
+ if (fp_equalr (b, real(0.0)) && fp_equalr (d, real(0.0)))
+ yrot = real(0.0)
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < real(0.0))
+ yrot = yrot + real(360.0)
+
+ call sfree (sp)
+end
+
+
+
+# GEO_MGFIT -- Fit the surface using interactive graphics.
+
+procedure geo_mgfitd (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, npts, xerrmsg, yerrmsg, maxch)
+
+pointer gd #I graphics file descriptor
+pointer fit #I pointer to the fit structure
+pointer sx1 #I pointer to the linear x surface fit
+pointer sy1 #I pointer to the linear y surface fit
+pointer sx2 #I pointer to higher order x surface fit
+pointer sy2 #I pointer to higher order y surface fit
+double xref[npts] #I the x reference coordinates
+double yref[npts] #I the y reference coordinates
+double xin[npts] #I input x coordinates
+double yin[npts] #I input y coordinates
+double wts[npts] #I array of weights
+int npts #I number of data points
+char xerrmsg[ARB] #O the output x fit error message
+char yerrmsg[ARB] #O the output x fit error message
+int maxch #I the size of the error messages
+
+char errstr[SZ_LINE]
+int newgraph, delete, wcs, key, errcode
+pointer sp, w, gfit, xresid, yresid, cmd
+pointer gt1, gt2, gt3, gt4, gt5
+real wx, wy
+double xshift, yshift, xscale, yscale, thetax, thetay
+
+int clgcur(), errget()
+pointer gt_init()
+
+errchk geo_fxyd(), geo_mrejectd(), geo_fthetad()
+errchk geo_fmagnifyd(), geo_flineard()
+
+begin
+ # Initialize gfit structure and working space.
+ call smark (sp)
+ call salloc (gfit, LEN_GEOGRAPH, TY_STRUCT)
+ call salloc (xresid, npts, TY_DOUBLE)
+ call salloc (yresid, npts, TY_DOUBLE)
+ call salloc (w, npts, TY_DOUBLE)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ # Do initial fit.
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresid], Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresid], Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts,
+ Memd[xresid], Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin, wts,
+ Memd[xresid], npts, YES, xerrmsg, maxch)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin, wts,
+ Memd[yresid], npts, NO, yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin,
+ yin, wts, Memd[xresid], Memd[yresid], npts, xerrmsg,
+ maxch, yerrmsg, maxch)
+ } then {
+ call sfree (sp)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call error (2, "Too few points for X and Y fits.")
+ else
+ call error (2, "Too few points for XI and ETA fits.")
+ }
+
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+
+ # Set up plotting defaults.
+ GG_PLOTTYPE(gfit) = FIT
+ GG_OVERPLOT(gfit) = NO
+ GG_CONSTXY(gfit) = YES
+ newgraph = NO
+
+ # Allocate graphics tools.
+ gt1 = gt_init ()
+ gt2 = gt_init ()
+ gt3 = gt_init ()
+ gt4 = gt_init ()
+ gt5 = gt_init ()
+
+ # Set the plot title and x and y axis labels.
+ call geo_gtset (FIT, gt1, fit)
+ call geo_gtset (XXRESID, gt2, fit)
+ call geo_gtset (XYRESID, gt3, fit)
+ call geo_gtset (YXRESID, gt4, fit)
+ call geo_gtset (YYRESID, gt5, fit)
+
+ # Make the first plot.
+ call gclear (gd)
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphd (gd, gt1, fit, gfit, xref, yref, xin, yin, wts,
+ npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyd (gd, fit, sx1, sy1, sx2, sy2)
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+
+ # Read the cursor commands.
+ call amovd (wts, Memd[w], npts)
+ while (clgcur ("cursor", wx, wy, wcs, key, Memc[cmd], SZ_LINE) != EOF) {
+
+ switch (key) {
+
+ case 'q':
+ call amovd (Memd[w], wts, npts)
+ break
+
+ case '?':
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call gpagefile (gd, GHELPFILE, "")
+ else
+ call gpagefile (gd, CHELPFILE, "")
+
+ case ':':
+ call geo_colon (gd, fit, gfit, Memc[cmd], newgraph)
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call gt_colon (Memc[cmd], gd, gt1, newgraph)
+ case XXRESID:
+ call gt_colon (Memc[cmd], gd, gt2, newgraph)
+ case XYRESID:
+ call gt_colon (Memc[cmd], gd, gt3, newgraph)
+ case YXRESID:
+ call gt_colon (Memc[cmd], gd, gt4, newgraph)
+ case YYRESID:
+ call gt_colon (Memc[cmd], gd, gt5, newgraph)
+ }
+
+ case 'l':
+ if (GG_FITERROR(gfit) == NO) {
+ call geo_lcoeffd (sx1, sy1, xshift, yshift, xscale, yscale,
+ thetax, thetay)
+ call printf ("xshift: %.2f yshift: %.2f ")
+ call pargd (xshift)
+ call pargd (yshift)
+ call printf ("xmag: %0.3g ymag: %0.3g ")
+ call pargd (xscale)
+ call pargd (yscale)
+ call printf ("xrot: %.2f yrot: %.2f\n")
+ call pargd (thetax)
+ call pargd (thetay)
+ }
+
+ case 't':
+ if (GG_FITERROR(gfit) == NO && GG_PLOTTYPE(gfit) == FIT)
+ call geo_lxyd (gd, fit, sx1, sy1, sx2, sy2, xref, yref,
+ xin, yin, npts, wx, wy)
+
+ case 'c':
+ if (GG_CONSTXY(gfit) == YES)
+ GG_CONSTXY(gfit) = NO
+ else if (GG_CONSTXY(gfit) == NO)
+ GG_CONSTXY(gfit) = YES
+
+ case 'd', 'u':
+ if (key == 'd')
+ delete = YES
+ else
+ delete = NO
+
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_1deleted (gd, xin, yin, Memd[w], wts, npts, wx,
+ wy, delete)
+ case XXRESID:
+ call geo_2deleted (gd, xref, Memd[xresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ case XYRESID:
+ call geo_2deleted (gd, yref, Memd[xresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ case YXRESID:
+ call geo_2deleted (gd, xref, Memd[yresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ case YYRESID:
+ call geo_2deleted (gd, yref, Memd[yresid], Memd[w], wts,
+ npts, wx, wy, delete)
+ }
+
+ GG_NEWFUNCTION(gfit) = YES
+
+ case 'g':
+ if (GG_PLOTTYPE(gfit) != FIT)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = FIT
+
+ case 'x':
+ if (GG_PLOTTYPE(gfit) != XXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XXRESID
+
+ case 'r':
+ if (GG_PLOTTYPE(gfit) != XYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = XYRESID
+
+ case 'y':
+ if (GG_PLOTTYPE(gfit) != YXRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YXRESID
+
+ case 's':
+ if (GG_PLOTTYPE(gfit) != YYRESID)
+ newgraph = YES
+ GG_PLOTTYPE(gfit) = YYRESID
+
+ case 'f':
+ # do fit
+ if (GG_NEWFUNCTION(gfit) == YES) {
+ iferr {
+ switch (GM_FIT(fit)) {
+ case GM_ROTATE:
+ call geo_fthetad (fit, sx1, sy1, xref, yref, xin,
+ yin, Memd[w], Memd[xresid], Memd[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RSCALE:
+ call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin,
+ yin, Memd[w], Memd[xresid], Memd[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ case GM_RXYSCALE:
+ call geo_flineard (fit, sx1, sy1, xref, yref, xin,
+ yin, Memd[w], Memd[xresid], Memd[yresid],
+ npts, xerrmsg, maxch, yerrmsg, maxch)
+ sx2 = NULL
+ sy2 = NULL
+ default:
+ call geo_fxyd (fit, sx1, sx2, xref, yref, xin,
+ Memd[w], Memd[xresid], npts, YES,
+ xerrmsg, maxch)
+ call geo_fxyd (fit, sy1, sy2, xref, yref, yin,
+ Memd[w], Memd[yresid], npts, NO,
+ yerrmsg, maxch)
+ }
+ if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit)))
+ GM_NREJECT(fit) = 0
+ else
+ call geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref,
+ yref, xin, yin, Memd[w], Memd[xresid],
+ Memd[yresid], npts, xerrmsg, maxch,
+ yerrmsg, maxch)
+ GG_NEWFUNCTION(gfit) = NO
+ GG_FITERROR(gfit) = NO
+ errcode = OK
+ } then {
+ errcode = errget (errstr, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (errstr)
+ GG_FITERROR(gfit) = YES
+ }
+ }
+
+ # plot new graph
+ if (GG_FITERROR(gfit) == YES)
+ newgraph = NO
+ else
+ newgraph = YES
+
+ case 'o':
+ GG_OVERPLOT(gfit) = YES
+
+ default:
+ call printf ("\07")
+
+ }
+
+ if (newgraph == YES) {
+ switch (GG_PLOTTYPE(gfit)) {
+ case FIT:
+ call geo_label (FIT, gt1, fit)
+ call geo_1graphd (gd, gt1, fit, gfit, xref, yref, xin, yin,
+ Memd[w], npts)
+ if (GG_CONSTXY(gfit) == YES)
+ call geo_conxyd (gd, fit, sx1, sy1, sx2, sy2)
+ case XXRESID:
+ call geo_label (XXRESID, gt2, fit)
+ call geo_2graphd (gd, gt2, fit, gfit, xref, Memd[xresid],
+ Memd[w], npts)
+ case XYRESID:
+ call geo_label (XYRESID, gt3, fit)
+ call geo_2graphd (gd, gt3, fit, gfit, yref, Memd[xresid],
+ Memd[w], npts)
+ case YXRESID:
+ call geo_label (YXRESID, gt4, fit)
+ call geo_2graphd (gd, gt4, fit, gfit, xref, Memd[yresid],
+ Memd[w], npts)
+ case YYRESID:
+ call geo_label (YYRESID, gt5, fit)
+ call geo_2graphd (gd, gt5, fit, gfit, yref, Memd[yresid],
+ Memd[w], npts)
+ }
+ call printf ("%s %s\n")
+ call pargstr (xerrmsg)
+ call pargstr (yerrmsg)
+ newgraph = NO
+ }
+ }
+
+ # Free space.
+ call gt_free (gt1)
+ call gt_free (gt2)
+ call gt_free (gt3)
+ call gt_free (gt4)
+ call gt_free (gt5)
+ call sfree (sp)
+
+ # Call an error if appropriate.
+ if (errcode > 0)
+ call error (2, errstr)
+end
+
+# GEO_LCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift, xexpansion, yexpansion, x and y rotations.
+
+procedure geo_lcoeffd (sx, sy, xshift, yshift, xscale, yscale, xrot, yrot)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+double xshift #O output x shift
+double yshift #O output y shift
+double xscale #O output x scale
+double yscale #O output y scale
+double xrot #O rotation of point on x axis
+double yrot #O rotation of point on y axis
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+double xxrange, xyrange, xxmaxmin, xymaxmin
+double yxrange, yyrange, yxmaxmin, yymaxmin
+double a, b, c, d
+
+bool fp_equald()
+int dgsgeti()
+double dgsgetd()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xcoeff, dgsgeti (sx, GSNCOEFF), TY_DOUBLE)
+ call salloc (ycoeff, dgsgeti (sy, GSNCOEFF), TY_DOUBLE)
+
+ # Get coefficients and numbers of coefficients.
+ call dgscoeff (sx, Memd[xcoeff], nxxcoeff)
+ call dgscoeff (sy, Memd[ycoeff], nyycoeff)
+ nxxcoeff = dgsgeti (sx, GSNXCOEFF)
+ nxycoeff = dgsgeti (sx, GSNYCOEFF)
+ nyxcoeff = dgsgeti (sy, GSNXCOEFF)
+ nyycoeff = dgsgeti (sy, GSNYCOEFF)
+
+ # Get the data range.
+ if (dgsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (dgsgetd (sx, GSXMAX) - dgsgetd (sx, GSXMIN)) / 2.0d0
+ xxmaxmin = - (dgsgetd (sx, GSXMAX) + dgsgetd (sx, GSXMIN)) / 2.0d0
+ xyrange = (dgsgetd (sx, GSYMAX) - dgsgetd (sx, GSYMIN)) / 2.0d0
+ xymaxmin = - (dgsgetd (sx, GSYMAX) + dgsgetd (sx, GSYMIN)) / 2.0d0
+ } else {
+ xxrange = double(1.0)
+ xxmaxmin = double(0.0)
+ xyrange = double(1.0)
+ xymaxmin = double(0.0)
+ }
+
+ if (dgsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (dgsgetd (sy, GSXMAX) - dgsgetd (sy, GSXMIN)) / 2.0d0
+ yxmaxmin = - (dgsgetd (sy, GSXMAX) + dgsgetd (sy, GSXMIN)) / 2.0d0
+ yyrange = (dgsgetd (sy, GSYMAX) - dgsgetd (sy, GSYMIN)) / 2.0d0
+ yymaxmin = - (dgsgetd (sy, GSYMAX) + dgsgetd (sy, GSYMIN)) / 2.0d0
+ } else {
+ yxrange = double(1.0)
+ yxmaxmin = double(0.0)
+ yyrange = double(1.0)
+ yymaxmin = double(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Memd[xcoeff] + Memd[xcoeff+1] * xxmaxmin / xxrange +
+ Memd[xcoeff+2] * xymaxmin / xyrange
+ yshift = Memd[ycoeff] + Memd[ycoeff+1] * yxmaxmin / yxrange +
+ Memd[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Memd[xcoeff+1] / xxrange
+ else
+ a = double(0.0)
+ if (nxycoeff > 1)
+ b = Memd[xcoeff+nxxcoeff] / xyrange
+ else
+ b = double(0.0)
+ if (nyxcoeff > 1)
+ c = Memd[ycoeff+1] / yxrange
+ else
+ c = double(0.0)
+ if (nyycoeff > 1)
+ d = Memd[ycoeff+nyxcoeff] / yyrange
+ else
+ d = double(0.0)
+
+ # Get the magnification factors.
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+
+ # Get the x and y axes rotation factors.
+ if (fp_equald (a, double(0.0)) && fp_equald (c, double(0.0)))
+ xrot = double(0.0)
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < double(0.0))
+ xrot = xrot + double(360.0)
+
+ if (fp_equald (b, double(0.0)) && fp_equald (d, double(0.0)))
+ yrot = double(0.0)
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < double(0.0))
+ yrot = yrot + double(360.0)
+
+ call sfree (sp)
+end
+
+
diff --git a/pkg/images/lib/geograph.gx b/pkg/images/lib/geograph.gx
new file mode 100644
index 00000000..5c42de24
--- /dev/null
+++ b/pkg/images/lib/geograph.gx
@@ -0,0 +1,1379 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math/gsurfit.h>
+include <pkg/gtools.h>
+include <mach.h>
+include <math.h>
+include <gset.h>
+include "geomap.h"
+include "geogmap.h"
+
+define MAX_PARAMS (10 * SZ_LINE)
+define NINTERVALS 5
+define NGRAPH 100
+
+$for (r)
+
+# GEO_LABEL -- Annotate the plot.
+
+procedure geo_label (plot_type, gt, fit)
+
+int plot_type #I type of plot
+pointer gt #I gtools descriptor
+pointer fit #I geomap fit parameters
+
+int npts
+pointer sp, params, xtermlab, ytermlab
+real xrms, yrms, rej
+int strlen(), rg_wrdstr()
+
+begin
+ call smark (sp)
+ call salloc (params, MAX_PARAMS, TY_CHAR)
+ call salloc (xtermlab, SZ_FNAME, TY_CHAR)
+ call salloc (ytermlab, SZ_FNAME, TY_CHAR)
+
+ npts = max (0, GM_NPTS(fit) - GM_NWTS0(fit))
+ xrms = max (0.0d0, GM_XRMS(fit))
+ yrms = max (0.0d0, GM_YRMS(fit))
+ if (npts > 1) {
+ xrms = sqrt (xrms / (npts - 1))
+ yrms = sqrt (yrms / (npts - 1))
+ } else {
+ xrms = 0.0
+ yrms = 0.0
+ }
+ if (IS_INDEFD(GM_REJECT(fit)))
+ rej = INDEFR
+ else if (GM_REJECT(fit) > MAX_REAL)
+ rej = INDEFR
+ else
+ rej = GM_REJECT(fit)
+
+ # Print data parameters.
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params], MAX_PARAMS,
+ "GEOMAP: function = %s npts = %d reject = %g nrej = %d\n")
+ else
+ call sprintf (Memc[params], MAX_PARAMS,
+ "CCMAP: function = %s npts = %d reject = %g nrej = %d\n")
+
+ switch (GM_FUNCTION(fit)) {
+ case GS_LEGENDRE:
+ call pargstr ("legendre")
+ case GS_CHEBYSHEV:
+ call pargstr ("chebyshev")
+ case GS_POLYNOMIAL:
+ call pargstr ("polynomial")
+ }
+ call pargi (GM_NPTS(fit))
+ call pargr (rej)
+ call pargi (GM_NWTS0(fit))
+
+ # Print fit parameters.
+ switch (plot_type) {
+ case FIT:
+
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[xtermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[xtermlab], SZ_FNAME)
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[ytermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[ytermlab], SZ_FNAME)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "X fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "XI fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g arcsec\n")
+ call pargi (GM_XXORDER(fit))
+ call pargi (GM_XYORDER(fit))
+ call pargstr (Memc[xtermlab])
+ call pargr (xrms)
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "Y fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "ETA fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g arcsec\n")
+ call pargi (GM_YXORDER(fit))
+ call pargi (GM_YYORDER(fit))
+ call pargstr (Memc[ytermlab])
+ call pargr (yrms)
+
+ case XXRESID, XYRESID:
+
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[xtermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[xtermlab], SZ_FNAME)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "X fit: xorder = %d yorder = %d xterms = %s rms = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "XI fit: xorder = %d yorder = %d xterms = %s rms = %8.3g arcsec\n")
+ call pargi (GM_XXORDER(fit))
+ call pargi (GM_XYORDER(fit))
+ call pargstr (Memc[xtermlab])
+ call pargr (xrms)
+
+ case YXRESID, YYRESID:
+
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[ytermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[ytermlab], SZ_FNAME)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "Y fit: xorder = %d yorder = %d xterms = %s rms = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "ETA fit: xorder = %d yorder = %d xterms = %s rms = %8.3g arcsec\n")
+ call pargi (GM_YXORDER(fit))
+ call pargi (GM_YYORDER(fit))
+ call pargstr (Memc[ytermlab])
+ call pargr (yrms)
+
+ default:
+
+ # do nothing gracefully
+ }
+
+ call gt_sets (gt, GTPARAMS, Memc[params])
+
+ call sfree (sp)
+end
+
+
+# GEO_GTSET -- Write title and labels.
+
+procedure geo_gtset (plot_type, gt, fit)
+
+int plot_type #I plot type
+pointer gt #I plot descriptor
+pointer fit #I fit descriptor
+
+char str[SZ_LINE]
+int nchars
+int gstrcpy()
+
+begin
+ nchars = gstrcpy (GM_RECORD(fit), str, SZ_LINE)
+
+ switch (plot_type) {
+ case FIT:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": Coordinate Transformation", str[nchars+1],
+ SZ_LINE)
+ else
+ call strcpy (": Celestial Coordinate Transformation",
+ str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "X (in units)")
+ call gt_sets (gt, GTYLABEL, "Y (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "XI (arcsec)")
+ call gt_sets (gt, GTYLABEL, "ETA (arcsec)")
+ }
+
+ case XXRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": X fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": XI fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "X (ref units)")
+ call gt_sets (gt, GTYLABEL, "X Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "X (pixels)")
+ call gt_sets (gt, GTYLABEL, "XI Residuals (arcsec)")
+ }
+
+ case XYRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": X fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": XI fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "Y (ref units)")
+ call gt_sets (gt, GTYLABEL, "X Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "Y (pixels)")
+ call gt_sets (gt, GTYLABEL, "XI Residuals (arcsec)")
+ }
+
+ case YXRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": Y fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": ETA fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "X (ref units)")
+ call gt_sets (gt, GTYLABEL, "Y (Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "X (pixels)")
+ call gt_sets (gt, GTYLABEL, "ETA Residuals (arcsec)")
+ }
+
+ case YYRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": Y fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": ETA fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "Y (ref units)")
+ call gt_sets (gt, GTYLABEL, "Y Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "Y (pixels)")
+ call gt_sets (gt, GTYLABEL, "ETA Residuals (arcsec)")
+ }
+
+ default:
+
+ # do nothing gracefully
+ }
+end
+
+
+# GEO_COLON -- Process the colon commands.
+
+procedure geo_colon (gd, fit, gfit, cmdstr, newgraph)
+
+pointer gd #I graphics stream
+pointer fit #I pointer to fit structure
+pointer gfit #I pointer to the gfit structure
+char cmdstr[ARB] #I command string
+int newgraph #I plot new graph
+
+int ncmd, ival
+pointer sp, str, cmd
+real rval
+int nscan(), strdic(), rg_wrdstr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan() == 0) {
+ call sfree (sp)
+ return
+ }
+
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_CMDS)
+ switch (ncmd) {
+ case GMCMD_SHOW:
+ call gdeactivate (gd, AW_CLEAR)
+ call printf ("Current Fitting Parameters\n\n")
+ if (GM_PROJECTION(fit) != GM_NONE) {
+ if (rg_wrdstr (GM_PROJECTION(fit), Memc[str], SZ_FNAME,
+ GM_PROJLIST) <= 0)
+ ;
+ call printf ("\tprojection = %s\n")
+ call pargstr (Memc[str])
+ call printf ("\tlngref = %h\n")
+ call pargd (GM_XREFPT(fit))
+ call printf ("\tlatref = %h\n")
+ call pargd (GM_YREFPT(fit))
+ }
+ if (rg_wrdstr (GM_FIT(fit), Memc[str], SZ_FNAME,
+ GM_GEOMETRIES) <= 0)
+ call strcpy ("general", Memc[str], SZ_FNAME)
+ call printf ("\tfitgeometry = %s\n")
+ call pargstr (Memc[str])
+ if (rg_wrdstr (GM_FUNCTION(fit), Memc[str], SZ_FNAME,
+ GM_FUNCS) <= 0)
+ call strcpy ("polynomial", Memc[str], SZ_FNAME)
+ call printf ("\tfunction = %s\n")
+ Call pargstr (Memc[str])
+ call printf ("\txxorder = %d\n")
+ call pargi (GM_XXORDER(fit))
+ call printf ("\txyorder = %d\n")
+ call pargi (GM_XYORDER(fit))
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("\txxterms = %s\n")
+ call pargstr (Memc[str])
+ call printf ("\tyxorder = %d\n")
+ call pargi (GM_YXORDER(fit))
+ call printf ("\tyyorder = %d\n")
+ call pargi (GM_YYORDER(fit))
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("\tyxterms = %s\n")
+ call pargstr (Memc[str])
+ if (IS_INDEFD(GM_REJECT(fit)))
+ rval = INDEFR
+ else if (GM_REJECT(fit) > MAX_REAL)
+ rval = INDEFR
+ else
+ rval = GM_REJECT(fit)
+ call printf ("\treject = %f\n")
+ call pargr (rval)
+ call greactivate (gd, AW_PAUSE)
+
+ case GMCMD_PROJECTION:
+ if (rg_wrdstr (GM_PROJECTION(fit), Memc[str], SZ_FNAME,
+ GM_PROJLIST) <= 0)
+ call strcpy ("INDEF", Memc[str], SZ_FNAME)
+ call printf ("projection = %s\n")
+ call pargstr (Memc[str])
+
+ case GMCMD_REFPOINT:
+ call printf ("lngref = %h latref = %h\n")
+ call pargd (GM_XREFPT(fit))
+ call pargd (GM_YREFPT(fit))
+
+ case GMCMD_GEOMETRY:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr (GM_FIT(fit), Memc[str], SZ_FNAME,
+ GM_GEOMETRIES) <= 0)
+ call strcpy ("general", Memc[str], SZ_FNAME)
+ call printf ("fitgeometry = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_GEOMETRIES)
+ if (ival > 0) {
+ GM_FIT(fit) = ival
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_FUNCTION:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr (GM_FUNCTION(fit), Memc[str], SZ_FNAME,
+ GM_FUNCS) <= 0)
+ call strcpy ("polynomial", Memc[str], SZ_FNAME)
+ call printf ("function = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_FUNCS)
+ if (ival > 0) {
+ GM_FUNCTION(fit) = ival
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_ORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf (
+ "xxorder = %d xyorder = %d yxorder = %d yyorder = %d\n")
+ call pargi (GM_XXORDER(fit))
+ call pargi (GM_XYORDER(fit))
+ call pargi (GM_YXORDER(fit))
+ call pargi (GM_YYORDER(fit))
+ } else {
+ GM_XXORDER(fit) = max (ival, 2)
+ GM_XYORDER(fit) = max (ival, 2)
+ GM_YXORDER(fit) = max (ival, 2)
+ GM_YYORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_XXORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("xxorder = %d\n")
+ call pargi (GM_XXORDER(fit))
+ } else {
+ GM_XXORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_XYORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("xyorder = %d\n")
+ call pargi (GM_XYORDER(fit))
+ } else {
+ GM_XYORDER(fit) = max (ival,2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_YXORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("yxorder = %d\n")
+ call pargi (GM_YXORDER(fit))
+ } else {
+ GM_YXORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_YYORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("yyorder = %d\n")
+ call pargi (GM_YYORDER(fit))
+ } else {
+ GM_YYORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_XXTERMS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("xxterms = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_XFUNCS)
+ if (ival > 0) {
+ GM_XXTERMS(fit) = ival - 1
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_YXTERMS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("yxterms = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_XFUNCS)
+ if (ival > 0) {
+ GM_YXTERMS(fit) = ival - 1
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_REJECT:
+ call gargr (rval)
+ if (nscan() == 1) {
+ if (IS_INDEFD(GM_REJECT(fit)))
+ rval = INDEFR
+ else if (GM_REJECT(fit) > MAX_REAL)
+ rval = INDEFR
+ else
+ rval = GM_REJECT(fit)
+ call printf ("reject = %f\n")
+ call pargr (rval)
+ } else {
+ GM_REJECT(fit) = rval
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_MAXITER:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("maxiter = %d\n")
+ call pargi (GM_MAXITER(fit))
+ } else {
+ GM_MAXITER(fit) = ival
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ }
+
+ call sfree (sp)
+end
+
+$endfor
+
+
+$for (rd)
+
+# GEO_1DELETE -- Delete a point from the fit.
+
+procedure geo_1delete$t (gd, xin, yin, wts, userwts, npts, wx, wy, delete)
+
+pointer gd #I pointer to graphics descriptor
+PIXEL xin[ARB] #I x array
+PIXEL yin[ARB] #I y array
+PIXEL wts[ARB] #I array of weights
+PIXEL userwts[ARB] #I array of user weights
+int npts #I number of points
+real wx, wy #I world coordinates
+int delete #I delete points ?
+
+int i, j, pmltype
+real r2min, r2, x0, y0
+int gstati()
+
+begin
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ if (delete == YES) {
+
+ # Search for nearest point that has not been deleted.
+ do i = 1, npts {
+ if (wts[i] <= PIXEL(0.0))
+ next
+$if (datatype == r)
+ call gctran (gd, xin[i], yin[i], x0, y0, 1, 0)
+$else
+ call gctran (gd, real (xin[i]), real (yin[i]), x0, y0, 1, 0)
+$endif
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Mark point and set weights to 0.
+ if (j != 0) {
+$if (datatype == r)
+ call gscur (gd, xin[j], yin[j])
+ call gmark (gd, xin[j], yin[j], GM_CROSS, 2., 2.)
+$else
+ call gscur (gd, real(xin[j]), real(yin[j]))
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_CROSS, 2., 2.)
+$endif
+ wts[j] = PIXEL(0.0)
+ }
+
+ } else {
+
+ # Search for the nearest deleted point.
+ do i = 1, npts {
+ if (wts[i] > PIXEL(0.0))
+ next
+$if (datatype == r)
+ call gctran (gd, xin[i], yin[i], x0, y0, 1, 0)
+$else
+ call gctran (gd, real(xin[i]), real(yin[i]), x0, y0, 1, 0)
+$endif
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Erase cross and remark with a plus.
+ if (j != 0) {
+$if (datatype == r)
+ call gscur (gd, xin[j], yin[j])
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, xin[j], yin[j], GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, xin[j], yin[j], GM_PLUS, 2., 2.)
+$else
+ call gscur (gd, real(xin[j]), real(yin[j]))
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_PLUS, 2., 2.)
+$endif
+ wts[j] = userwts[j]
+ }
+ }
+end
+
+
+# GEO_2DELETE -- Delete the residuals.
+
+procedure geo_2delete$t (gd, x, resid, wts, userwts, npts, wx, wy, delete)
+
+pointer gd #I pointer to graphics descriptor
+PIXEL x[ARB] #I reference x values
+PIXEL resid[ARB] #I residuals
+PIXEL wts[ARB] #I weight array
+PIXEL userwts[ARB] #I user weight array
+int npts #I number of points
+real wx #I world x coordinate
+real wy #I world y coordinate
+int delete #I delete point
+
+int i, j, pmltype
+real r2, r2min, x0, y0
+int gstati()
+
+begin
+ # Delete the point.
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ # Delete or add a point.
+ if (delete == YES) {
+
+ # Find the nearest undeleted point.
+ do i = 1, npts {
+ if (wts[i] <= PIXEL(0.0))
+ next
+$if (datatype == r)
+ call gctran (gd, x[i], resid[i], x0, y0, 1, 0)
+$else
+ call gctran (gd, real(x[i]), real(resid[i]), x0, y0, 1, 0)
+$endif
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Mark the point with a cross and set weight to zero.
+ if (j != 0) {
+$if (datatype == r)
+ call gscur (gd, x[j], resid[j])
+ call gmark (gd, x[j], resid[j], GM_CROSS, 2., 2.)
+$else
+ call gscur (gd, real(x[j]), real(resid[j]))
+ call gmark (gd, real(x[j]), real(resid[j]), GM_CROSS, 2., 2.)
+$endif
+ wts[j] = PIXEL(0.0)
+ }
+
+ } else {
+
+ # Find the nearest deleted point.
+ do i = 1, npts {
+ if (wts[i] > PIXEL(0.0))
+ next
+$if (datatype == r)
+ call gctran (gd, x[i], resid[i], x0, y0, 1, 0)
+$else
+ call gctran (gd, real(x[i]), real(resid[i]), x0, y0, 1, 0)
+$endif
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Erase the cross and remark with a plus.
+ if (j != 0) {
+$if (datatype == r)
+ call gscur (gd, x[j], resid[j])
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, x[j], resid[j], GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, x[j], resid[j], GM_PLUS, 2., 2.)
+$else
+ call gscur (gd, real(x[j]), real(resid[j]))
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, real(x[j]), real(resid[j]), GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, real(x[j]), real(resid[j]), GM_PLUS, 2., 2.)
+$endif
+ wts[j] = userwts[j]
+ }
+ }
+end
+
+
+# GEO_1GRAPH - Procedure to graph the distribution of the data in the x-y
+# plane. Rejected points are marked by a ' ' and deleted points are marked
+# by a ' '. The shift in position of the data points are indicated by
+# vectors. Sample fits of constant x and y are marked on the plots.
+
+procedure geo_1graph$t (gd, gt, fit, gfit, xref, yref, xin, yin, wts, npts)
+
+pointer gd #I pointer to the graphics device
+pointer gt #I pointer to the plot descriptor
+pointer fit #I pointer to the geofit structure
+pointer gfit #I pointer to the plot structure
+PIXEL xref[ARB] #I x reference values
+PIXEL yref[ARB] #I y reference values
+PIXEL xin[ARB] #I x values
+PIXEL yin[ARB] #I y values
+PIXEL wts[ARB] #I array of weights
+int npts #I number of points
+
+int i, j
+$if (datatype == d)
+pointer sp, rxin, ryin
+$endif
+
+begin
+ # If previous plot different type don't overplot.
+ if (GG_PLOTTYPE(gfit) != FIT)
+ GG_OVERPLOT(gfit) = NO
+
+ # If not overplottting start new plot.
+ if (GG_OVERPLOT(gfit) == NO) {
+
+ # Set scale and axes.
+ call gclear (gd)
+$if (datatype == r)
+ call gascale (gd, xin, npts, 1)
+ call gascale (gd, yin, npts, 2)
+$else
+ call smark (sp)
+ call salloc (rxin, npts, TY_REAL)
+ call salloc (ryin, npts, TY_REAL)
+ call achtdr (xin, Memr[rxin], npts)
+ call achtdr (yin, Memr[ryin], npts)
+ call gascale (gd, Memr[rxin], npts, 1)
+ call gascale (gd, Memr[ryin], npts, 2)
+ call sfree (sp)
+$endif
+ call gt_swind (gd, gt)
+ call gtlabax (gd, gt)
+
+ # Mark the data and deleted points.
+ do i = 1, npts {
+$if (datatype == r)
+ if (wts[i] == PIXEL(0.0))
+ call gmark (gd, xin[i], yin[i], GM_CROSS, 2., 2.)
+ else
+ call gmark (gd, xin[i], yin[i], GM_PLUS, 2., 2.)
+$else
+ if (wts[i] == PIXEL(0.0))
+ call gmark (gd, real(xin[i]), real(yin[i]), GM_CROSS,
+ 2., 2.)
+ else
+ call gmark (gd, real(xin[i]), real(yin[i]), GM_PLUS,
+ 2., 2.)
+$endif
+ }
+
+ call gflush (gd)
+ }
+
+ # Mark the rejected points.
+ do i = 1, GM_NREJECT(fit) {
+ j = Memi[GM_REJ(fit)+i-1]
+$if (datatype == r)
+ call gmark (gd, xin[j], yin[j], GM_CIRCLE, 2., 2.)
+$else
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_CIRCLE, 2., 2.)
+$endif
+ }
+
+ call gflush (gd)
+
+ # Reset the status flags
+ GG_OVERPLOT(gfit) = NO
+end
+
+
+# GEO_2GRAPH -- Graph the x and y fit residuals versus x or y .
+
+procedure geo_2graph$t (gd, gt, fit, gfit, x, resid, wts, npts)
+
+pointer gd #I pointer to the graphics device
+pointer gt #I pointer to the plot descriptor
+pointer fit #I pointer to geomap structure
+pointer gfit #I pointer to the plot structure
+PIXEL x[ARB] #I x reference values
+PIXEL resid[ARB] #I residual
+PIXEL wts[ARB] #I array of weights
+int npts #I number of points
+
+int i, j
+pointer sp, zero
+$if (datatype == d)
+pointer rxin, ryin
+$endif
+
+begin
+ # Allocate space.
+ call smark (sp)
+ call salloc (zero, npts, TY_REAL)
+ call amovkr (0.0, Memr[zero], npts)
+
+ # Calculate the residuals.
+ if (GG_PLOTTYPE(gfit) == FIT)
+ GG_OVERPLOT(gfit) = NO
+
+ if (GG_OVERPLOT(gfit) == NO) {
+
+ call gclear (gd)
+
+ # Set scale and axes.
+$if (datatype == r)
+ call gascale (gd, x, npts, 1)
+ call gascale (gd, resid, npts, 2)
+$else
+ call salloc (rxin, npts, TY_REAL)
+ call salloc (ryin, npts, TY_REAL)
+ call achtdr (x, Memr[rxin], npts)
+ call achtdr (resid, Memr[ryin], npts)
+ call gascale (gd, Memr[rxin], npts, 1)
+ call gascale (gd, Memr[ryin], npts, 2)
+$endif
+ call gt_swind (gd, gt)
+ call gtlabax (gd, gt)
+
+$if (datatype == r)
+ call gpline (gd, x, Memr[zero], npts)
+$else
+ call gpline (gd, Memr[rxin], Memr[zero], npts)
+$endif
+ }
+
+ # Graph residuals and mark deleted points.
+ if (GG_OVERPLOT(gfit) == NO || GG_NEWFUNCTION(gfit) == YES) {
+ do i = 1, npts {
+$if (datatype == r)
+ if (wts[i] == PIXEL(0.0))
+ call gmark (gd, x[i], resid[i], GM_CROSS, 2., 2.)
+ else
+ call gmark (gd, x[i], resid[i], GM_PLUS, 2., 2.)
+$else
+ if (wts[i] == PIXEL(0.0))
+ call gmark (gd, Memr[rxin+i-1], Memr[ryin+i-1],
+ GM_CROSS, 2., 2.)
+ else
+ call gmark (gd, Memr[rxin+i-1], Memr[ryin+i-1],
+ GM_PLUS, 2., 2.)
+$endif
+ }
+ }
+
+ # plot rejected points
+ if (GM_NREJECT(fit) > 0) {
+ do i = 1, GM_NREJECT(fit) {
+ j = Memi[GM_REJ(fit)+i-1]
+$if (datatype == r)
+ call gmark (gd, x[j], resid[j], GM_CIRCLE, 2., 2.)
+$else
+ call gmark (gd, Memr[rxin+j-1], Memr[ryin+j-1], GM_CIRCLE,
+ 2., 2.)
+$endif
+ }
+ }
+
+ # Reset the status flag.
+ GG_OVERPLOT(gfit) = NO
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# GEO_CONXY -- Plot a set of default lines of xref = const and yref = const.
+
+procedure geo_conxy$t (gd, fit, sx1, sy1, sx2, sy2)
+
+pointer gd #I graphics file descriptor
+pointer fit #I fit descriptor
+pointer sx1, sy1 #I pointer to the linear x and y surface fits
+pointer sx2, sy2 #I pointer to the linear x and y surface fits
+
+int i
+pointer sp, xtemp, ytemp, xfit1, yfit1, xfit2, yfit2
+$if (datatype == d)
+pointer xbuf, ybuf
+$endif
+PIXEL xint, yint, dx, dy
+
+begin
+ # allocate temporary space
+ call smark (sp)
+ call salloc (xtemp, NGRAPH, TY_PIXEL)
+ call salloc (ytemp, NGRAPH, TY_PIXEL)
+ call salloc (xfit1, NGRAPH, TY_PIXEL)
+ call salloc (yfit1, NGRAPH, TY_PIXEL)
+ call salloc (xfit2, NGRAPH, TY_PIXEL)
+ call salloc (yfit2, NGRAPH, TY_PIXEL)
+$if (datatype == d)
+ call salloc (xbuf, NGRAPH, TY_REAL)
+ call salloc (ybuf, NGRAPH, TY_REAL)
+$endif
+
+ # Calculate intervals in x and y.
+ dx = (GM_XMAX(fit) - GM_XMIN(fit)) / NINTERVALS
+ dy = (GM_YMAX(fit) - GM_YMIN(fit)) / (NGRAPH - 1)
+
+ # Set up an array of y values.
+ Mem$t[ytemp] = GM_YMIN(fit)
+ do i = 2, NGRAPH
+ Mem$t[ytemp+i-1] = Mem$t[ytemp+i-2] + dy
+
+ # Mark lines of constant x.
+ xint = GM_XMIN(fit)
+ for (i = 1; i <= NINTERVALS + 1; i = i + 1) {
+
+ # Set the x value.
+ call amovk$t (xint, Mem$t[xtemp], NGRAPH)
+
+ # X fit.
+$if (datatype == r)
+ call gsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$else
+ call dgsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$endif
+ if (sx2 != NULL) {
+$if (datatype == r)
+ call gsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$else
+ call dgsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[xfit1], Mem$t[xfit2], Mem$t[xfit1], NGRAPH)
+ }
+
+ # Y fit.
+$if (datatype == r)
+ call gsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$else
+ call dgsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$endif
+ if (sy2 != NULL) {
+$if (datatype == r)
+ call gsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$else
+ call dgsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[yfit1], Mem$t[yfit2], Mem$t[yfit1], NGRAPH)
+ }
+
+ # Plot line of constant x.
+$if (datatype == r)
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+$else
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+$endif
+
+ # Update the x value.
+ xint = xint + dx
+ }
+
+ call gflush (gd)
+
+ # Calculate x and y intervals.
+ dx = (GM_XMAX(fit) - GM_XMIN(fit)) / (NGRAPH - 1)
+ dy = (GM_YMAX(fit) - GM_YMIN(fit)) / NINTERVALS
+
+ # Set up array of x values.
+ Mem$t[xtemp] = GM_XMIN(fit)
+ do i = 2, NGRAPH
+ Mem$t[xtemp+i-1] = Mem$t[xtemp+i-2] + dx
+
+ # Mark lines of constant y.
+ yint = GM_YMIN(fit)
+ for (i = 1; i <= NINTERVALS + 1; i = i + 1) {
+
+ # set the y value
+ call amovk$t (yint, Mem$t[ytemp], NGRAPH)
+
+ # X fit.
+$if (datatype == r)
+ call gsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$else
+ call dgsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$endif
+ if (sx2 != NULL) {
+$if (datatype == r)
+ call gsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$else
+ call dgsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[xfit1], Mem$t[xfit2], Mem$t[xfit1], NGRAPH)
+ }
+
+
+ # Y fit.
+$if (datatype == r)
+ call gsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$else
+ call dgsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$endif
+ if (sy2 != NULL) {
+$if (datatype == r)
+ call gsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$else
+ call dgsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[yfit1], Mem$t[yfit2], Mem$t[yfit1], NGRAPH)
+ }
+
+ # Plot line of constant y.
+$if (datatype == r)
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+$else
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+$endif
+
+ # Update the y value.
+ yint = yint + dy
+ }
+
+ call gflush (gd)
+
+ call sfree (sp)
+end
+
+
+# GEO_LXY -- Draw a line of constant x-y.
+
+procedure geo_lxy$t (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, npts,
+ wx, wy)
+
+pointer gd #I pointer to graphics descriptor
+pointer fit #I pointer to the fit parameters
+pointer sx1 #I pointer to the linear x fit
+pointer sy1 #I pointer to the linear y fit
+pointer sx2 #I pointer to the higher order x fit
+pointer sy2 #I pointer to the higher order y fit
+PIXEL xref[ARB] #I x reference values
+PIXEL yref[ARB] #I y reference values
+PIXEL xin[ARB] #I x input values
+PIXEL yin[ARB] #I y input values
+int npts #I number of data points
+real wx, wy #I x and y world coordinates
+
+int i, j
+pointer sp, xtemp, ytemp, xfit1, yfit1, xfit2, yfit2
+$if (datatype == d)
+pointer xbuf, ybuf
+$endif
+real x0, y0, r2, r2min
+PIXEL delta, deltax, deltay
+$if (datatype == r)
+real gseval()
+$else
+double dgseval()
+$endif
+
+begin
+ # Transform world coordinates.
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ # Find the nearest data point.
+ do i = 1, npts {
+$if (datatype == r)
+ call gctran (gd, xin[i], yin[i], x0, y0, 1, 0)
+$else
+ call gctran (gd, real(xin[i]), real(yin[i]), x0, y0, 1, 0)
+$endif
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Fit the line
+ if (j != 0) {
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (xtemp, NGRAPH, TY_PIXEL)
+ call salloc (ytemp, NGRAPH, TY_PIXEL)
+ call salloc (xfit1, NGRAPH, TY_PIXEL)
+ call salloc (yfit1, NGRAPH, TY_PIXEL)
+ call salloc (xfit2, NGRAPH, TY_PIXEL)
+ call salloc (yfit2, NGRAPH, TY_PIXEL)
+$if (datatype == d)
+ call salloc (xbuf, NGRAPH, TY_REAL)
+ call salloc (ybuf, NGRAPH, TY_REAL)
+$endif
+
+ # Compute the deltas.
+$if (datatype == r)
+ deltax = xin[j] - gseval (sx1, xref[j], yref[j])
+ if (sx2 != NULL)
+ deltax = deltax - gseval (sx2, xref[j], yref[j])
+ deltay = yin[j] - gseval (sy1, xref[j], yref[j])
+ if (sy2 != NULL)
+ deltay = deltay - gseval (sy2, xref[j], yref[j])
+$else
+ deltax = xin[j] - dgseval (sx1, xref[j], yref[j])
+ if (sx2 != NULL)
+ deltax = deltax - dgseval (sx2, xref[j], yref[j])
+ deltay = yin[j] - dgseval (sy1, xref[j], yref[j])
+ if (sy2 != NULL)
+ deltay = deltay - dgseval (sy2, xref[j], yref[j])
+$endif
+
+ # Set up line of constant x.
+ call amovk$t (xref[j], Mem$t[xtemp], NGRAPH)
+ delta = (GM_YMAX(fit) - GM_YMIN(fit)) / (NGRAPH - 1)
+ Mem$t[ytemp] = GM_YMIN(fit)
+ do i = 2, NGRAPH
+ Mem$t[ytemp+i-1] = Mem$t[ytemp+i-2] + delta
+
+ # X solution.
+$if (datatype == r)
+ call gsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$else
+ call dgsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$endif
+ if (sx2 != NULL) {
+$if (datatype == r)
+ call gsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$else
+ call dgsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[xfit1], Mem$t[xfit2], Mem$t[xfit1], NGRAPH)
+ }
+ call aaddk$t (Mem$t[xfit1], deltax, Mem$t[xfit1], NGRAPH)
+
+ # Y solution.
+$if (datatype == r)
+ call gsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$else
+ call dgsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$endif
+ if (sy2 != NULL) {
+$if (datatype == r)
+ call gsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$else
+ call dgsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[yfit1], Mem$t[yfit2], Mem$t[yfit1], NGRAPH)
+ }
+ call aaddk$t (Mem$t[yfit1], deltay, Mem$t[yfit1], NGRAPH)
+
+ # Plot line of constant x.
+$if (datatype == r)
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+$else
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+$endif
+ call gflush (gd)
+
+ # Set up line of constant y.
+ call amovk$t (yref[j], Mem$t[ytemp], NGRAPH)
+ delta = (GM_XMAX(fit) - GM_XMIN(fit)) / (NGRAPH - 1)
+ Mem$t[xtemp] = GM_XMIN(fit)
+ do i = 2, NGRAPH
+ Mem$t[xtemp+i-1] = Mem$t[xtemp+i-2] + delta
+
+ # X fit.
+$if (datatype == r)
+ call gsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$else
+ call dgsvector (sx1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit1],
+ NGRAPH)
+$endif
+ if (sx2 != NULL) {
+$if (datatype == r)
+ call gsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$else
+ call dgsvector (sx2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[xfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[xfit1], Mem$t[xfit2], Mem$t[xfit1], NGRAPH)
+ }
+ call aaddk$t (Mem$t[xfit1], deltax, Mem$t[xfit1], NGRAPH)
+
+ # Y fit.
+$if (datatype == r)
+ call gsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$else
+ call dgsvector (sy1, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit1],
+ NGRAPH)
+$endif
+ if (sy2 != NULL) {
+$if (datatype == r)
+ call gsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$else
+ call dgsvector (sy2, Mem$t[xtemp], Mem$t[ytemp], Mem$t[yfit2],
+ NGRAPH)
+$endif
+ call aadd$t (Mem$t[yfit1], Mem$t[yfit2], Mem$t[yfit1], NGRAPH)
+ }
+ call aaddk$t (Mem$t[yfit1], deltay, Mem$t[yfit1], NGRAPH)
+
+ # Plot line of constant y.
+$if (datatype == r)
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+$else
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+$endif
+ call gflush (gd)
+
+ # Free space.
+ call sfree (sp)
+ }
+end
+
+
+# GEO_GCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift,
+
+procedure geo_gcoeff$t (sx, sy, xshift, yshift, a, b, c, d)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+PIXEL xshift #O output x shift
+PIXEL yshift #O output y shift
+PIXEL a #O output x coefficient of x fit
+PIXEL b #O output y coefficient of x fit
+PIXEL c #O output x coefficient of y fit
+PIXEL d #O output y coefficient of y fit
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+PIXEL xxrange, xyrange, xxmaxmin, xymaxmin
+PIXEL yxrange, yyrange, yxmaxmin, yymaxmin
+
+$if (datatype == r)
+int gsgeti()
+real gsgetr()
+$else
+int dgsgeti()
+double dgsgetd()
+$endif
+
+begin
+ # Allocate working space.
+ call smark (sp)
+$if (datatype == r)
+ call salloc (xcoeff, gsgeti (sx, GSNCOEFF), TY_PIXEL)
+ call salloc (ycoeff, gsgeti (sy, GSNCOEFF), TY_PIXEL)
+$else
+ call salloc (xcoeff, dgsgeti (sx, GSNCOEFF), TY_PIXEL)
+ call salloc (ycoeff, dgsgeti (sy, GSNCOEFF), TY_PIXEL)
+$endif
+
+ # Get coefficients and numbers of coefficients.
+$if (datatype == r)
+ call gscoeff (sx, Mem$t[xcoeff], nxxcoeff)
+ call gscoeff (sy, Mem$t[ycoeff], nyycoeff)
+ nxxcoeff = gsgeti (sx, GSNXCOEFF)
+ nxycoeff = gsgeti (sx, GSNYCOEFF)
+ nyxcoeff = gsgeti (sy, GSNXCOEFF)
+ nyycoeff = gsgeti (sy, GSNYCOEFF)
+$else
+ call dgscoeff (sx, Mem$t[xcoeff], nxxcoeff)
+ call dgscoeff (sy, Mem$t[ycoeff], nyycoeff)
+ nxxcoeff = dgsgeti (sx, GSNXCOEFF)
+ nxycoeff = dgsgeti (sx, GSNYCOEFF)
+ nyxcoeff = dgsgeti (sy, GSNXCOEFF)
+ nyycoeff = dgsgeti (sy, GSNYCOEFF)
+$endif
+
+ # Get the data range.
+$if (datatype == r)
+ if (gsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (gsgetr (sx, GSXMAX) - gsgetr (sx, GSXMIN)) / 2.0
+ xxmaxmin = - (gsgetr (sx, GSXMAX) + gsgetr (sx, GSXMIN)) / 2.0
+ xyrange = (gsgetr (sx, GSYMAX) - gsgetr (sx, GSYMIN)) / 2.0
+ xymaxmin = - (gsgetr (sx, GSYMAX) + gsgetr (sx, GSYMIN)) / 2.0
+$else
+ if (dgsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (dgsgetd (sx, GSXMAX) - dgsgetd (sx, GSXMIN)) / 2.0d0
+ xxmaxmin = - (dgsgetd (sx, GSXMAX) + dgsgetd (sx, GSXMIN)) / 2.0d0
+ xyrange = (dgsgetd (sx, GSYMAX) - dgsgetd (sx, GSYMIN)) / 2.0d0
+ xymaxmin = - (dgsgetd (sx, GSYMAX) + dgsgetd (sx, GSYMIN)) / 2.0d0
+$endif
+ } else {
+ xxrange = PIXEL(1.0)
+ xxmaxmin = PIXEL(0.0)
+ xyrange = PIXEL(1.0)
+ xymaxmin = PIXEL(0.0)
+ }
+
+$if (datatype == r)
+ if (gsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (gsgetr (sy, GSXMAX) - gsgetr (sy, GSXMIN)) / 2.0
+ yxmaxmin = - (gsgetr (sy, GSXMAX) + gsgetr (sy, GSXMIN)) / 2.0
+ yyrange = (gsgetr (sy, GSYMAX) - gsgetr (sy, GSYMIN)) / 2.0
+ yymaxmin = - (gsgetr (sy, GSYMAX) + gsgetr (sy, GSYMIN)) / 2.0
+$else
+ if (dgsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (dgsgetd (sy, GSXMAX) - dgsgetd (sy, GSXMIN)) / 2.0d0
+ yxmaxmin = - (dgsgetd (sy, GSXMAX) + dgsgetd (sy, GSXMIN)) / 2.0d0
+ yyrange = (dgsgetd (sy, GSYMAX) - dgsgetd (sy, GSYMIN)) / 2.0d0
+ yymaxmin = - (dgsgetd (sy, GSYMAX) + dgsgetd (sy, GSYMIN)) / 2.0d0
+$endif
+ } else {
+ yxrange = PIXEL(1.0)
+ yxmaxmin = PIXEL(0.0)
+ yyrange = PIXEL(1.0)
+ yymaxmin = PIXEL(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Mem$t[xcoeff] + Mem$t[xcoeff+1] * xxmaxmin / xxrange +
+ Mem$t[xcoeff+2] * xymaxmin / xyrange
+ yshift = Mem$t[ycoeff] + Mem$t[ycoeff+1] * yxmaxmin / yxrange +
+ Mem$t[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Mem$t[xcoeff+1] / xxrange
+ else
+ a = PIXEL(0.0)
+ if (nxycoeff > 1)
+ b = Mem$t[xcoeff+nxxcoeff] / xyrange
+ else
+ b = PIXEL(0.0)
+ if (nyxcoeff > 1)
+ c = Mem$t[ycoeff+1] / yxrange
+ else
+ c = PIXEL(0.0)
+ if (nyycoeff > 1)
+ d = Mem$t[ycoeff+nyxcoeff] / yyrange
+ else
+ d = PIXEL(0.0)
+
+ call sfree (sp)
+end
+
+$endfor
diff --git a/pkg/images/lib/geograph.x b/pkg/images/lib/geograph.x
new file mode 100644
index 00000000..6597311a
--- /dev/null
+++ b/pkg/images/lib/geograph.x
@@ -0,0 +1,1740 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math/gsurfit.h>
+include <pkg/gtools.h>
+include <mach.h>
+include <math.h>
+include <gset.h>
+include "geomap.h"
+include "geogmap.h"
+
+define MAX_PARAMS (10 * SZ_LINE)
+define NINTERVALS 5
+define NGRAPH 100
+
+
+
+# GEO_LABEL -- Annotate the plot.
+
+procedure geo_label (plot_type, gt, fit)
+
+int plot_type #I type of plot
+pointer gt #I gtools descriptor
+pointer fit #I geomap fit parameters
+
+int npts
+pointer sp, params, xtermlab, ytermlab
+real xrms, yrms, rej
+int strlen(), rg_wrdstr()
+
+begin
+ call smark (sp)
+ call salloc (params, MAX_PARAMS, TY_CHAR)
+ call salloc (xtermlab, SZ_FNAME, TY_CHAR)
+ call salloc (ytermlab, SZ_FNAME, TY_CHAR)
+
+ npts = max (0, GM_NPTS(fit) - GM_NWTS0(fit))
+ xrms = max (0.0d0, GM_XRMS(fit))
+ yrms = max (0.0d0, GM_YRMS(fit))
+ if (npts > 1) {
+ xrms = sqrt (xrms / (npts - 1))
+ yrms = sqrt (yrms / (npts - 1))
+ } else {
+ xrms = 0.0
+ yrms = 0.0
+ }
+ if (IS_INDEFD(GM_REJECT(fit)))
+ rej = INDEFR
+ else if (GM_REJECT(fit) > MAX_REAL)
+ rej = INDEFR
+ else
+ rej = GM_REJECT(fit)
+
+ # Print data parameters.
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params], MAX_PARAMS,
+ "GEOMAP: function = %s npts = %d reject = %g nrej = %d\n")
+ else
+ call sprintf (Memc[params], MAX_PARAMS,
+ "CCMAP: function = %s npts = %d reject = %g nrej = %d\n")
+
+ switch (GM_FUNCTION(fit)) {
+ case GS_LEGENDRE:
+ call pargstr ("legendre")
+ case GS_CHEBYSHEV:
+ call pargstr ("chebyshev")
+ case GS_POLYNOMIAL:
+ call pargstr ("polynomial")
+ }
+ call pargi (GM_NPTS(fit))
+ call pargr (rej)
+ call pargi (GM_NWTS0(fit))
+
+ # Print fit parameters.
+ switch (plot_type) {
+ case FIT:
+
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[xtermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[xtermlab], SZ_FNAME)
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[ytermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[ytermlab], SZ_FNAME)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "X fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "XI fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g arcsec\n")
+ call pargi (GM_XXORDER(fit))
+ call pargi (GM_XYORDER(fit))
+ call pargstr (Memc[xtermlab])
+ call pargr (xrms)
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "Y fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "ETA fit: xorder = %d yorder = %d xterms = %s stdev = %8.3g arcsec\n")
+ call pargi (GM_YXORDER(fit))
+ call pargi (GM_YYORDER(fit))
+ call pargstr (Memc[ytermlab])
+ call pargr (yrms)
+
+ case XXRESID, XYRESID:
+
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[xtermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[xtermlab], SZ_FNAME)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "X fit: xorder = %d yorder = %d xterms = %s rms = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "XI fit: xorder = %d yorder = %d xterms = %s rms = %8.3g arcsec\n")
+ call pargi (GM_XXORDER(fit))
+ call pargi (GM_XYORDER(fit))
+ call pargstr (Memc[xtermlab])
+ call pargr (xrms)
+
+ case YXRESID, YYRESID:
+
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[ytermlab], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[ytermlab], SZ_FNAME)
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "Y fit: xorder = %d yorder = %d xterms = %s rms = %8.3g\n")
+ else
+ call sprintf (Memc[params+strlen(Memc[params])], MAX_PARAMS,
+ "ETA fit: xorder = %d yorder = %d xterms = %s rms = %8.3g arcsec\n")
+ call pargi (GM_YXORDER(fit))
+ call pargi (GM_YYORDER(fit))
+ call pargstr (Memc[ytermlab])
+ call pargr (yrms)
+
+ default:
+
+ # do nothing gracefully
+ }
+
+ call gt_sets (gt, GTPARAMS, Memc[params])
+
+ call sfree (sp)
+end
+
+
+# GEO_GTSET -- Write title and labels.
+
+procedure geo_gtset (plot_type, gt, fit)
+
+int plot_type #I plot type
+pointer gt #I plot descriptor
+pointer fit #I fit descriptor
+
+char str[SZ_LINE]
+int nchars
+int gstrcpy()
+
+begin
+ nchars = gstrcpy (GM_RECORD(fit), str, SZ_LINE)
+
+ switch (plot_type) {
+ case FIT:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": Coordinate Transformation", str[nchars+1],
+ SZ_LINE)
+ else
+ call strcpy (": Celestial Coordinate Transformation",
+ str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "X (in units)")
+ call gt_sets (gt, GTYLABEL, "Y (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "XI (arcsec)")
+ call gt_sets (gt, GTYLABEL, "ETA (arcsec)")
+ }
+
+ case XXRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": X fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": XI fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "X (ref units)")
+ call gt_sets (gt, GTYLABEL, "X Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "X (pixels)")
+ call gt_sets (gt, GTYLABEL, "XI Residuals (arcsec)")
+ }
+
+ case XYRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": X fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": XI fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "Y (ref units)")
+ call gt_sets (gt, GTYLABEL, "X Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "Y (pixels)")
+ call gt_sets (gt, GTYLABEL, "XI Residuals (arcsec)")
+ }
+
+ case YXRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": Y fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": ETA fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "X (ref units)")
+ call gt_sets (gt, GTYLABEL, "Y (Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "X (pixels)")
+ call gt_sets (gt, GTYLABEL, "ETA Residuals (arcsec)")
+ }
+
+ case YYRESID:
+
+ if (GM_PROJECTION(fit) == GM_NONE)
+ call strcpy (": Y fit Residuals", str[nchars+1], SZ_LINE)
+ else
+ call strcpy (": ETA fit Residuals", str[nchars+1], SZ_LINE)
+ call gt_sets (gt, GTTITLE, str)
+ if (GM_PROJECTION(fit) == GM_NONE) {
+ call gt_sets (gt, GTXLABEL, "Y (ref units)")
+ call gt_sets (gt, GTYLABEL, "Y Residuals (in units)")
+ } else {
+ call gt_sets (gt, GTXLABEL, "Y (pixels)")
+ call gt_sets (gt, GTYLABEL, "ETA Residuals (arcsec)")
+ }
+
+ default:
+
+ # do nothing gracefully
+ }
+end
+
+
+# GEO_COLON -- Process the colon commands.
+
+procedure geo_colon (gd, fit, gfit, cmdstr, newgraph)
+
+pointer gd #I graphics stream
+pointer fit #I pointer to fit structure
+pointer gfit #I pointer to the gfit structure
+char cmdstr[ARB] #I command string
+int newgraph #I plot new graph
+
+int ncmd, ival
+pointer sp, str, cmd
+real rval
+int nscan(), strdic(), rg_wrdstr()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan() == 0) {
+ call sfree (sp)
+ return
+ }
+
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_CMDS)
+ switch (ncmd) {
+ case GMCMD_SHOW:
+ call gdeactivate (gd, AW_CLEAR)
+ call printf ("Current Fitting Parameters\n\n")
+ if (GM_PROJECTION(fit) != GM_NONE) {
+ if (rg_wrdstr (GM_PROJECTION(fit), Memc[str], SZ_FNAME,
+ GM_PROJLIST) <= 0)
+ ;
+ call printf ("\tprojection = %s\n")
+ call pargstr (Memc[str])
+ call printf ("\tlngref = %h\n")
+ call pargd (GM_XREFPT(fit))
+ call printf ("\tlatref = %h\n")
+ call pargd (GM_YREFPT(fit))
+ }
+ if (rg_wrdstr (GM_FIT(fit), Memc[str], SZ_FNAME,
+ GM_GEOMETRIES) <= 0)
+ call strcpy ("general", Memc[str], SZ_FNAME)
+ call printf ("\tfitgeometry = %s\n")
+ call pargstr (Memc[str])
+ if (rg_wrdstr (GM_FUNCTION(fit), Memc[str], SZ_FNAME,
+ GM_FUNCS) <= 0)
+ call strcpy ("polynomial", Memc[str], SZ_FNAME)
+ call printf ("\tfunction = %s\n")
+ Call pargstr (Memc[str])
+ call printf ("\txxorder = %d\n")
+ call pargi (GM_XXORDER(fit))
+ call printf ("\txyorder = %d\n")
+ call pargi (GM_XYORDER(fit))
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("\txxterms = %s\n")
+ call pargstr (Memc[str])
+ call printf ("\tyxorder = %d\n")
+ call pargi (GM_YXORDER(fit))
+ call printf ("\tyyorder = %d\n")
+ call pargi (GM_YYORDER(fit))
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("\tyxterms = %s\n")
+ call pargstr (Memc[str])
+ if (IS_INDEFD(GM_REJECT(fit)))
+ rval = INDEFR
+ else if (GM_REJECT(fit) > MAX_REAL)
+ rval = INDEFR
+ else
+ rval = GM_REJECT(fit)
+ call printf ("\treject = %f\n")
+ call pargr (rval)
+ call greactivate (gd, AW_PAUSE)
+
+ case GMCMD_PROJECTION:
+ if (rg_wrdstr (GM_PROJECTION(fit), Memc[str], SZ_FNAME,
+ GM_PROJLIST) <= 0)
+ call strcpy ("INDEF", Memc[str], SZ_FNAME)
+ call printf ("projection = %s\n")
+ call pargstr (Memc[str])
+
+ case GMCMD_REFPOINT:
+ call printf ("lngref = %h latref = %h\n")
+ call pargd (GM_XREFPT(fit))
+ call pargd (GM_YREFPT(fit))
+
+ case GMCMD_GEOMETRY:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr (GM_FIT(fit), Memc[str], SZ_FNAME,
+ GM_GEOMETRIES) <= 0)
+ call strcpy ("general", Memc[str], SZ_FNAME)
+ call printf ("fitgeometry = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_GEOMETRIES)
+ if (ival > 0) {
+ GM_FIT(fit) = ival
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_FUNCTION:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr (GM_FUNCTION(fit), Memc[str], SZ_FNAME,
+ GM_FUNCS) <= 0)
+ call strcpy ("polynomial", Memc[str], SZ_FNAME)
+ call printf ("function = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_FUNCS)
+ if (ival > 0) {
+ GM_FUNCTION(fit) = ival
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_ORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf (
+ "xxorder = %d xyorder = %d yxorder = %d yyorder = %d\n")
+ call pargi (GM_XXORDER(fit))
+ call pargi (GM_XYORDER(fit))
+ call pargi (GM_YXORDER(fit))
+ call pargi (GM_YYORDER(fit))
+ } else {
+ GM_XXORDER(fit) = max (ival, 2)
+ GM_XYORDER(fit) = max (ival, 2)
+ GM_YXORDER(fit) = max (ival, 2)
+ GM_YYORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_XXORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("xxorder = %d\n")
+ call pargi (GM_XXORDER(fit))
+ } else {
+ GM_XXORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_XYORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("xyorder = %d\n")
+ call pargi (GM_XYORDER(fit))
+ } else {
+ GM_XYORDER(fit) = max (ival,2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_YXORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("yxorder = %d\n")
+ call pargi (GM_YXORDER(fit))
+ } else {
+ GM_YXORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_YYORDER:
+ call gargi (ival)
+ if (nscan () == 1) {
+ call printf ("yyorder = %d\n")
+ call pargi (GM_YYORDER(fit))
+ } else {
+ GM_YYORDER(fit) = max (ival, 2)
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_XXTERMS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr ((GM_XXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("xxterms = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_XFUNCS)
+ if (ival > 0) {
+ GM_XXTERMS(fit) = ival - 1
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_YXTERMS:
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (nscan () == 1) {
+ if (rg_wrdstr ((GM_YXTERMS(fit) + 1), Memc[str], SZ_FNAME,
+ GM_XFUNCS) <= 0)
+ call strcpy ("none", Memc[str], SZ_FNAME)
+ call printf ("yxterms = %s\n")
+ call pargstr (Memc[str])
+ } else {
+ ival = strdic (Memc[cmd], Memc[cmd], SZ_LINE, GM_XFUNCS)
+ if (ival > 0) {
+ GM_YXTERMS(fit) = ival - 1
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+ }
+
+ case GMCMD_REJECT:
+ call gargr (rval)
+ if (nscan() == 1) {
+ if (IS_INDEFD(GM_REJECT(fit)))
+ rval = INDEFR
+ else if (GM_REJECT(fit) > MAX_REAL)
+ rval = INDEFR
+ else
+ rval = GM_REJECT(fit)
+ call printf ("reject = %f\n")
+ call pargr (rval)
+ } else {
+ GM_REJECT(fit) = rval
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ case GMCMD_MAXITER:
+ call gargi (ival)
+ if (nscan() == 1) {
+ call printf ("maxiter = %d\n")
+ call pargi (GM_MAXITER(fit))
+ } else {
+ GM_MAXITER(fit) = ival
+ GG_NEWFUNCTION(gfit) = YES
+ GG_FITERROR(gfit) = NO
+ }
+
+ }
+
+ call sfree (sp)
+end
+
+
+
+
+
+
+# GEO_1DELETE -- Delete a point from the fit.
+
+procedure geo_1deleter (gd, xin, yin, wts, userwts, npts, wx, wy, delete)
+
+pointer gd #I pointer to graphics descriptor
+real xin[ARB] #I x array
+real yin[ARB] #I y array
+real wts[ARB] #I array of weights
+real userwts[ARB] #I array of user weights
+int npts #I number of points
+real wx, wy #I world coordinates
+int delete #I delete points ?
+
+int i, j, pmltype
+real r2min, r2, x0, y0
+int gstati()
+
+begin
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ if (delete == YES) {
+
+ # Search for nearest point that has not been deleted.
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ next
+ call gctran (gd, xin[i], yin[i], x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Mark point and set weights to 0.
+ if (j != 0) {
+ call gscur (gd, xin[j], yin[j])
+ call gmark (gd, xin[j], yin[j], GM_CROSS, 2., 2.)
+ wts[j] = real(0.0)
+ }
+
+ } else {
+
+ # Search for the nearest deleted point.
+ do i = 1, npts {
+ if (wts[i] > real(0.0))
+ next
+ call gctran (gd, xin[i], yin[i], x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Erase cross and remark with a plus.
+ if (j != 0) {
+ call gscur (gd, xin[j], yin[j])
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, xin[j], yin[j], GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, xin[j], yin[j], GM_PLUS, 2., 2.)
+ wts[j] = userwts[j]
+ }
+ }
+end
+
+
+# GEO_2DELETE -- Delete the residuals.
+
+procedure geo_2deleter (gd, x, resid, wts, userwts, npts, wx, wy, delete)
+
+pointer gd #I pointer to graphics descriptor
+real x[ARB] #I reference x values
+real resid[ARB] #I residuals
+real wts[ARB] #I weight array
+real userwts[ARB] #I user weight array
+int npts #I number of points
+real wx #I world x coordinate
+real wy #I world y coordinate
+int delete #I delete point
+
+int i, j, pmltype
+real r2, r2min, x0, y0
+int gstati()
+
+begin
+ # Delete the point.
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ # Delete or add a point.
+ if (delete == YES) {
+
+ # Find the nearest undeleted point.
+ do i = 1, npts {
+ if (wts[i] <= real(0.0))
+ next
+ call gctran (gd, x[i], resid[i], x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Mark the point with a cross and set weight to zero.
+ if (j != 0) {
+ call gscur (gd, x[j], resid[j])
+ call gmark (gd, x[j], resid[j], GM_CROSS, 2., 2.)
+ wts[j] = real(0.0)
+ }
+
+ } else {
+
+ # Find the nearest deleted point.
+ do i = 1, npts {
+ if (wts[i] > real(0.0))
+ next
+ call gctran (gd, x[i], resid[i], x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Erase the cross and remark with a plus.
+ if (j != 0) {
+ call gscur (gd, x[j], resid[j])
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, x[j], resid[j], GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, x[j], resid[j], GM_PLUS, 2., 2.)
+ wts[j] = userwts[j]
+ }
+ }
+end
+
+
+# GEO_1GRAPH - Procedure to graph the distribution of the data in the x-y
+# plane. Rejected points are marked by a ' ' and deleted points are marked
+# by a ' '. The shift in position of the data points are indicated by
+# vectors. Sample fits of constant x and y are marked on the plots.
+
+procedure geo_1graphr (gd, gt, fit, gfit, xref, yref, xin, yin, wts, npts)
+
+pointer gd #I pointer to the graphics device
+pointer gt #I pointer to the plot descriptor
+pointer fit #I pointer to the geofit structure
+pointer gfit #I pointer to the plot structure
+real xref[ARB] #I x reference values
+real yref[ARB] #I y reference values
+real xin[ARB] #I x values
+real yin[ARB] #I y values
+real wts[ARB] #I array of weights
+int npts #I number of points
+
+int i, j
+
+begin
+ # If previous plot different type don't overplot.
+ if (GG_PLOTTYPE(gfit) != FIT)
+ GG_OVERPLOT(gfit) = NO
+
+ # If not overplottting start new plot.
+ if (GG_OVERPLOT(gfit) == NO) {
+
+ # Set scale and axes.
+ call gclear (gd)
+ call gascale (gd, xin, npts, 1)
+ call gascale (gd, yin, npts, 2)
+ call gt_swind (gd, gt)
+ call gtlabax (gd, gt)
+
+ # Mark the data and deleted points.
+ do i = 1, npts {
+ if (wts[i] == real(0.0))
+ call gmark (gd, xin[i], yin[i], GM_CROSS, 2., 2.)
+ else
+ call gmark (gd, xin[i], yin[i], GM_PLUS, 2., 2.)
+ }
+
+ call gflush (gd)
+ }
+
+ # Mark the rejected points.
+ do i = 1, GM_NREJECT(fit) {
+ j = Memi[GM_REJ(fit)+i-1]
+ call gmark (gd, xin[j], yin[j], GM_CIRCLE, 2., 2.)
+ }
+
+ call gflush (gd)
+
+ # Reset the status flags
+ GG_OVERPLOT(gfit) = NO
+end
+
+
+# GEO_2GRAPH -- Graph the x and y fit residuals versus x or y .
+
+procedure geo_2graphr (gd, gt, fit, gfit, x, resid, wts, npts)
+
+pointer gd #I pointer to the graphics device
+pointer gt #I pointer to the plot descriptor
+pointer fit #I pointer to geomap structure
+pointer gfit #I pointer to the plot structure
+real x[ARB] #I x reference values
+real resid[ARB] #I residual
+real wts[ARB] #I array of weights
+int npts #I number of points
+
+int i, j
+pointer sp, zero
+
+begin
+ # Allocate space.
+ call smark (sp)
+ call salloc (zero, npts, TY_REAL)
+ call amovkr (0.0, Memr[zero], npts)
+
+ # Calculate the residuals.
+ if (GG_PLOTTYPE(gfit) == FIT)
+ GG_OVERPLOT(gfit) = NO
+
+ if (GG_OVERPLOT(gfit) == NO) {
+
+ call gclear (gd)
+
+ # Set scale and axes.
+ call gascale (gd, x, npts, 1)
+ call gascale (gd, resid, npts, 2)
+ call gt_swind (gd, gt)
+ call gtlabax (gd, gt)
+
+ call gpline (gd, x, Memr[zero], npts)
+ }
+
+ # Graph residuals and mark deleted points.
+ if (GG_OVERPLOT(gfit) == NO || GG_NEWFUNCTION(gfit) == YES) {
+ do i = 1, npts {
+ if (wts[i] == real(0.0))
+ call gmark (gd, x[i], resid[i], GM_CROSS, 2., 2.)
+ else
+ call gmark (gd, x[i], resid[i], GM_PLUS, 2., 2.)
+ }
+ }
+
+ # plot rejected points
+ if (GM_NREJECT(fit) > 0) {
+ do i = 1, GM_NREJECT(fit) {
+ j = Memi[GM_REJ(fit)+i-1]
+ call gmark (gd, x[j], resid[j], GM_CIRCLE, 2., 2.)
+ }
+ }
+
+ # Reset the status flag.
+ GG_OVERPLOT(gfit) = NO
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# GEO_CONXY -- Plot a set of default lines of xref = const and yref = const.
+
+procedure geo_conxyr (gd, fit, sx1, sy1, sx2, sy2)
+
+pointer gd #I graphics file descriptor
+pointer fit #I fit descriptor
+pointer sx1, sy1 #I pointer to the linear x and y surface fits
+pointer sx2, sy2 #I pointer to the linear x and y surface fits
+
+int i
+pointer sp, xtemp, ytemp, xfit1, yfit1, xfit2, yfit2
+real xint, yint, dx, dy
+
+begin
+ # allocate temporary space
+ call smark (sp)
+ call salloc (xtemp, NGRAPH, TY_REAL)
+ call salloc (ytemp, NGRAPH, TY_REAL)
+ call salloc (xfit1, NGRAPH, TY_REAL)
+ call salloc (yfit1, NGRAPH, TY_REAL)
+ call salloc (xfit2, NGRAPH, TY_REAL)
+ call salloc (yfit2, NGRAPH, TY_REAL)
+
+ # Calculate intervals in x and y.
+ dx = (GM_XMAX(fit) - GM_XMIN(fit)) / NINTERVALS
+ dy = (GM_YMAX(fit) - GM_YMIN(fit)) / (NGRAPH - 1)
+
+ # Set up an array of y values.
+ Memr[ytemp] = GM_YMIN(fit)
+ do i = 2, NGRAPH
+ Memr[ytemp+i-1] = Memr[ytemp+i-2] + dy
+
+ # Mark lines of constant x.
+ xint = GM_XMIN(fit)
+ for (i = 1; i <= NINTERVALS + 1; i = i + 1) {
+
+ # Set the x value.
+ call amovkr (xint, Memr[xtemp], NGRAPH)
+
+ # X fit.
+ call gsvector (sx1, Memr[xtemp], Memr[ytemp], Memr[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call gsvector (sx2, Memr[xtemp], Memr[ytemp], Memr[xfit2],
+ NGRAPH)
+ call aaddr (Memr[xfit1], Memr[xfit2], Memr[xfit1], NGRAPH)
+ }
+
+ # Y fit.
+ call gsvector (sy1, Memr[xtemp], Memr[ytemp], Memr[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call gsvector (sy2, Memr[xtemp], Memr[ytemp], Memr[yfit2],
+ NGRAPH)
+ call aaddr (Memr[yfit1], Memr[yfit2], Memr[yfit1], NGRAPH)
+ }
+
+ # Plot line of constant x.
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+
+ # Update the x value.
+ xint = xint + dx
+ }
+
+ call gflush (gd)
+
+ # Calculate x and y intervals.
+ dx = (GM_XMAX(fit) - GM_XMIN(fit)) / (NGRAPH - 1)
+ dy = (GM_YMAX(fit) - GM_YMIN(fit)) / NINTERVALS
+
+ # Set up array of x values.
+ Memr[xtemp] = GM_XMIN(fit)
+ do i = 2, NGRAPH
+ Memr[xtemp+i-1] = Memr[xtemp+i-2] + dx
+
+ # Mark lines of constant y.
+ yint = GM_YMIN(fit)
+ for (i = 1; i <= NINTERVALS + 1; i = i + 1) {
+
+ # set the y value
+ call amovkr (yint, Memr[ytemp], NGRAPH)
+
+ # X fit.
+ call gsvector (sx1, Memr[xtemp], Memr[ytemp], Memr[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call gsvector (sx2, Memr[xtemp], Memr[ytemp], Memr[xfit2],
+ NGRAPH)
+ call aaddr (Memr[xfit1], Memr[xfit2], Memr[xfit1], NGRAPH)
+ }
+
+
+ # Y fit.
+ call gsvector (sy1, Memr[xtemp], Memr[ytemp], Memr[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call gsvector (sy2, Memr[xtemp], Memr[ytemp], Memr[yfit2],
+ NGRAPH)
+ call aaddr (Memr[yfit1], Memr[yfit2], Memr[yfit1], NGRAPH)
+ }
+
+ # Plot line of constant y.
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+
+ # Update the y value.
+ yint = yint + dy
+ }
+
+ call gflush (gd)
+
+ call sfree (sp)
+end
+
+
+# GEO_LXY -- Draw a line of constant x-y.
+
+procedure geo_lxyr (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, npts,
+ wx, wy)
+
+pointer gd #I pointer to graphics descriptor
+pointer fit #I pointer to the fit parameters
+pointer sx1 #I pointer to the linear x fit
+pointer sy1 #I pointer to the linear y fit
+pointer sx2 #I pointer to the higher order x fit
+pointer sy2 #I pointer to the higher order y fit
+real xref[ARB] #I x reference values
+real yref[ARB] #I y reference values
+real xin[ARB] #I x input values
+real yin[ARB] #I y input values
+int npts #I number of data points
+real wx, wy #I x and y world coordinates
+
+int i, j
+pointer sp, xtemp, ytemp, xfit1, yfit1, xfit2, yfit2
+real x0, y0, r2, r2min
+real delta, deltax, deltay
+real gseval()
+
+begin
+ # Transform world coordinates.
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ # Find the nearest data point.
+ do i = 1, npts {
+ call gctran (gd, xin[i], yin[i], x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Fit the line
+ if (j != 0) {
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (xtemp, NGRAPH, TY_REAL)
+ call salloc (ytemp, NGRAPH, TY_REAL)
+ call salloc (xfit1, NGRAPH, TY_REAL)
+ call salloc (yfit1, NGRAPH, TY_REAL)
+ call salloc (xfit2, NGRAPH, TY_REAL)
+ call salloc (yfit2, NGRAPH, TY_REAL)
+
+ # Compute the deltas.
+ deltax = xin[j] - gseval (sx1, xref[j], yref[j])
+ if (sx2 != NULL)
+ deltax = deltax - gseval (sx2, xref[j], yref[j])
+ deltay = yin[j] - gseval (sy1, xref[j], yref[j])
+ if (sy2 != NULL)
+ deltay = deltay - gseval (sy2, xref[j], yref[j])
+
+ # Set up line of constant x.
+ call amovkr (xref[j], Memr[xtemp], NGRAPH)
+ delta = (GM_YMAX(fit) - GM_YMIN(fit)) / (NGRAPH - 1)
+ Memr[ytemp] = GM_YMIN(fit)
+ do i = 2, NGRAPH
+ Memr[ytemp+i-1] = Memr[ytemp+i-2] + delta
+
+ # X solution.
+ call gsvector (sx1, Memr[xtemp], Memr[ytemp], Memr[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call gsvector (sx2, Memr[xtemp], Memr[ytemp], Memr[xfit2],
+ NGRAPH)
+ call aaddr (Memr[xfit1], Memr[xfit2], Memr[xfit1], NGRAPH)
+ }
+ call aaddkr (Memr[xfit1], deltax, Memr[xfit1], NGRAPH)
+
+ # Y solution.
+ call gsvector (sy1, Memr[xtemp], Memr[ytemp], Memr[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call gsvector (sy2, Memr[xtemp], Memr[ytemp], Memr[yfit2],
+ NGRAPH)
+ call aaddr (Memr[yfit1], Memr[yfit2], Memr[yfit1], NGRAPH)
+ }
+ call aaddkr (Memr[yfit1], deltay, Memr[yfit1], NGRAPH)
+
+ # Plot line of constant x.
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+ call gflush (gd)
+
+ # Set up line of constant y.
+ call amovkr (yref[j], Memr[ytemp], NGRAPH)
+ delta = (GM_XMAX(fit) - GM_XMIN(fit)) / (NGRAPH - 1)
+ Memr[xtemp] = GM_XMIN(fit)
+ do i = 2, NGRAPH
+ Memr[xtemp+i-1] = Memr[xtemp+i-2] + delta
+
+ # X fit.
+ call gsvector (sx1, Memr[xtemp], Memr[ytemp], Memr[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call gsvector (sx2, Memr[xtemp], Memr[ytemp], Memr[xfit2],
+ NGRAPH)
+ call aaddr (Memr[xfit1], Memr[xfit2], Memr[xfit1], NGRAPH)
+ }
+ call aaddkr (Memr[xfit1], deltax, Memr[xfit1], NGRAPH)
+
+ # Y fit.
+ call gsvector (sy1, Memr[xtemp], Memr[ytemp], Memr[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call gsvector (sy2, Memr[xtemp], Memr[ytemp], Memr[yfit2],
+ NGRAPH)
+ call aaddr (Memr[yfit1], Memr[yfit2], Memr[yfit1], NGRAPH)
+ }
+ call aaddkr (Memr[yfit1], deltay, Memr[yfit1], NGRAPH)
+
+ # Plot line of constant y.
+ call gpline (gd, Memr[xfit1], Memr[yfit1], NGRAPH)
+ call gflush (gd)
+
+ # Free space.
+ call sfree (sp)
+ }
+end
+
+
+# GEO_GCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift,
+
+procedure geo_gcoeffr (sx, sy, xshift, yshift, a, b, c, d)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+real xshift #O output x shift
+real yshift #O output y shift
+real a #O output x coefficient of x fit
+real b #O output y coefficient of x fit
+real c #O output x coefficient of y fit
+real d #O output y coefficient of y fit
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+real xxrange, xyrange, xxmaxmin, xymaxmin
+real yxrange, yyrange, yxmaxmin, yymaxmin
+
+int gsgeti()
+real gsgetr()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xcoeff, gsgeti (sx, GSNCOEFF), TY_REAL)
+ call salloc (ycoeff, gsgeti (sy, GSNCOEFF), TY_REAL)
+
+ # Get coefficients and numbers of coefficients.
+ call gscoeff (sx, Memr[xcoeff], nxxcoeff)
+ call gscoeff (sy, Memr[ycoeff], nyycoeff)
+ nxxcoeff = gsgeti (sx, GSNXCOEFF)
+ nxycoeff = gsgeti (sx, GSNYCOEFF)
+ nyxcoeff = gsgeti (sy, GSNXCOEFF)
+ nyycoeff = gsgeti (sy, GSNYCOEFF)
+
+ # Get the data range.
+ if (gsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (gsgetr (sx, GSXMAX) - gsgetr (sx, GSXMIN)) / 2.0
+ xxmaxmin = - (gsgetr (sx, GSXMAX) + gsgetr (sx, GSXMIN)) / 2.0
+ xyrange = (gsgetr (sx, GSYMAX) - gsgetr (sx, GSYMIN)) / 2.0
+ xymaxmin = - (gsgetr (sx, GSYMAX) + gsgetr (sx, GSYMIN)) / 2.0
+ } else {
+ xxrange = real(1.0)
+ xxmaxmin = real(0.0)
+ xyrange = real(1.0)
+ xymaxmin = real(0.0)
+ }
+
+ if (gsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (gsgetr (sy, GSXMAX) - gsgetr (sy, GSXMIN)) / 2.0
+ yxmaxmin = - (gsgetr (sy, GSXMAX) + gsgetr (sy, GSXMIN)) / 2.0
+ yyrange = (gsgetr (sy, GSYMAX) - gsgetr (sy, GSYMIN)) / 2.0
+ yymaxmin = - (gsgetr (sy, GSYMAX) + gsgetr (sy, GSYMIN)) / 2.0
+ } else {
+ yxrange = real(1.0)
+ yxmaxmin = real(0.0)
+ yyrange = real(1.0)
+ yymaxmin = real(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Memr[xcoeff] + Memr[xcoeff+1] * xxmaxmin / xxrange +
+ Memr[xcoeff+2] * xymaxmin / xyrange
+ yshift = Memr[ycoeff] + Memr[ycoeff+1] * yxmaxmin / yxrange +
+ Memr[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Memr[xcoeff+1] / xxrange
+ else
+ a = real(0.0)
+ if (nxycoeff > 1)
+ b = Memr[xcoeff+nxxcoeff] / xyrange
+ else
+ b = real(0.0)
+ if (nyxcoeff > 1)
+ c = Memr[ycoeff+1] / yxrange
+ else
+ c = real(0.0)
+ if (nyycoeff > 1)
+ d = Memr[ycoeff+nyxcoeff] / yyrange
+ else
+ d = real(0.0)
+
+ call sfree (sp)
+end
+
+
+
+# GEO_1DELETE -- Delete a point from the fit.
+
+procedure geo_1deleted (gd, xin, yin, wts, userwts, npts, wx, wy, delete)
+
+pointer gd #I pointer to graphics descriptor
+double xin[ARB] #I x array
+double yin[ARB] #I y array
+double wts[ARB] #I array of weights
+double userwts[ARB] #I array of user weights
+int npts #I number of points
+real wx, wy #I world coordinates
+int delete #I delete points ?
+
+int i, j, pmltype
+real r2min, r2, x0, y0
+int gstati()
+
+begin
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ if (delete == YES) {
+
+ # Search for nearest point that has not been deleted.
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ next
+ call gctran (gd, real (xin[i]), real (yin[i]), x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Mark point and set weights to 0.
+ if (j != 0) {
+ call gscur (gd, real(xin[j]), real(yin[j]))
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_CROSS, 2., 2.)
+ wts[j] = double(0.0)
+ }
+
+ } else {
+
+ # Search for the nearest deleted point.
+ do i = 1, npts {
+ if (wts[i] > double(0.0))
+ next
+ call gctran (gd, real(xin[i]), real(yin[i]), x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Erase cross and remark with a plus.
+ if (j != 0) {
+ call gscur (gd, real(xin[j]), real(yin[j]))
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_PLUS, 2., 2.)
+ wts[j] = userwts[j]
+ }
+ }
+end
+
+
+# GEO_2DELETE -- Delete the residuals.
+
+procedure geo_2deleted (gd, x, resid, wts, userwts, npts, wx, wy, delete)
+
+pointer gd #I pointer to graphics descriptor
+double x[ARB] #I reference x values
+double resid[ARB] #I residuals
+double wts[ARB] #I weight array
+double userwts[ARB] #I user weight array
+int npts #I number of points
+real wx #I world x coordinate
+real wy #I world y coordinate
+int delete #I delete point
+
+int i, j, pmltype
+real r2, r2min, x0, y0
+int gstati()
+
+begin
+ # Delete the point.
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ # Delete or add a point.
+ if (delete == YES) {
+
+ # Find the nearest undeleted point.
+ do i = 1, npts {
+ if (wts[i] <= double(0.0))
+ next
+ call gctran (gd, real(x[i]), real(resid[i]), x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Mark the point with a cross and set weight to zero.
+ if (j != 0) {
+ call gscur (gd, real(x[j]), real(resid[j]))
+ call gmark (gd, real(x[j]), real(resid[j]), GM_CROSS, 2., 2.)
+ wts[j] = double(0.0)
+ }
+
+ } else {
+
+ # Find the nearest deleted point.
+ do i = 1, npts {
+ if (wts[i] > double(0.0))
+ next
+ call gctran (gd, real(x[i]), real(resid[i]), x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Erase the cross and remark with a plus.
+ if (j != 0) {
+ call gscur (gd, real(x[j]), real(resid[j]))
+ pmltype = gstati (gd, G_PMLTYPE)
+ call gseti (gd, G_PMLTYPE, 0)
+ call gmark (gd, real(x[j]), real(resid[j]), GM_CROSS, 2., 2.)
+ call gseti (gd, G_PMLTYPE, pmltype)
+ call gmark (gd, real(x[j]), real(resid[j]), GM_PLUS, 2., 2.)
+ wts[j] = userwts[j]
+ }
+ }
+end
+
+
+# GEO_1GRAPH - Procedure to graph the distribution of the data in the x-y
+# plane. Rejected points are marked by a ' ' and deleted points are marked
+# by a ' '. The shift in position of the data points are indicated by
+# vectors. Sample fits of constant x and y are marked on the plots.
+
+procedure geo_1graphd (gd, gt, fit, gfit, xref, yref, xin, yin, wts, npts)
+
+pointer gd #I pointer to the graphics device
+pointer gt #I pointer to the plot descriptor
+pointer fit #I pointer to the geofit structure
+pointer gfit #I pointer to the plot structure
+double xref[ARB] #I x reference values
+double yref[ARB] #I y reference values
+double xin[ARB] #I x values
+double yin[ARB] #I y values
+double wts[ARB] #I array of weights
+int npts #I number of points
+
+int i, j
+pointer sp, rxin, ryin
+
+begin
+ # If previous plot different type don't overplot.
+ if (GG_PLOTTYPE(gfit) != FIT)
+ GG_OVERPLOT(gfit) = NO
+
+ # If not overplottting start new plot.
+ if (GG_OVERPLOT(gfit) == NO) {
+
+ # Set scale and axes.
+ call gclear (gd)
+ call smark (sp)
+ call salloc (rxin, npts, TY_REAL)
+ call salloc (ryin, npts, TY_REAL)
+ call achtdr (xin, Memr[rxin], npts)
+ call achtdr (yin, Memr[ryin], npts)
+ call gascale (gd, Memr[rxin], npts, 1)
+ call gascale (gd, Memr[ryin], npts, 2)
+ call sfree (sp)
+ call gt_swind (gd, gt)
+ call gtlabax (gd, gt)
+
+ # Mark the data and deleted points.
+ do i = 1, npts {
+ if (wts[i] == double(0.0))
+ call gmark (gd, real(xin[i]), real(yin[i]), GM_CROSS,
+ 2., 2.)
+ else
+ call gmark (gd, real(xin[i]), real(yin[i]), GM_PLUS,
+ 2., 2.)
+ }
+
+ call gflush (gd)
+ }
+
+ # Mark the rejected points.
+ do i = 1, GM_NREJECT(fit) {
+ j = Memi[GM_REJ(fit)+i-1]
+ call gmark (gd, real(xin[j]), real(yin[j]), GM_CIRCLE, 2., 2.)
+ }
+
+ call gflush (gd)
+
+ # Reset the status flags
+ GG_OVERPLOT(gfit) = NO
+end
+
+
+# GEO_2GRAPH -- Graph the x and y fit residuals versus x or y .
+
+procedure geo_2graphd (gd, gt, fit, gfit, x, resid, wts, npts)
+
+pointer gd #I pointer to the graphics device
+pointer gt #I pointer to the plot descriptor
+pointer fit #I pointer to geomap structure
+pointer gfit #I pointer to the plot structure
+double x[ARB] #I x reference values
+double resid[ARB] #I residual
+double wts[ARB] #I array of weights
+int npts #I number of points
+
+int i, j
+pointer sp, zero
+pointer rxin, ryin
+
+begin
+ # Allocate space.
+ call smark (sp)
+ call salloc (zero, npts, TY_REAL)
+ call amovkr (0.0, Memr[zero], npts)
+
+ # Calculate the residuals.
+ if (GG_PLOTTYPE(gfit) == FIT)
+ GG_OVERPLOT(gfit) = NO
+
+ if (GG_OVERPLOT(gfit) == NO) {
+
+ call gclear (gd)
+
+ # Set scale and axes.
+ call salloc (rxin, npts, TY_REAL)
+ call salloc (ryin, npts, TY_REAL)
+ call achtdr (x, Memr[rxin], npts)
+ call achtdr (resid, Memr[ryin], npts)
+ call gascale (gd, Memr[rxin], npts, 1)
+ call gascale (gd, Memr[ryin], npts, 2)
+ call gt_swind (gd, gt)
+ call gtlabax (gd, gt)
+
+ call gpline (gd, Memr[rxin], Memr[zero], npts)
+ }
+
+ # Graph residuals and mark deleted points.
+ if (GG_OVERPLOT(gfit) == NO || GG_NEWFUNCTION(gfit) == YES) {
+ do i = 1, npts {
+ if (wts[i] == double(0.0))
+ call gmark (gd, Memr[rxin+i-1], Memr[ryin+i-1],
+ GM_CROSS, 2., 2.)
+ else
+ call gmark (gd, Memr[rxin+i-1], Memr[ryin+i-1],
+ GM_PLUS, 2., 2.)
+ }
+ }
+
+ # plot rejected points
+ if (GM_NREJECT(fit) > 0) {
+ do i = 1, GM_NREJECT(fit) {
+ j = Memi[GM_REJ(fit)+i-1]
+ call gmark (gd, Memr[rxin+j-1], Memr[ryin+j-1], GM_CIRCLE,
+ 2., 2.)
+ }
+ }
+
+ # Reset the status flag.
+ GG_OVERPLOT(gfit) = NO
+
+ call gflush (gd)
+ call sfree (sp)
+end
+
+
+# GEO_CONXY -- Plot a set of default lines of xref = const and yref = const.
+
+procedure geo_conxyd (gd, fit, sx1, sy1, sx2, sy2)
+
+pointer gd #I graphics file descriptor
+pointer fit #I fit descriptor
+pointer sx1, sy1 #I pointer to the linear x and y surface fits
+pointer sx2, sy2 #I pointer to the linear x and y surface fits
+
+int i
+pointer sp, xtemp, ytemp, xfit1, yfit1, xfit2, yfit2
+pointer xbuf, ybuf
+double xint, yint, dx, dy
+
+begin
+ # allocate temporary space
+ call smark (sp)
+ call salloc (xtemp, NGRAPH, TY_DOUBLE)
+ call salloc (ytemp, NGRAPH, TY_DOUBLE)
+ call salloc (xfit1, NGRAPH, TY_DOUBLE)
+ call salloc (yfit1, NGRAPH, TY_DOUBLE)
+ call salloc (xfit2, NGRAPH, TY_DOUBLE)
+ call salloc (yfit2, NGRAPH, TY_DOUBLE)
+ call salloc (xbuf, NGRAPH, TY_REAL)
+ call salloc (ybuf, NGRAPH, TY_REAL)
+
+ # Calculate intervals in x and y.
+ dx = (GM_XMAX(fit) - GM_XMIN(fit)) / NINTERVALS
+ dy = (GM_YMAX(fit) - GM_YMIN(fit)) / (NGRAPH - 1)
+
+ # Set up an array of y values.
+ Memd[ytemp] = GM_YMIN(fit)
+ do i = 2, NGRAPH
+ Memd[ytemp+i-1] = Memd[ytemp+i-2] + dy
+
+ # Mark lines of constant x.
+ xint = GM_XMIN(fit)
+ for (i = 1; i <= NINTERVALS + 1; i = i + 1) {
+
+ # Set the x value.
+ call amovkd (xint, Memd[xtemp], NGRAPH)
+
+ # X fit.
+ call dgsvector (sx1, Memd[xtemp], Memd[ytemp], Memd[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call dgsvector (sx2, Memd[xtemp], Memd[ytemp], Memd[xfit2],
+ NGRAPH)
+ call aaddd (Memd[xfit1], Memd[xfit2], Memd[xfit1], NGRAPH)
+ }
+
+ # Y fit.
+ call dgsvector (sy1, Memd[xtemp], Memd[ytemp], Memd[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call dgsvector (sy2, Memd[xtemp], Memd[ytemp], Memd[yfit2],
+ NGRAPH)
+ call aaddd (Memd[yfit1], Memd[yfit2], Memd[yfit1], NGRAPH)
+ }
+
+ # Plot line of constant x.
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+
+ # Update the x value.
+ xint = xint + dx
+ }
+
+ call gflush (gd)
+
+ # Calculate x and y intervals.
+ dx = (GM_XMAX(fit) - GM_XMIN(fit)) / (NGRAPH - 1)
+ dy = (GM_YMAX(fit) - GM_YMIN(fit)) / NINTERVALS
+
+ # Set up array of x values.
+ Memd[xtemp] = GM_XMIN(fit)
+ do i = 2, NGRAPH
+ Memd[xtemp+i-1] = Memd[xtemp+i-2] + dx
+
+ # Mark lines of constant y.
+ yint = GM_YMIN(fit)
+ for (i = 1; i <= NINTERVALS + 1; i = i + 1) {
+
+ # set the y value
+ call amovkd (yint, Memd[ytemp], NGRAPH)
+
+ # X fit.
+ call dgsvector (sx1, Memd[xtemp], Memd[ytemp], Memd[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call dgsvector (sx2, Memd[xtemp], Memd[ytemp], Memd[xfit2],
+ NGRAPH)
+ call aaddd (Memd[xfit1], Memd[xfit2], Memd[xfit1], NGRAPH)
+ }
+
+
+ # Y fit.
+ call dgsvector (sy1, Memd[xtemp], Memd[ytemp], Memd[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call dgsvector (sy2, Memd[xtemp], Memd[ytemp], Memd[yfit2],
+ NGRAPH)
+ call aaddd (Memd[yfit1], Memd[yfit2], Memd[yfit1], NGRAPH)
+ }
+
+ # Plot line of constant y.
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+
+ # Update the y value.
+ yint = yint + dy
+ }
+
+ call gflush (gd)
+
+ call sfree (sp)
+end
+
+
+# GEO_LXY -- Draw a line of constant x-y.
+
+procedure geo_lxyd (gd, fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, npts,
+ wx, wy)
+
+pointer gd #I pointer to graphics descriptor
+pointer fit #I pointer to the fit parameters
+pointer sx1 #I pointer to the linear x fit
+pointer sy1 #I pointer to the linear y fit
+pointer sx2 #I pointer to the higher order x fit
+pointer sy2 #I pointer to the higher order y fit
+double xref[ARB] #I x reference values
+double yref[ARB] #I y reference values
+double xin[ARB] #I x input values
+double yin[ARB] #I y input values
+int npts #I number of data points
+real wx, wy #I x and y world coordinates
+
+int i, j
+pointer sp, xtemp, ytemp, xfit1, yfit1, xfit2, yfit2
+pointer xbuf, ybuf
+real x0, y0, r2, r2min
+double delta, deltax, deltay
+double dgseval()
+
+begin
+ # Transform world coordinates.
+ call gctran (gd, wx, wy, wx, wy, 1, 0)
+ r2min = MAX_REAL
+ j = 0
+
+ # Find the nearest data point.
+ do i = 1, npts {
+ call gctran (gd, real(xin[i]), real(yin[i]), x0, y0, 1, 0)
+ r2 = (x0 - wx) ** 2 + (y0 - wy) ** 2
+ if (r2 < r2min) {
+ r2min = r2
+ j = i
+ }
+ }
+
+ # Fit the line
+ if (j != 0) {
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (xtemp, NGRAPH, TY_DOUBLE)
+ call salloc (ytemp, NGRAPH, TY_DOUBLE)
+ call salloc (xfit1, NGRAPH, TY_DOUBLE)
+ call salloc (yfit1, NGRAPH, TY_DOUBLE)
+ call salloc (xfit2, NGRAPH, TY_DOUBLE)
+ call salloc (yfit2, NGRAPH, TY_DOUBLE)
+ call salloc (xbuf, NGRAPH, TY_REAL)
+ call salloc (ybuf, NGRAPH, TY_REAL)
+
+ # Compute the deltas.
+ deltax = xin[j] - dgseval (sx1, xref[j], yref[j])
+ if (sx2 != NULL)
+ deltax = deltax - dgseval (sx2, xref[j], yref[j])
+ deltay = yin[j] - dgseval (sy1, xref[j], yref[j])
+ if (sy2 != NULL)
+ deltay = deltay - dgseval (sy2, xref[j], yref[j])
+
+ # Set up line of constant x.
+ call amovkd (xref[j], Memd[xtemp], NGRAPH)
+ delta = (GM_YMAX(fit) - GM_YMIN(fit)) / (NGRAPH - 1)
+ Memd[ytemp] = GM_YMIN(fit)
+ do i = 2, NGRAPH
+ Memd[ytemp+i-1] = Memd[ytemp+i-2] + delta
+
+ # X solution.
+ call dgsvector (sx1, Memd[xtemp], Memd[ytemp], Memd[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call dgsvector (sx2, Memd[xtemp], Memd[ytemp], Memd[xfit2],
+ NGRAPH)
+ call aaddd (Memd[xfit1], Memd[xfit2], Memd[xfit1], NGRAPH)
+ }
+ call aaddkd (Memd[xfit1], deltax, Memd[xfit1], NGRAPH)
+
+ # Y solution.
+ call dgsvector (sy1, Memd[xtemp], Memd[ytemp], Memd[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call dgsvector (sy2, Memd[xtemp], Memd[ytemp], Memd[yfit2],
+ NGRAPH)
+ call aaddd (Memd[yfit1], Memd[yfit2], Memd[yfit1], NGRAPH)
+ }
+ call aaddkd (Memd[yfit1], deltay, Memd[yfit1], NGRAPH)
+
+ # Plot line of constant x.
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+ call gflush (gd)
+
+ # Set up line of constant y.
+ call amovkd (yref[j], Memd[ytemp], NGRAPH)
+ delta = (GM_XMAX(fit) - GM_XMIN(fit)) / (NGRAPH - 1)
+ Memd[xtemp] = GM_XMIN(fit)
+ do i = 2, NGRAPH
+ Memd[xtemp+i-1] = Memd[xtemp+i-2] + delta
+
+ # X fit.
+ call dgsvector (sx1, Memd[xtemp], Memd[ytemp], Memd[xfit1],
+ NGRAPH)
+ if (sx2 != NULL) {
+ call dgsvector (sx2, Memd[xtemp], Memd[ytemp], Memd[xfit2],
+ NGRAPH)
+ call aaddd (Memd[xfit1], Memd[xfit2], Memd[xfit1], NGRAPH)
+ }
+ call aaddkd (Memd[xfit1], deltax, Memd[xfit1], NGRAPH)
+
+ # Y fit.
+ call dgsvector (sy1, Memd[xtemp], Memd[ytemp], Memd[yfit1],
+ NGRAPH)
+ if (sy2 != NULL) {
+ call dgsvector (sy2, Memd[xtemp], Memd[ytemp], Memd[yfit2],
+ NGRAPH)
+ call aaddd (Memd[yfit1], Memd[yfit2], Memd[yfit1], NGRAPH)
+ }
+ call aaddkd (Memd[yfit1], deltay, Memd[yfit1], NGRAPH)
+
+ # Plot line of constant y.
+ call achtdr (Memd[xfit1], Memr[xbuf], NGRAPH)
+ call achtdr (Memd[yfit1], Memr[ybuf], NGRAPH)
+ call gpline (gd, Memr[xbuf], Memr[ybuf], NGRAPH)
+ call gflush (gd)
+
+ # Free space.
+ call sfree (sp)
+ }
+end
+
+
+# GEO_GCOEFF -- Print the coefficents of the linear portion of the
+# fit, xshift, yshift,
+
+procedure geo_gcoeffd (sx, sy, xshift, yshift, a, b, c, d)
+
+pointer sx #I pointer to the x surface fit
+pointer sy #I pointer to the y surface fit
+double xshift #O output x shift
+double yshift #O output y shift
+double a #O output x coefficient of x fit
+double b #O output y coefficient of x fit
+double c #O output x coefficient of y fit
+double d #O output y coefficient of y fit
+
+int nxxcoeff, nxycoeff, nyxcoeff, nyycoeff
+pointer sp, xcoeff, ycoeff
+double xxrange, xyrange, xxmaxmin, xymaxmin
+double yxrange, yyrange, yxmaxmin, yymaxmin
+
+int dgsgeti()
+double dgsgetd()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (xcoeff, dgsgeti (sx, GSNCOEFF), TY_DOUBLE)
+ call salloc (ycoeff, dgsgeti (sy, GSNCOEFF), TY_DOUBLE)
+
+ # Get coefficients and numbers of coefficients.
+ call dgscoeff (sx, Memd[xcoeff], nxxcoeff)
+ call dgscoeff (sy, Memd[ycoeff], nyycoeff)
+ nxxcoeff = dgsgeti (sx, GSNXCOEFF)
+ nxycoeff = dgsgeti (sx, GSNYCOEFF)
+ nyxcoeff = dgsgeti (sy, GSNXCOEFF)
+ nyycoeff = dgsgeti (sy, GSNYCOEFF)
+
+ # Get the data range.
+ if (dgsgeti (sx, GSTYPE) != GS_POLYNOMIAL) {
+ xxrange = (dgsgetd (sx, GSXMAX) - dgsgetd (sx, GSXMIN)) / 2.0d0
+ xxmaxmin = - (dgsgetd (sx, GSXMAX) + dgsgetd (sx, GSXMIN)) / 2.0d0
+ xyrange = (dgsgetd (sx, GSYMAX) - dgsgetd (sx, GSYMIN)) / 2.0d0
+ xymaxmin = - (dgsgetd (sx, GSYMAX) + dgsgetd (sx, GSYMIN)) / 2.0d0
+ } else {
+ xxrange = double(1.0)
+ xxmaxmin = double(0.0)
+ xyrange = double(1.0)
+ xymaxmin = double(0.0)
+ }
+
+ if (dgsgeti (sy, GSTYPE) != GS_POLYNOMIAL) {
+ yxrange = (dgsgetd (sy, GSXMAX) - dgsgetd (sy, GSXMIN)) / 2.0d0
+ yxmaxmin = - (dgsgetd (sy, GSXMAX) + dgsgetd (sy, GSXMIN)) / 2.0d0
+ yyrange = (dgsgetd (sy, GSYMAX) - dgsgetd (sy, GSYMIN)) / 2.0d0
+ yymaxmin = - (dgsgetd (sy, GSYMAX) + dgsgetd (sy, GSYMIN)) / 2.0d0
+ } else {
+ yxrange = double(1.0)
+ yxmaxmin = double(0.0)
+ yyrange = double(1.0)
+ yymaxmin = double(0.0)
+ }
+
+ # Get the shifts.
+ xshift = Memd[xcoeff] + Memd[xcoeff+1] * xxmaxmin / xxrange +
+ Memd[xcoeff+2] * xymaxmin / xyrange
+ yshift = Memd[ycoeff] + Memd[ycoeff+1] * yxmaxmin / yxrange +
+ Memd[ycoeff+2] * yymaxmin / yyrange
+
+ # Get the rotation and scaling parameters and correct for normalization.
+ if (nxxcoeff > 1)
+ a = Memd[xcoeff+1] / xxrange
+ else
+ a = double(0.0)
+ if (nxycoeff > 1)
+ b = Memd[xcoeff+nxxcoeff] / xyrange
+ else
+ b = double(0.0)
+ if (nyxcoeff > 1)
+ c = Memd[ycoeff+1] / yxrange
+ else
+ c = double(0.0)
+ if (nyycoeff > 1)
+ d = Memd[ycoeff+nyxcoeff] / yyrange
+ else
+ d = double(0.0)
+
+ call sfree (sp)
+end
+
+
diff --git a/pkg/images/lib/geomap.h b/pkg/images/lib/geomap.h
new file mode 100644
index 00000000..f67d64f3
--- /dev/null
+++ b/pkg/images/lib/geomap.h
@@ -0,0 +1,109 @@
+# Header file for GEOMAP
+
+define LEN_GEOMAP (54 + SZ_FNAME + SZ_LINE + 2)
+
+define GM_XO Memd[P2D($1)] # X origin
+define GM_YO Memd[P2D($1+2)] # Y origin
+define GM_ZO Memd[P2D($1+4)] # Z origin
+define GM_XOREF Memd[P2D($1+6)] # X reference origin
+define GM_YOREF Memd[P2D($1+8)] # Y reference origin
+define GM_XMIN Memd[P2D($1+10)] # Minimum x value
+define GM_XMAX Memd[P2D($1+12)] # Maximum x value
+define GM_YMIN Memd[P2D($1+14)] # Minimum y value
+define GM_YMAX Memd[P2D($1+16)] # Maximum y value
+define GM_XOREF Memd[P2D($1+18)] # Mean of xref coords
+define GM_YOREF Memd[P2D($1+20)] # Mean of yref coords
+define GM_XOIN Memd[P2D($1+22)] # Mean of x coords
+define GM_YOIN Memd[P2D($1+24)] # Mean of y coords
+define GM_XREFPT Memd[P2D($1+26)] # Computed X reference point
+define GM_YREFPT Memd[P2D($1+28)] # Computed Y reference point
+define GM_XRMS Memd[P2D($1+30)] # Rms of x fit
+define GM_YRMS Memd[P2D($1+32)] # Rms of y fit
+define GM_REJECT Memd[P2D($1+34)] # Sigma limit for rejection
+define GM_PROJECTION Memi[$1+36] # Coordinate projection type
+define GM_FIT Memi[$1+37] # Fit geometry type
+define GM_FUNCTION Memi[$1+38] # Function type
+define GM_XXORDER Memi[$1+39] # X fit X order
+define GM_XYORDER Memi[$1+40] # X fit Y order
+define GM_XXTERMS Memi[$1+41] # X fit cross-terms
+define GM_YXORDER Memi[$1+42] # Y fit X order
+define GM_YYORDER Memi[$1+43] # Y fit Y order
+define GM_YXTERMS Memi[$1+44] # Y fit cross-terms
+define GM_MAXITER Memi[$1+45] # maximum number of iterations
+define GM_NPTS Memi[$1+46] # Number of data points
+define GM_NREJECT Memi[$1+47] # Number of rejected pixels
+define GM_NWTS0 Memi[$1+48] # Number of pts with wts <= 0
+define GM_REJ Memi[$1+49] # Pointer to rejected pixels
+define GM_RECORD Memc[P2C($1+50)] # Record name
+define GM_PROJSTR Memc[P2C($1+50+SZ_FNAME+1)] # Projection parameters
+
+# geoset parameters
+define GMXO 1
+define GMYO 2
+define GMXOREF 3
+define GMYOREF 4
+define GMPROJECTION 5
+define GMFIT 6
+define GMFUNCTION 7
+define GMXXORDER 8
+define GMXYORDER 9
+define GMYXORDER 10
+define GMYYORDER 11
+define GMXXTERMS 12
+define GMYXTERMS 13
+define GMREJECT 14
+define GMMAXITER 15
+
+# define the permitted coordinate projections
+
+define GM_PROJLIST "|lin|azp|tan|sin|stg|arc|zpn|zea|air|cyp|car|\
+mer|cea|cop|cod|coe|coo|bon|pco|gls|par|ait|mol|csc|qsc|tsc|tnx|zpx|"
+
+define GM_NONE 0
+define GM_LIN 1
+define GM_AZP 2
+define GM_TAN 3
+define GM_SIN 4
+define GM_STG 5
+define GM_ARC 6
+define GM_ZPN 7
+define GM_ZEA 8
+define GM_AIR 9
+define GM_CYP 10
+define GM_CAR 11
+define GM_MER 12
+define GM_CEA 13
+define GM_COP 14
+define GM_COD 15
+define GM_COE 16
+define GM_COO 17
+define GM_BON 18
+define GM_PCO 19
+define GM_GLS 20
+define GM_PAR 21
+define GM_AIT 22
+define GM_MOL 23
+define GM_CSC 24
+define GM_QSC 25
+define GM_TSC 26
+define GM_TNX 27
+define GM_ZPX 28
+
+# define the permitted fitting geometries
+
+define GM_GEOMETRIES "|shift|xyscale|rotate|rscale|rxyscale|general|"
+
+define GM_SHIFT 1
+define GM_XYSCALE 2
+define GM_ROTATE 3
+define GM_RSCALE 4
+define GM_RXYSCALE 5
+define GM_GENERAL 6
+
+# define the permitted fitting functions
+
+define GM_FUNCS "|chebyshev|legendre|polynomial|"
+
+# define the permitted x-terms functions
+
+define GM_XFUNCS "|none|full|half|"
diff --git a/pkg/images/lib/geomap.key b/pkg/images/lib/geomap.key
new file mode 100644
index 00000000..5cc5d043
--- /dev/null
+++ b/pkg/images/lib/geomap.key
@@ -0,0 +1,31 @@
+ Interactive Keystroke Commands
+
+? Print options
+f Fit data and graph fit with the current graph type (g,x,r,y,s)
+g Graph the data and the current fit
+x,r Graph the x(in) fit residuals versus x(ref) and y(ref) respectively
+y,s Graph the y(in) fit residuals versus x(ref) and y(ref) respectively
+d,u Delete or undelete the data point nearest the cursor
+o Overplot the next graph
+c Toggle the line of constant x(ref), y(ref) plotting option
+t Plot a line of constant x(ref), y(ref) through nearest data point
+l Print xshift, yshift, xscale, yscale, xrotate, yrotate
+q Exit the interactive surface fitting code
+
+ Interactive Colon Commands
+
+The parameters are listed or set with the following commands which may be
+abbreviated. To list the value of a parameter type the command alone.
+
+:show List parameters
+:fit [value] Fit geometry (shift,xyscale,rotate,rscale,rxyscale,general)
+:function [value] Fitting function (chebyshev,legendre,polynomial)
+:order [value] X and Y fitting orders in x and y
+:xxorder [value] X fitting function order in x
+:xyorder [value] X fitting function order in y
+:yxorder [value] Y fitting function order in x
+:yyorder [value] Y fitting function order in y
+:xxterms [n/h/f] X fit cross terms type
+:yxterms [n/h/f] Y fit cross terms type
+:maxiter [value] Maximum number of rejection iterations
+:reject [value] K-sigma rejection threshold
diff --git a/pkg/images/lib/geoset.x b/pkg/images/lib/geoset.x
new file mode 100644
index 00000000..9591fa21
--- /dev/null
+++ b/pkg/images/lib/geoset.x
@@ -0,0 +1,61 @@
+# Copyright(c) 1986 Assocation of Universities for Research in Astronomy Inc.
+
+include "geomap.h"
+
+
+# GEO_SETI -- Set integer parameters.
+
+procedure geo_seti (fit, param, ival)
+
+pointer fit #I pointer to the fit structure
+int param #I paramter ID
+int ival #I value
+
+begin
+ switch (param) {
+ case GMPROJECTION:
+ GM_PROJECTION(fit) = ival
+ case GMFIT:
+ GM_FIT(fit) = ival
+ case GMFUNCTION:
+ GM_FUNCTION(fit) = ival
+ case GMXXORDER:
+ GM_XXORDER(fit) = ival
+ case GMXYORDER:
+ GM_XYORDER(fit) = ival
+ case GMYXORDER:
+ GM_YXORDER(fit) = ival
+ case GMYYORDER:
+ GM_YYORDER(fit) = ival
+ case GMXXTERMS:
+ GM_XXTERMS(fit) = ival
+ case GMYXTERMS:
+ GM_YXTERMS(fit) = ival
+ case GMMAXITER:
+ GM_MAXITER(fit) = ival
+ }
+end
+
+
+# GEO_SETD -- Set double parameters.
+
+procedure geo_setd (fit, param, dval)
+
+pointer fit #I pointer to the fit structure
+int param #I paramter ID
+double dval #I value
+
+begin
+ switch (param) {
+ case GMXO:
+ GM_XO(fit) = dval
+ case GMYO:
+ GM_YO(fit) = dval
+ case GMXOREF:
+ GM_XOREF(fit) = dval
+ case GMYOREF:
+ GM_YOREF(fit) = dval
+ case GMREJECT:
+ GM_REJECT(fit) = dval
+ }
+end
diff --git a/pkg/images/lib/imcopy.x b/pkg/images/lib/imcopy.x
new file mode 100644
index 00000000..1d33693d
--- /dev/null
+++ b/pkg/images/lib/imcopy.x
@@ -0,0 +1,106 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+
+# IMG_IMCOPY -- Copy an image. Use sequential routines to permit copying
+# images of any dimension. Perform pixel i/o in the datatype of the image,
+# to avoid unnecessary type conversion.
+
+procedure img_imcopy (image1, image2, verbose)
+
+char image1[ARB] # Input image
+char image2[ARB] # Output image
+bool verbose # Print the operation
+
+int npix, junk
+pointer buf1, buf2, im1, im2
+pointer sp, root1, root2, imtemp, section
+long v1[IM_MAXDIM], v2[IM_MAXDIM]
+
+bool strne()
+int imgnls(), imgnll(), imgnlr(), imgnld(), imgnlx()
+int impnls(), impnll(), impnlr(), impnld(), impnlx()
+pointer immap()
+
+begin
+ call smark (sp)
+ call salloc (root1, SZ_PATHNAME, TY_CHAR)
+ call salloc (root2, SZ_PATHNAME, TY_CHAR)
+ call salloc (imtemp, SZ_PATHNAME, TY_CHAR)
+ call salloc (section, SZ_FNAME, TY_CHAR)
+
+ # If verbose print the operation.
+ if (verbose) {
+ call printf ("%s -> %s\n")
+ call pargstr (image1)
+ call pargstr (image2)
+ call flush (STDOUT)
+ }
+
+ # Get the input and output root names and the output section.
+ call imgimage (image1, Memc[root1], SZ_PATHNAME)
+ call imgimage (image2, Memc[root2], SZ_PATHNAME)
+ call imgsection (image2, Memc[section], SZ_FNAME)
+
+ # Map the input image.
+ im1 = immap (image1, READ_ONLY, 0)
+
+ # If the output has a section appended we are writing to a
+ # section of an existing image. Otherwise get a temporary
+ # output image name and map it as a copy of the input image.
+ # Copy the input image to the temporary output image and unmap
+ # the images. Release the temporary image name.
+
+ if (strne (Memc[root1], Memc[root2]) && Memc[section] != EOS) {
+ call strcpy (image2, Memc[imtemp], SZ_PATHNAME)
+ im2 = immap (image2, READ_WRITE, 0)
+ } else {
+ call xt_mkimtemp (image1, image2, Memc[imtemp], SZ_PATHNAME)
+ im2 = immap (image2, NEW_COPY, im1)
+ }
+
+ # Setup start vector for sequential reads and writes.
+
+ call amovkl (long(1), v1, IM_MAXDIM)
+ call amovkl (long(1), v2, IM_MAXDIM)
+
+ # Copy the image.
+
+ npix = IM_LEN(im1, 1)
+ switch (IM_PIXTYPE(im1)) {
+ case TY_SHORT:
+ while (imgnls (im1, buf1, v1) != EOF) {
+ junk = impnls (im2, buf2, v2)
+ call amovs (Mems[buf1], Mems[buf2], npix)
+ }
+ case TY_USHORT, TY_INT, TY_LONG:
+ while (imgnll (im1, buf1, v1) != EOF) {
+ junk = impnll (im2, buf2, v2)
+ call amovl (Meml[buf1], Meml[buf2], npix)
+ }
+ case TY_REAL:
+ while (imgnlr (im1, buf1, v1) != EOF) {
+ junk = impnlr (im2, buf2, v2)
+ call amovr (Memr[buf1], Memr[buf2], npix)
+ }
+ case TY_DOUBLE:
+ while (imgnld (im1, buf1, v1) != EOF) {
+ junk = impnld (im2, buf2, v2)
+ call amovd (Memd[buf1], Memd[buf2], npix)
+ }
+ case TY_COMPLEX:
+ while (imgnlx (im1, buf1, v1) != EOF) {
+ junk = impnlx (im2, buf2, v2)
+ call amovx (Memx[buf1], Memx[buf2], npix)
+ }
+ default:
+ call error (1, "unknown pixel datatype")
+ }
+
+ # Unmap the images.
+
+ call imunmap (im2)
+ call imunmap (im1)
+ call xt_delimtemp (image2, Memc[imtemp])
+ call sfree (sp)
+end
diff --git a/pkg/images/lib/liststr.gx b/pkg/images/lib/liststr.gx
new file mode 100644
index 00000000..ec627e0c
--- /dev/null
+++ b/pkg/images/lib/liststr.gx
@@ -0,0 +1,427 @@
+include <ctype.h>
+
+$for (r)
+
+# LI_FIND_FIELDS -- This procedure finds the starting column for each field
+# in the input line. These column numbers are returned in the array
+# field_pos; the number of fields is also returned.
+
+procedure li_find_fields (linebuf, field_pos, max_fields, nfields)
+
+char linebuf[ARB] #I the input buffer
+int field_pos[max_fields] #O the output field positions
+int max_fields #I the maximum number of fields
+int nfields #O the computed number of fields
+
+bool in_field
+int ip, field_num
+
+begin
+ field_num = 1
+ field_pos[1] = 1
+ in_field = false
+
+ for (ip=1; linebuf[ip] != '\n' && linebuf[ip] != EOS; ip=ip+1) {
+ if (! IS_WHITE(linebuf[ip]))
+ in_field = true
+ else if (in_field) {
+ in_field = false
+ field_num = field_num + 1
+ field_pos[field_num] = ip
+ }
+ }
+
+ field_pos[field_num+1] = ip
+ nfields = field_num
+end
+
+
+# LI_CAPPEND_LINE -- Fields are copied from the input buffer to the
+# output buffer.
+
+procedure li_cappend_line (inbuf, outbuf, maxch, xoffset, yoffset,
+ xwidth, ywidth)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int xoffset #I the offset to the x field
+int yoffset #I the offset to the y field
+int xwidth #I the width of the x field
+int ywidth #I the width of the y field
+
+int ip, op
+int gstrcpy()
+
+begin
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add a blank.
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy the two fields.
+ op = op + gstrcpy (inbuf[xoffset], outbuf[op], min (maxch - op + 1,
+ xwidth))
+ op = op + gstrcpy (inbuf[yoffset], outbuf[op], min (maxch - op + 1,
+ ywidth))
+
+ # Add a newline.
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ outbuf[op] = EOS
+end
+
+$endfor
+
+$for (rd)
+
+# LT_GET_NUM -- The field entry is converted from character to real or double
+# in preparation for the transformation. The number of significant
+# digits is counted and returned as an argument; the number of chars in
+# the number is returned as the function value.
+
+int procedure li_get_num$t (linebuf, fval, nsdig)
+
+char linebuf[ARB] #I the input line buffer
+PIXEL fval #O the output floating point value
+int nsdig #O the number of significant digits
+
+char ch
+int nchar, ip
+int cto$t(), stridx()
+
+begin
+ ip = 1
+ nsdig = 0
+ nchar = cto$t (linebuf, ip, fval)
+ if (nchar == 0 || fval == $INDEF$T)
+ return (nchar)
+
+ # Skip leading white space.
+ ip = 1
+ repeat {
+ ch = linebuf[ip]
+ if (! IS_WHITE(ch))
+ break
+ ip = ip + 1
+ }
+
+ # Count signifigant digits
+ for (; ! IS_WHITE(ch) && ch != '\n' && ch != EOS; ch=linebuf[ip]) {
+ if (stridx (ch, "eEdD") > 0)
+ break
+ if (IS_DIGIT (ch))
+ nsdig = nsdig + 1
+ ip = ip + 1
+ }
+
+ return (nchar)
+end
+
+
+# LI_PACK_LINE -- Fields are packed into the outbuf buffer. Transformed
+# fields are converted to strings; other fields are copied from
+# the input line to output buffer.
+
+procedure li_pack_line$t (inbuf, outbuf, maxch, field_pos, nfields,
+ xfield, yfield, xt, yt, xformat, yformat, nsdig_x, nsdig_y,
+ min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int xfield #I the field number of the x coordinate column
+int yfield #I the field number of the y coordinate column
+PIXEL xt #I the transformed x coordinate
+PIXEL yt #I the transformed y coordinate
+char xformat[ARB] #I the output format for the x column
+char yformat[ARB] #I the output format for the y column
+int nsdig_x #I the number of significant digits in x
+int nsdig_y #I the number of significant digits in y
+int min_sigdigits #I the minimum number of significant digits
+
+int num_field, width, op
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ do num_field = 1, nfields {
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ if (num_field == xfield) {
+ call li_format_field$t (xt, Memc[field], maxch, xformat,
+ nsdig_x, width, min_sigdigits)
+ } else if (num_field == yfield) {
+ call li_format_field$t (yt, Memc[field], maxch, yformat,
+ nsdig_y, width, min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_APPEND_LINE -- Fields are appened to the input buffer. Transformed
+# fields are converted to strings and added to the end of the input buffer.
+
+procedure li_append_line$t (inbuf, outbuf, maxch, xt, yt, xformat, yformat,
+ nsdig_x, nsdig_y, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+PIXEL xt #I the transformed x coordinate
+PIXEL yt #I the transformed y coordinate
+char xformat[ARB] #I the output format for the x column
+char yformat[ARB] #I the output format for the y column
+int nsdig_x #I the number of significant digits in x
+int nsdig_y #I the number of significant digits in y
+int min_sigdigits #I the minimum number of significant digits
+
+int ip, op
+pointer sp, field
+int gstrcpy()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add two blanks.
+ op = op + gstrcpy (" ", outbuf[op], maxch - op + 1)
+
+ # Format and add the the two extra fields with a blank between.
+ call li_format_field$t (xt, Memc[field], SZ_LINE, xformat,
+ nsdig_x, 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+ call li_format_field$t (yt, Memc[field], SZ_LINE, yformat,
+ nsdig_y, 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+
+ # Add a newline.
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ outbuf[op] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_FORMAT_FIELD -- A transformed coordinate is written into a string
+# buffer. The output field is of (at least) the same width and significance
+# as the input list entry.
+
+procedure li_format_field$t (fval, wordbuf, maxch, format, nsdig, width,
+ min_sigdigits)
+
+PIXEL fval #I the input value to be formatted
+char wordbuf[maxch] #O the output formatted string
+int maxch #I the maximum length of the output string
+char format[ARB] #I the output format
+int nsdig #I the number of sig-digits in current value
+int width #I the width of the curent field
+int min_sigdigits #I the minimum number of significant digits
+
+int fdigits, fwidth
+begin
+ if (format[1] == EOS) {
+ fdigits = max (min_sigdigits, nsdig)
+ fwidth = max (width, fdigits + 1)
+ call sprintf (wordbuf, maxch, "%*.*g")
+ call pargi (fwidth)
+ call pargi (fdigits)
+ call parg$t (fval)
+ } else {
+ call sprintf (wordbuf, maxch, format)
+ call parg$t (fval)
+ }
+end
+
+# LI_NPACK_LINE -- Fields are packed into the outbuf buffer. Transformed
+# fields are converted to strings; other fields are copied from
+# the input line to output buffer.
+
+procedure li_npack_line$t (inbuf, outbuf, maxch, field_pos, nfields,
+ vfields, values, nsdigits, nvalues, vformats, sz_fmt, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int vfields[ARB] #I the fields to be formatted
+PIXEL values[ARB] #I the field values to be formatted
+int nsdigits[ARB] #I the number of field significant digits
+int nvalues #I the number of fields to be formatted
+char vformats[sz_fmt,ARB] #I the field formats
+int sz_fmt #I the size of the format string
+int min_sigdigits #I the minimum number of significant digits
+
+bool found
+int op, num_field, num_var, width
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ do num_field = 1, nfields {
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ found = false
+ do num_var = 1, nvalues {
+ if (num_field == vfields[num_var]) {
+ found = true
+ break
+ }
+ }
+
+ if (found) {
+ call li_format_field$t (values[num_var], Memc[field],
+ maxch, vformats[1,num_var], nsdigits[num_var], width,
+ min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_NAPPEND_LINE -- Fields are appened to the input buffer. Transformed
+# fields are converted to strings and added to the end of the input buffer.
+
+procedure li_nappend_line$t (inbuf, outbuf, maxch, field_pos, nfields,
+ vfields, values, nsdigits, nvalues, vformats, sz_fmt, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int vfields[ARB] #I the fields to be formatted
+PIXEL values[ARB] #I the field values to be formatted
+int nsdigits[ARB] #I the number of field significant digits
+int nvalues #I the number of fields to be formatted
+char vformats[sz_fmt,ARB] #I the field formats
+int sz_fmt #I the size of the format string
+int min_sigdigits #I the minimum number of significant digits
+
+int num_var, ip, op, index
+pointer sp, field, nvfields
+int gstrcpy()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+ call salloc (nvfields, nvalues, TY_INT)
+ do num_var = 1, nvalues
+ Memi[nvfields+num_var-1] = num_var
+ call rg_qsorti (vfields, Memi[nvfields], Memi[nvfields], nvalues)
+
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add two blanks.
+ op = op + gstrcpy (" ", outbuf[op], maxch - op + 1)
+
+ do num_var = 1, nvalues {
+ index = Memi[nvfields+num_var-1]
+ call li_format_field$t (values[index], Memc[field], SZ_LINE,
+ vformats[sz_fmt,index], nsdigits[index], 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+ if (num_var == nvalues) {
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ } else {
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+ }
+ }
+
+ outbuf[op] = EOS
+
+ call sfree (sp)
+end
+
+
+$endfor
diff --git a/pkg/images/lib/liststr.x b/pkg/images/lib/liststr.x
new file mode 100644
index 00000000..edb2903c
--- /dev/null
+++ b/pkg/images/lib/liststr.x
@@ -0,0 +1,766 @@
+include <ctype.h>
+
+
+
+# LI_FIND_FIELDS -- This procedure finds the starting column for each field
+# in the input line. These column numbers are returned in the array
+# field_pos; the number of fields is also returned.
+
+procedure li_find_fields (linebuf, field_pos, max_fields, nfields)
+
+char linebuf[ARB] #I the input buffer
+int field_pos[max_fields] #O the output field positions
+int max_fields #I the maximum number of fields
+int nfields #O the computed number of fields
+
+bool in_field
+int ip, field_num
+
+begin
+ field_num = 1
+ field_pos[1] = 1
+ in_field = false
+
+ for (ip=1; linebuf[ip] != '\n' && linebuf[ip] != EOS; ip=ip+1) {
+ if (! IS_WHITE(linebuf[ip]))
+ in_field = true
+ else if (in_field) {
+ in_field = false
+ field_num = field_num + 1
+ field_pos[field_num] = ip
+ }
+ }
+
+ field_pos[field_num+1] = ip
+ nfields = field_num
+end
+
+
+# LI_CAPPEND_LINE -- Fields are copied from the input buffer to the
+# output buffer.
+
+procedure li_cappend_line (inbuf, outbuf, maxch, xoffset, yoffset,
+ xwidth, ywidth)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int xoffset #I the offset to the x field
+int yoffset #I the offset to the y field
+int xwidth #I the width of the x field
+int ywidth #I the width of the y field
+
+int ip, op
+int gstrcpy()
+
+begin
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add a blank.
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy the two fields.
+ op = op + gstrcpy (inbuf[xoffset], outbuf[op], min (maxch - op + 1,
+ xwidth))
+ op = op + gstrcpy (inbuf[yoffset], outbuf[op], min (maxch - op + 1,
+ ywidth))
+
+ # Add a newline.
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ outbuf[op] = EOS
+end
+
+
+
+
+
+# LT_GET_NUM -- The field entry is converted from character to real or double
+# in preparation for the transformation. The number of significant
+# digits is counted and returned as an argument; the number of chars in
+# the number is returned as the function value.
+
+int procedure li_get_numr (linebuf, fval, nsdig)
+
+char linebuf[ARB] #I the input line buffer
+real fval #O the output floating point value
+int nsdig #O the number of significant digits
+
+char ch
+int nchar, ip
+int ctor(), stridx()
+
+begin
+ ip = 1
+ nsdig = 0
+ nchar = ctor (linebuf, ip, fval)
+ if (nchar == 0 || fval == INDEFR)
+ return (nchar)
+
+ # Skip leading white space.
+ ip = 1
+ repeat {
+ ch = linebuf[ip]
+ if (! IS_WHITE(ch))
+ break
+ ip = ip + 1
+ }
+
+ # Count signifigant digits
+ for (; ! IS_WHITE(ch) && ch != '\n' && ch != EOS; ch=linebuf[ip]) {
+ if (stridx (ch, "eEdD") > 0)
+ break
+ if (IS_DIGIT (ch))
+ nsdig = nsdig + 1
+ ip = ip + 1
+ }
+
+ return (nchar)
+end
+
+
+# LI_PACK_LINE -- Fields are packed into the outbuf buffer. Transformed
+# fields are converted to strings; other fields are copied from
+# the input line to output buffer.
+
+procedure li_pack_liner (inbuf, outbuf, maxch, field_pos, nfields,
+ xfield, yfield, xt, yt, xformat, yformat, nsdig_x, nsdig_y,
+ min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int xfield #I the field number of the x coordinate column
+int yfield #I the field number of the y coordinate column
+real xt #I the transformed x coordinate
+real yt #I the transformed y coordinate
+char xformat[ARB] #I the output format for the x column
+char yformat[ARB] #I the output format for the y column
+int nsdig_x #I the number of significant digits in x
+int nsdig_y #I the number of significant digits in y
+int min_sigdigits #I the minimum number of significant digits
+
+int num_field, width, op
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ do num_field = 1, nfields {
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ if (num_field == xfield) {
+ call li_format_fieldr (xt, Memc[field], maxch, xformat,
+ nsdig_x, width, min_sigdigits)
+ } else if (num_field == yfield) {
+ call li_format_fieldr (yt, Memc[field], maxch, yformat,
+ nsdig_y, width, min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_APPEND_LINE -- Fields are appened to the input buffer. Transformed
+# fields are converted to strings and added to the end of the input buffer.
+
+procedure li_append_liner (inbuf, outbuf, maxch, xt, yt, xformat, yformat,
+ nsdig_x, nsdig_y, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+real xt #I the transformed x coordinate
+real yt #I the transformed y coordinate
+char xformat[ARB] #I the output format for the x column
+char yformat[ARB] #I the output format for the y column
+int nsdig_x #I the number of significant digits in x
+int nsdig_y #I the number of significant digits in y
+int min_sigdigits #I the minimum number of significant digits
+
+int ip, op
+pointer sp, field
+int gstrcpy()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add two blanks.
+ op = op + gstrcpy (" ", outbuf[op], maxch - op + 1)
+
+ # Format and add the the two extra fields with a blank between.
+ call li_format_fieldr (xt, Memc[field], SZ_LINE, xformat,
+ nsdig_x, 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+ call li_format_fieldr (yt, Memc[field], SZ_LINE, yformat,
+ nsdig_y, 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+
+ # Add a newline.
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ outbuf[op] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_FORMAT_FIELD -- A transformed coordinate is written into a string
+# buffer. The output field is of (at least) the same width and significance
+# as the input list entry.
+
+procedure li_format_fieldr (fval, wordbuf, maxch, format, nsdig, width,
+ min_sigdigits)
+
+real fval #I the input value to be formatted
+char wordbuf[maxch] #O the output formatted string
+int maxch #I the maximum length of the output string
+char format[ARB] #I the output format
+int nsdig #I the number of sig-digits in current value
+int width #I the width of the curent field
+int min_sigdigits #I the minimum number of significant digits
+
+int fdigits, fwidth
+begin
+ if (format[1] == EOS) {
+ fdigits = max (min_sigdigits, nsdig)
+ fwidth = max (width, fdigits + 1)
+ call sprintf (wordbuf, maxch, "%*.*g")
+ call pargi (fwidth)
+ call pargi (fdigits)
+ call pargr (fval)
+ } else {
+ call sprintf (wordbuf, maxch, format)
+ call pargr (fval)
+ }
+end
+
+# LI_NPACK_LINE -- Fields are packed into the outbuf buffer. Transformed
+# fields are converted to strings; other fields are copied from
+# the input line to output buffer.
+
+procedure li_npack_liner (inbuf, outbuf, maxch, field_pos, nfields,
+ vfields, values, nsdigits, nvalues, vformats, sz_fmt, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int vfields[ARB] #I the fields to be formatted
+real values[ARB] #I the field values to be formatted
+int nsdigits[ARB] #I the number of field significant digits
+int nvalues #I the number of fields to be formatted
+char vformats[sz_fmt,ARB] #I the field formats
+int sz_fmt #I the size of the format string
+int min_sigdigits #I the minimum number of significant digits
+
+bool found
+int op, num_field, num_var, width
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ do num_field = 1, nfields {
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ found = false
+ do num_var = 1, nvalues {
+ if (num_field == vfields[num_var]) {
+ found = true
+ break
+ }
+ }
+
+ if (found) {
+ call li_format_fieldr (values[num_var], Memc[field],
+ maxch, vformats[1,num_var], nsdigits[num_var], width,
+ min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_NAPPEND_LINE -- Fields are appened to the input buffer. Transformed
+# fields are converted to strings and added to the end of the input buffer.
+
+procedure li_nappend_liner (inbuf, outbuf, maxch, field_pos, nfields,
+ vfields, values, nsdigits, nvalues, vformats, sz_fmt, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int vfields[ARB] #I the fields to be formatted
+real values[ARB] #I the field values to be formatted
+int nsdigits[ARB] #I the number of field significant digits
+int nvalues #I the number of fields to be formatted
+char vformats[sz_fmt,ARB] #I the field formats
+int sz_fmt #I the size of the format string
+int min_sigdigits #I the minimum number of significant digits
+
+int num_var, ip, op, index
+pointer sp, field, nvfields
+int gstrcpy()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+ call salloc (nvfields, nvalues, TY_INT)
+ do num_var = 1, nvalues
+ Memi[nvfields+num_var-1] = num_var
+ call rg_qsorti (vfields, Memi[nvfields], Memi[nvfields], nvalues)
+
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add two blanks.
+ op = op + gstrcpy (" ", outbuf[op], maxch - op + 1)
+
+ do num_var = 1, nvalues {
+ index = Memi[nvfields+num_var-1]
+ call li_format_fieldr (values[index], Memc[field], SZ_LINE,
+ vformats[sz_fmt,index], nsdigits[index], 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+ if (num_var == nvalues) {
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ } else {
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+ }
+ }
+
+ outbuf[op] = EOS
+
+ call sfree (sp)
+end
+
+
+
+
+# LT_GET_NUM -- The field entry is converted from character to real or double
+# in preparation for the transformation. The number of significant
+# digits is counted and returned as an argument; the number of chars in
+# the number is returned as the function value.
+
+int procedure li_get_numd (linebuf, fval, nsdig)
+
+char linebuf[ARB] #I the input line buffer
+double fval #O the output floating point value
+int nsdig #O the number of significant digits
+
+char ch
+int nchar, ip
+int ctod(), stridx()
+
+begin
+ ip = 1
+ nsdig = 0
+ nchar = ctod (linebuf, ip, fval)
+ if (nchar == 0 || fval == INDEFD)
+ return (nchar)
+
+ # Skip leading white space.
+ ip = 1
+ repeat {
+ ch = linebuf[ip]
+ if (! IS_WHITE(ch))
+ break
+ ip = ip + 1
+ }
+
+ # Count signifigant digits
+ for (; ! IS_WHITE(ch) && ch != '\n' && ch != EOS; ch=linebuf[ip]) {
+ if (stridx (ch, "eEdD") > 0)
+ break
+ if (IS_DIGIT (ch))
+ nsdig = nsdig + 1
+ ip = ip + 1
+ }
+
+ return (nchar)
+end
+
+
+# LI_PACK_LINE -- Fields are packed into the outbuf buffer. Transformed
+# fields are converted to strings; other fields are copied from
+# the input line to output buffer.
+
+procedure li_pack_lined (inbuf, outbuf, maxch, field_pos, nfields,
+ xfield, yfield, xt, yt, xformat, yformat, nsdig_x, nsdig_y,
+ min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int xfield #I the field number of the x coordinate column
+int yfield #I the field number of the y coordinate column
+double xt #I the transformed x coordinate
+double yt #I the transformed y coordinate
+char xformat[ARB] #I the output format for the x column
+char yformat[ARB] #I the output format for the y column
+int nsdig_x #I the number of significant digits in x
+int nsdig_y #I the number of significant digits in y
+int min_sigdigits #I the minimum number of significant digits
+
+int num_field, width, op
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ do num_field = 1, nfields {
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ if (num_field == xfield) {
+ call li_format_fieldd (xt, Memc[field], maxch, xformat,
+ nsdig_x, width, min_sigdigits)
+ } else if (num_field == yfield) {
+ call li_format_fieldd (yt, Memc[field], maxch, yformat,
+ nsdig_y, width, min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_APPEND_LINE -- Fields are appened to the input buffer. Transformed
+# fields are converted to strings and added to the end of the input buffer.
+
+procedure li_append_lined (inbuf, outbuf, maxch, xt, yt, xformat, yformat,
+ nsdig_x, nsdig_y, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+double xt #I the transformed x coordinate
+double yt #I the transformed y coordinate
+char xformat[ARB] #I the output format for the x column
+char yformat[ARB] #I the output format for the y column
+int nsdig_x #I the number of significant digits in x
+int nsdig_y #I the number of significant digits in y
+int min_sigdigits #I the minimum number of significant digits
+
+int ip, op
+pointer sp, field
+int gstrcpy()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add two blanks.
+ op = op + gstrcpy (" ", outbuf[op], maxch - op + 1)
+
+ # Format and add the the two extra fields with a blank between.
+ call li_format_fieldd (xt, Memc[field], SZ_LINE, xformat,
+ nsdig_x, 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+ call li_format_fieldd (yt, Memc[field], SZ_LINE, yformat,
+ nsdig_y, 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+
+ # Add a newline.
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ outbuf[op] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_FORMAT_FIELD -- A transformed coordinate is written into a string
+# buffer. The output field is of (at least) the same width and significance
+# as the input list entry.
+
+procedure li_format_fieldd (fval, wordbuf, maxch, format, nsdig, width,
+ min_sigdigits)
+
+double fval #I the input value to be formatted
+char wordbuf[maxch] #O the output formatted string
+int maxch #I the maximum length of the output string
+char format[ARB] #I the output format
+int nsdig #I the number of sig-digits in current value
+int width #I the width of the curent field
+int min_sigdigits #I the minimum number of significant digits
+
+int fdigits, fwidth
+begin
+ if (format[1] == EOS) {
+ fdigits = max (min_sigdigits, nsdig)
+ fwidth = max (width, fdigits + 1)
+ call sprintf (wordbuf, maxch, "%*.*g")
+ call pargi (fwidth)
+ call pargi (fdigits)
+ call pargd (fval)
+ } else {
+ call sprintf (wordbuf, maxch, format)
+ call pargd (fval)
+ }
+end
+
+# LI_NPACK_LINE -- Fields are packed into the outbuf buffer. Transformed
+# fields are converted to strings; other fields are copied from
+# the input line to output buffer.
+
+procedure li_npack_lined (inbuf, outbuf, maxch, field_pos, nfields,
+ vfields, values, nsdigits, nvalues, vformats, sz_fmt, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int vfields[ARB] #I the fields to be formatted
+double values[ARB] #I the field values to be formatted
+int nsdigits[ARB] #I the number of field significant digits
+int nvalues #I the number of fields to be formatted
+char vformats[sz_fmt,ARB] #I the field formats
+int sz_fmt #I the size of the format string
+int min_sigdigits #I the minimum number of significant digits
+
+bool found
+int op, num_field, num_var, width
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ do num_field = 1, nfields {
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ found = false
+ do num_var = 1, nvalues {
+ if (num_field == vfields[num_var]) {
+ found = true
+ break
+ }
+ }
+
+ if (found) {
+ call li_format_fieldd (values[num_var], Memc[field],
+ maxch, vformats[1,num_var], nsdigits[num_var], width,
+ min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+# LI_NAPPEND_LINE -- Fields are appened to the input buffer. Transformed
+# fields are converted to strings and added to the end of the input buffer.
+
+procedure li_nappend_lined (inbuf, outbuf, maxch, field_pos, nfields,
+ vfields, values, nsdigits, nvalues, vformats, sz_fmt, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int vfields[ARB] #I the fields to be formatted
+double values[ARB] #I the field values to be formatted
+int nsdigits[ARB] #I the number of field significant digits
+int nvalues #I the number of fields to be formatted
+char vformats[sz_fmt,ARB] #I the field formats
+int sz_fmt #I the size of the format string
+int min_sigdigits #I the minimum number of significant digits
+
+int num_var, ip, op, index
+pointer sp, field, nvfields
+int gstrcpy()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+ call salloc (nvfields, nvalues, TY_INT)
+ do num_var = 1, nvalues
+ Memi[nvfields+num_var-1] = num_var
+ call rg_qsorti (vfields, Memi[nvfields], Memi[nvfields], nvalues)
+
+ # Copy the input buffer into the output buffer minus the newline.
+ op = 1
+ for (ip = 1; ip <= maxch; ip = ip + 1) {
+ if (inbuf[ip] == '\n' || inbuf[ip] == EOS)
+ break
+ outbuf[op] = inbuf[ip]
+ op = op + 1
+ }
+
+ # Add two blanks.
+ op = op + gstrcpy (" ", outbuf[op], maxch - op + 1)
+
+ do num_var = 1, nvalues {
+ index = Memi[nvfields+num_var-1]
+ call li_format_fieldd (values[index], Memc[field], SZ_LINE,
+ vformats[sz_fmt,index], nsdigits[index], 0, min_sigdigits)
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch - op + 1)
+ if (num_var == nvalues) {
+ if (op <= maxch) {
+ outbuf[op] = '\n'
+ op = op + 1
+ }
+ } else {
+ if (op <= maxch) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+ }
+ }
+
+ outbuf[op] = EOS
+
+ call sfree (sp)
+end
+
+
+
diff --git a/pkg/images/lib/mkpkg b/pkg/images/lib/mkpkg
new file mode 100644
index 00000000..dd55f750
--- /dev/null
+++ b/pkg/images/lib/mkpkg
@@ -0,0 +1,72 @@
+# Library for the IMAGES package containing routines used by tasks in
+# different subpackages
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+generic:
+ $set GEN = "$$generic -k"
+
+ $ifolder (geofit.x,geofit.gx)
+ $(GEN) geofit.gx -o geofit.x $endif
+ $ifolder (geogmap.x,geogmap.gx)
+ $(GEN) geogmap.gx -o geogmap.x $endif
+ $ifolder (geograph.x,geograph.gx)
+ $(GEN) geograph.gx -o geograph.x $endif
+
+ $ifolder (liststr.x, liststr.gx)
+ $(GEN) liststr.gx -o liststr.x $endif
+ ;
+
+libpkg.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+
+ # used by imcopy, lineclean tasks
+ imcopy.x <imhdr.h>
+
+ # used by xregister, psfmatch tasks
+ rgbckgrd.x <mach.h> <math.h> <math/gsurfit.h>
+ rgcontour.x <error.h> <mach.h> <gset.h> <config.h> <xwhen.h> \
+ <fset.h>
+ rgfft.x
+
+ # used by geoxytran and other list reading and writing tasks
+ liststr.x <ctype.h>
+
+ # geomap, ccmap, and other tasks?, should be fmtio routine which is
+ # the reverse of strdic
+ rgwrdstr.x
+
+ # used by ccmap, ccsetwcs, cctran, skyxymatch, skyctran, imcctran
+ # ccxymatch tasks
+ # put in xtools at some point ?
+ #skywcs.x <imhdr.h> <imio.h> <math.h> <mwset.h> \
+ # "skywcs.h" "skywcsdef.h"
+
+ # used by ccmap, ccxymatch
+ rgccwcs.x <imhdr.h> <math.h> <mwset.h> <pkg/skywcs.h>
+
+ # used by xyxymatch, ccxymatch, imtile tasks
+ rgsort.x
+
+ # used by skyxymatch and imctran tasks, include in skywcs.x ?
+ rglltran.x <math.h> <pkg/skywcs.h>
+
+ # used by skyxymatch, wcsxymatch, imcctran tasks
+ rgxymatch.x <mwset.h>
+
+ # used by ccxymatch, xyxymatch tasks
+ rgmerge.x <mach.h> <plset.h> "xyxymatch.h"
+ rgtransform.x <math.h> <math/gsurfit.h> "xyxymatch.h"
+ xymatch.x "xyxymatch.h"
+
+ # used by ccmap, geomap tasks
+ geofit.x <mach.h> <math.h> <math/gsurfit.h> "geomap.h"
+ geogmap.x <error.h> <math.h> <math/gsurfit.h> "geomap.h" \
+ "geogmap.h"
+ geograph.x <mach.h> <math.h> <gset.h> <math/gsurfit.h> \
+ <pkg/gtools.h> "geomap.h" "geogmap.h"
+ geoset.x "geomap.h"
+ ;
diff --git a/pkg/images/lib/rgbckgrd.x b/pkg/images/lib/rgbckgrd.x
new file mode 100644
index 00000000..feef4fd4
--- /dev/null
+++ b/pkg/images/lib/rgbckgrd.x
@@ -0,0 +1,661 @@
+include <mach.h>
+include <math.h>
+include <math/gsurfit.h>
+
+
+# RG_BORDER -- Fetch the border pixels from a 2D subraster.
+
+int procedure rg_border (buf, nx, ny, pnx, pny, ptr)
+
+real buf[nx,ARB] #I the input data subraster
+int nx, ny #I the dimensions of the input subraster
+int pnx, pny #I the size of the data region
+pointer ptr #I the pointer to the output buffer
+
+int j, nborder, wxborder, wyborder, index
+
+begin
+ # Compute the size of the array
+ nborder = nx * ny - pnx * pny
+ if (nborder <= 0) {
+ ptr = NULL
+ return (0)
+ } else if (nborder >= nx * ny) {
+ call malloc (ptr, nx * ny, TY_REAL)
+ call amovr (buf, Memr[ptr], nx * ny)
+ return (nx * ny)
+ } else
+ call malloc (ptr, nborder, TY_REAL)
+
+ # Fill the array.
+ wxborder = (nx - pnx) / 2
+ wyborder = (ny - pny) / 2
+ index = ptr
+ do j = 1, wyborder {
+ call amovr (buf[1,j], Memr[index], nx)
+ index = index + nx
+ }
+ do j = wyborder + 1, ny - wyborder {
+ call amovr (buf[1,j], Memr[index], wxborder)
+ index = index + wxborder
+ call amovr (buf[nx-wxborder+1,j], Memr[index], wxborder)
+ index = index + wxborder
+ }
+ do j = ny - wyborder + 1, ny {
+ call amovr (buf[1,j], Memr[index], nx)
+ index = index + nx
+ }
+
+ return (nborder)
+end
+
+
+# RG_SUBTRACT -- Subtract a plane from the data.
+
+procedure rg_subtract (data, nx, ny, zero, xslope, yslope)
+
+real data[nx,ARB] #I/O the input/output data array
+int nx, ny #I the dimensions of the input data array
+real zero #I the input zero point
+real xslope #I the input x slope
+real yslope #I the input y slope
+
+int i, j
+real ydelta
+
+begin
+ do j = 1, ny {
+ ydelta = yslope * j
+ do i = 1, nx
+ data[i,j] = data[i,j] - zero - xslope * i - ydelta
+ }
+end
+
+
+# RG_APODIZE -- Apply a cosine bell to the data. The operation can be
+# performed in place
+
+procedure rg_apodize (data, nx, ny, apodize, forward)
+
+real data[nx,ARB] #I the input data array
+int nx, ny #I the size of the input array
+real apodize #I the percentage of the end to apodize
+int forward #I YES for forward, NO for reverse
+
+int i, j, nxpercent, nypercent, iindex, jindex
+real f
+
+begin
+ nxpercent = apodize * nx
+ nypercent = apodize * ny
+
+ if (forward == YES) {
+ do j = 1, ny {
+ do i = 1, nxpercent {
+ iindex = nx - i + 1
+ f = (1.0 - cos (PI * real (i-1) / real(nxpercent))) / 2.0
+ data[i,j] = f * data[i,j]
+ data[iindex,j] = f * data[iindex,j]
+ }
+ }
+ do i = 1, nx {
+ do j = 1, nypercent {
+ jindex = ny - j + 1
+ f = (1.0 - cos (PI * real (j-1) / real(nypercent))) / 2.0
+ data[i,j] = f * data[i,j]
+ data[i,jindex] = f * data[i,jindex]
+ }
+ }
+ } else {
+ do j = 1, ny {
+ do i = 1, nxpercent {
+ iindex = nx - i + 1
+ f = (1.0 - cos (PI * real (i-1) / real(nxpercent))) / 2.0
+ if (f < 1.0e-3)
+ f = 1.0e-3
+ data[i,j] = data[i,j] / f
+ data[iindex,j] = data[iindex,j] / f
+ }
+ }
+ do i = 1, nx {
+ do j = 1, nypercent {
+ jindex = ny - j + 1
+ f = (1.0 - cos (PI * real (j-1) / real(nypercent))) / 2.0
+ if (f < 1.0e-3)
+ f = 1.0e-3
+ data[i,j] = data[i,j] / f
+ data[i,jindex] = data[i,jindex] / f
+ }
+ }
+ }
+end
+
+
+# RG_ZNSUM -- Compute the mean and number of good points in the array with
+# one optional level of rejections.
+
+int procedure rg_znsum (data, npts, mean, lcut, hcut)
+
+real data[ARB] #I the input data array
+int npts #I the number of data points
+real mean #O the mean of the data
+real lcut, hcut #I the good data limits
+
+int i, ngpts
+real dif, sigma, sum, sumsq, lo, hi
+real asumr(), assqr()
+
+begin
+ # Get the mean.
+ if (npts == 0) {
+ mean = INDEFR
+ return (0)
+ } else if (npts == 1) {
+ mean = data[1]
+ return (1)
+ } else {
+ sum = asumr (data, npts)
+ mean = sum / npts
+ }
+
+ # Quit if the rejection flags are not set.
+ if (IS_INDEFR(lcut) && IS_INDEFR(hcut))
+ return (npts)
+
+ # Compute sigma
+ sumsq = assqr (data, npts)
+ sigma = sumsq / (npts - 1) - mean * sum / (npts - 1)
+ if (sigma <= 0.0)
+ sigma = 0.0
+ else
+ sigma = sqrt (sigma)
+ if (sigma <= 0.0)
+ return (npts)
+
+ # Do the k-sigma rejection.
+ if (IS_INDEF(lcut))
+ lo = -MAX_REAL
+ else
+ lo = -lcut * sigma
+ if (IS_INDEFR(hcut))
+ hi = MAX_REAL
+ else
+ hi = hcut * sigma
+
+ # Reject points.
+ ngpts = npts
+ do i = 1, npts {
+ dif = (data[i] - mean)
+ if (dif >= lo && dif <= hi)
+ next
+ ngpts = ngpts - 1
+ sum = sum - data[i]
+ sumsq = sumsq - data[i] ** 2
+ }
+
+ # Get the final mean.
+ if (ngpts == 0) {
+ mean = INDEFR
+ return (0)
+ } else if (ngpts == 1) {
+ mean = sum
+ return (1)
+ } else
+ mean = sum / ngpts
+
+ return (ngpts)
+end
+
+
+# RG_ZNMEDIAN -- Compute the median and number of good points in the array
+# with one level of rejection.
+
+int procedure rg_znmedian (data, npts, median, lcut, hcut)
+
+real data[ARB] #I the input data array
+int npts #I the number of data points
+real median #O the median of the data
+real lcut, hcut #I the good data limits
+
+int i, ngpts, lindex, hindex
+pointer sp, sdata
+real mean, sigma, dif, lo, hi
+real amedr()
+
+begin
+ if (IS_INDEFR (lcut) && IS_INDEFR(hcut)) {
+ median = amedr (data, npts)
+ return (npts)
+ }
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (sdata, npts, TY_REAL)
+ call asrtr (data, Memr[sdata], npts)
+ if (mod (npts, 2) == 0)
+ median = (Memr[sdata+(1+npts)/2-1] + Memr[sdata+(1+npts)/2]) / 2.0
+ else
+ median = Memr[sdata+(1+npts)/2-1]
+
+ # Compute the sigma.
+ call aavgr (Memr[sdata], npts, mean, sigma)
+ if (sigma <= 0.0) {
+ call sfree (sp)
+ return (npts)
+ }
+
+ # Do rejection.
+ ngpts = npts
+ if (IS_INDEFR(lo))
+ lo = -MAX_REAL
+ else
+ lo = -lcut * sigma
+ if (IS_INDEFR(hi))
+ hi = MAX_REAL
+ else
+ hi = hcut * sigma
+
+ do i = 1, npts {
+ lindex = i
+ dif = Memr[sdata+i-1] - median
+ if (dif >= lo)
+ break
+ }
+ do i = npts, 1, -1 {
+ hindex = i
+ dif = Memr[sdata+i-1] - median
+ if (dif <= hi)
+ break
+ }
+
+ ngpts = hindex - lindex + 1
+ if (ngpts <= 0)
+ median = INDEFR
+ else if (mod (ngpts, 2) == 0)
+ median = (Memr[sdata+lindex-1+(ngpts+1)/2-1] + Memr[sdata+lindex-1+
+ (ngpts+1)/2]) / 2.0
+ else
+ median = Memr[sdata+lindex-1+(ngpts+1)/2-1]
+
+ call sfree (sp)
+
+ return (ngpts)
+end
+
+
+# RG_SLOPE -- Subtract a slope from the data to be psf matched.
+
+int procedure rg_slope (gs, data, npts, nx, ny, wxborder, wyborder, loreject,
+ hireject)
+
+pointer gs #I the pointer to surfit structure
+real data[ARB] #I/O the input/output data
+int npts #I the number of points
+int nx, ny #I dimensions of the original data
+int wxborder, wyborder #I the x and y width of the border
+real loreject, hireject #I the rejection criteria
+
+int i, stat, ier
+pointer sp, x, y, w, zfit
+real lcut, hcut, sigma
+int rg_reject(), rg_breject()
+real rg_sigma(), rg_bsigma()
+
+begin
+ # Initialize.
+ call smark (sp)
+ call salloc (x, nx, TY_REAL)
+ call salloc (y, nx, TY_REAL)
+ call salloc (w, nx, TY_REAL)
+ call salloc (zfit, nx, TY_REAL)
+ do i = 1, nx
+ Memr[x+i-1] = i
+ call amovkr (1.0, Memr[w], nx)
+
+ # Accumulate the fit.
+ call gszero (gs)
+ if (npts >= nx * ny)
+ call rg_gsaccum (gs, Memr[x], Memr[y], Memr[w], data, nx, ny)
+ else
+ call rg_gsborder (gs, Memr[x], Memr[y], Memr[w], data, nx, ny,
+ wxborder, wyborder)
+
+ # Solve the surface.
+ call gssolve (gs, ier)
+ if (ier == NO_DEG_FREEDOM) {
+ call sfree (sp)
+ return (ERR)
+ }
+
+ # Perform the rejection.
+ if (! IS_INDEFR(loreject) || ! IS_INDEFR(hireject)) {
+ if (npts >= nx * ny)
+ sigma = rg_sigma (gs, Memr[x], Memr[y], Memr[w], Memr[zfit],
+ data, nx, ny)
+ else
+ sigma = rg_bsigma (gs, Memr[x], Memr[y], Memr[w], Memr[zfit],
+ data, nx, ny, wxborder, wyborder)
+ if (sigma <= 0.0) {
+ call sfree (sp)
+ return (OK)
+ }
+ if (! IS_INDEFR(loreject))
+ lcut = -loreject * sigma
+ else
+ lcut = -MAX_REAL
+ if (! IS_INDEFR(hireject))
+ hcut = hireject * sigma
+ else
+ hcut = MAX_REAL
+ if (npts >= nx * ny)
+ stat = rg_reject (gs, Memr[x], Memr[y], Memr[w], Memr[zfit],
+ data, nx, ny, lcut, hcut)
+ else
+ stat = rg_breject (gs, Memr[x], Memr[y], Memr[w], Memr[zfit],
+ data, nx, ny, wxborder, wyborder, lcut, hcut)
+ }
+
+ call sfree (sp)
+ return (stat)
+end
+
+
+# RG_GSACCUM -- Accumulate the points into the fits assuming the data is in the
+# form of a two-dimensional subraster.
+
+procedure rg_gsaccum (gs, x, y, w, data, nx, ny)
+
+pointer gs #I pointer to the surface fitting structure
+real x[ARB] #I the input x array
+real y[ARB] #I the input y array
+real w[ARB] #I the input weight array
+real data[ARB] #I the input data array
+int nx, ny #I the size of the input data array
+
+int i, index
+
+begin
+ index = 1
+ do i = 1, ny {
+ call amovkr (real (i), y, nx)
+ call gsacpts (gs, x, y, data[index], w, nx, WTS_USER)
+ index = index + nx
+ }
+end
+
+
+# RG_GSBORDER -- Procedure to accumulate the points into the fit assuming
+# that a border has been extracted
+
+procedure rg_gsborder (gs, x, y, w, data, nx, ny, wxborder, wyborder)
+
+pointer gs #I pointer to the surface fitting structure
+real x[ARB] #I the input x array
+real y[ARB] #I the input y array
+real w[ARB] #I the input weight array
+real data[ARB] #I the input data array
+int nx, ny #I the dimensions of the input data
+int wxborder, wyborder #I the width of the border
+
+int i, index, nborder
+
+begin
+ nborder = nx * ny - (nx - wxborder) * (ny - wyborder)
+
+ index = 1
+ do i = 1, wyborder {
+ call amovkr (real (i), y, nx)
+ call gsacpts (gs, x, y, data[index], w, nx, WTS_USER)
+ index = index + nx
+ }
+
+ index = nx * wyborder + 1
+ do i = wyborder + 1, ny - wyborder {
+ call amovkr (real (i), y, nx)
+ call gsacpts (gs, x, y, data[index], w, wxborder, WTS_USER)
+ index = index + wxborder
+ call gsacpts (gs, x[1+nx-wxborder], y[1+nx-wxborder],
+ data[index], w[1+nx-wxborder], wxborder, WTS_USER)
+ index = index + wxborder
+ }
+
+ index = 1 + nborder - nx * wyborder
+ do i = ny - wyborder + 1, ny {
+ call amovkr (real (i), y, nx)
+ call gsacpts (gs, x, y, data[index], w, nx, WTS_USER)
+ index = index + nx
+ }
+
+end
+
+
+# RG_SIGMA -- Compute sigma assuming the data is in the form of a
+# two-dimensional subraster.
+
+real procedure rg_sigma (gs, x, y, w, zfit, data, nx, ny)
+
+pointer gs #I the pointer to the surface fitting structure
+real x[ARB] #I the input x array
+real y[ARB] #I the input y array
+real w[ARB] #I the input w array
+real zfit[ARB] #O the output fitted data
+real data[ARB] #I/O the input/output data array
+int nx, ny #I the dimensions of the output data
+
+int i, j, index, npts
+real sum
+
+begin
+ npts = 0
+ index = 1
+ sum = 0.0
+
+ do i = 1, ny {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, nx)
+ call asubr (data[index], zfit, zfit, nx)
+ do j = 1, nx {
+ if (w[j] > 0.0) {
+ sum = sum + zfit[j] ** 2
+ npts = npts + 1
+ }
+ }
+ index = index + nx
+ }
+
+ return (sqrt (sum / npts))
+end
+
+
+# RG_BSIGMA -- Procedure to compute sigma assuming a border has been
+# extracted from a subraster.
+
+real procedure rg_bsigma (gs, x, y, w, zfit, data, nx, ny, wxborder, wyborder)
+
+pointer gs #I the pointer to the surface fitting structure
+real x[ARB] #I the input x array
+real y[ARB] #I the output y array
+real w[ARB] #I the output weight array
+real zfit[ARB] #O the fitted z array
+real data[ARB] #I/O the input/output data array
+int nx, ny #I the dimensions of original subraster
+int wxborder, wyborder #I the width of the border
+
+int i, j, npts, nborder, index
+real sum
+
+begin
+ nborder = nx * ny - (nx - wxborder) * (ny - wyborder)
+ npts = 0
+ index = 1
+ sum = 0.0
+
+ do i = 1, wyborder {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, nx)
+ call asubr (data[index], zfit, zfit, nx)
+ do j = 1, nx {
+ if (w[j] > 0.0) {
+ npts = npts + 1
+ sum = sum + zfit[j] ** 2
+ }
+ }
+ index = index + nx
+ }
+
+ index = nx * wyborder + 1
+ do i = wyborder + 1, ny - wyborder {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, wxborder)
+ call asubr (data[index], zfit, zfit, wxborder)
+ do j = 1, wxborder {
+ if (w[j] > 0.0) {
+ npts = npts + 1
+ sum = sum + zfit[j] ** 2
+ }
+ }
+ index = index + wxborder
+ call gsvector (gs, x[1+nx-wxborder], y[1+nx-wxborder], zfit,
+ wxborder)
+ call asubr (data[index], zfit, zfit, wxborder)
+ do j = 1, wxborder {
+ if (w[j] > 0.0) {
+ npts = npts + 1
+ sum = sum + zfit[j] ** 2
+ }
+ }
+ index = index + wxborder
+ }
+
+ index = 1 + nborder - nx * wyborder
+ do i = ny - wyborder + 1, ny {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, nx)
+ call asubr (data[index], zfit, zfit, nx)
+ do j = 1, nx {
+ if (w[j] > 0.0) {
+ npts = npts + 1
+ sum = sum + zfit[j] ** 2
+ }
+ }
+ index = index + nx
+ }
+
+ return (sqrt (sum / npts))
+end
+
+
+# RG_REJECT -- Reject points from the fit assuming the data is in the form of a
+# two-dimensional subraster.
+
+int procedure rg_reject (gs, x, y, w, zfit, data, nx, ny, lcut, hcut)
+
+pointer gs #I the pointer to the surface fitting structure
+real x[ARB] #I the input x array
+real y[ARB] #I the input y array
+real w[ARB] #I the input w array
+real zfit[ARB] #O the fitted data
+real data[ARB] #I/O the input/output data array
+int nx, ny #I the dimensions of the data
+real lcut, hcut #I the lo and high side rejection criteria
+
+int i, j, index, ier
+
+begin
+ index = 1
+
+ do i = 1, ny {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, nx)
+ call asubr (data[index], zfit, zfit, nx)
+ do j = 1, nx {
+ if (zfit[j] < lcut || zfit[j] > hcut)
+ call gsrej (gs, x[j], y[j], data[index+j-1], w[j], WTS_USER)
+ }
+ index = index + nx
+ }
+
+ call gssolve (gs, ier)
+ if (ier == NO_DEG_FREEDOM)
+ return (ERR)
+ else
+ return (OK)
+end
+
+
+# RG_BREJECT -- Reject deviant points from the fits assuming a border has
+# been extracted from the subraster.
+
+int procedure rg_breject (gs, x, y, w, zfit, data, nx, ny, wxborder,
+ wyborder, lcut, hcut)
+
+pointer gs #I the pointer to the surface fitting structure
+real x[ARB] #I the input x array
+real y[ARB] #I the input y array
+real w[ARB] #I the input weight array
+real zfit[ARB] #O the fitted z array
+real data[ARB] #I/O the input/output data array
+int nx, ny #I the dimensions of the original subraster
+int wxborder, wyborder #I the width of the border
+real lcut, hcut #I the low and high rejection criteria
+
+int i, j, nborder, index, ier
+
+begin
+ nborder = nx * ny - (nx - wxborder) * (ny - wyborder)
+ index = 1
+
+ do i = 1, wyborder {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, nx)
+ call asubr (data[index], zfit, zfit, nx)
+ do j = 1, nx {
+ if (zfit[j] < lcut || zfit[j] > hcut)
+ call gsrej (gs, x[j], y[j], data[index+j-1], w[j],
+ WTS_USER)
+ }
+ index = index + nx
+ }
+
+ index = nx * wyborder + 1
+ do i = wyborder + 1, ny - wyborder {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, wxborder)
+ call asubr (data[index], zfit, zfit, wxborder)
+ do j = 1, wxborder {
+ if (zfit[j] < lcut || zfit[j] > hcut)
+ call gsrej (gs, x[j], y[j], data[index+j-1], w[j],
+ WTS_USER)
+ }
+ index = index + wxborder
+ call gsvector (gs, x[1+nx-wxborder], y[1+nx-wxborder], zfit,
+ wxborder)
+ call asubr (data[index], zfit, zfit, wxborder)
+ do j = 1, wxborder {
+ if (zfit[j] < lcut || zfit[j] > hcut)
+ call gsrej (gs, x[j], y[j], data[index+j-1], w[j],
+ WTS_USER)
+ }
+ index = index + wxborder
+ }
+
+ index = 1 + nborder - nx * wyborder
+ do i = ny - wyborder + 1, ny {
+ call amovkr (real (i), y, nx)
+ call gsvector (gs, x, y, zfit, nx)
+ call asubr (data[index], zfit, zfit, nx)
+ do j = 1, nx {
+ if (zfit[j] < lcut || zfit[j] > hcut)
+ call gsrej (gs, x[j], y[j], data[index+j-1], w[j],
+ WTS_USER)
+ }
+ index = index + nx
+ }
+
+ call gssolve (gs, ier)
+ if (ier == NO_DEG_FREEDOM)
+ return (ERR)
+ else
+ return (OK)
+end
+
diff --git a/pkg/images/lib/rgccwcs.x b/pkg/images/lib/rgccwcs.x
new file mode 100644
index 00000000..519c2cb3
--- /dev/null
+++ b/pkg/images/lib/rgccwcs.x
@@ -0,0 +1,221 @@
+include <imhdr.h>
+include <math.h>
+include <mwset.h>
+include <pkg/skywcs.h>
+
+
+# RG_CELTOSTD - Convert the longitude / latitude coordinates to standard
+# coordinates given the position of the reference point and the form of
+# the projection.
+
+procedure rg_celtostd (projection, lngref, latref, xi, eta, npts, reflng,
+ reflat, lngunits, latunits)
+
+char projection[ARB] #I the projection type
+double lngref[ARB] #I the input ra / longitude coordinates
+double latref[ARB] #I the input dec / latitude coordinates
+double xi[ARB] #O the output ra / longitude std coordinates
+double eta[ARB] #O the output dec / latitude std coordinates
+int npts #I the number of data points
+double reflng #I the ra / longitude reference point
+double reflat #I the dec / latitude reference point
+int lngunits #I the ra / longitude units
+int latunits #I the dec / latitude units
+
+
+double tlngref, tlatref
+int i
+pointer mw, ct
+pointer rg_projwcs(), mw_sctran()
+errchk mw_sctran()
+
+begin
+ # Initialize the projection transformation.
+ mw = rg_projwcs (projection, reflng, reflat, lngunits, latunits)
+
+ # Compile the transformation.
+ ct = mw_sctran (mw, "world", "logical", 03B)
+
+ # Evaluate the standard coordinates.
+ do i = 1, npts {
+
+ switch (lngunits) {
+ case SKY_DEGREES:
+ tlngref = lngref[i]
+ case SKY_RADIANS:
+ tlngref = RADTODEG(lngref[i])
+ case SKY_HOURS:
+ tlngref = 15.0d0 * lngref[i]
+ default:
+ tlngref = lngref[i]
+ }
+
+ switch (latunits) {
+ case SKY_DEGREES:
+ tlatref = latref[i]
+ case SKY_RADIANS:
+ tlatref = RADTODEG(latref[i])
+ case SKY_HOURS:
+ tlatref = 15.0d0 * latref[i]
+ default:
+ tlatref = latref[i]
+ }
+
+ call mw_c2trand (ct, tlngref, tlatref, xi[i], eta[i])
+ }
+
+ call mw_close (mw)
+
+end
+
+
+# RG_STDTOCEL - Convert the longitude / latitude coordinates to standard
+# coordinates given the position of the reference point and the form of
+# the projection.
+
+procedure rg_stdtocel (projection, xi, eta, lngfit, latfit, npts, reflng,
+ reflat, lngunits, latunits)
+
+char projection[ARB] #I the sky projection geometry
+double xi[ARB] #I the output ra / longitude std coordinates
+double eta[ARB] #I the output dec / latitude std coordinates
+double lngfit[ARB] #O the input ra / longitude coordinates
+double latfit[ARB] #O the input dec / latitude coordinates
+int npts #I the number of data points
+double reflng #I the ra / longitude reference point
+double reflat #I the dec / latitude reference point
+int lngunits #I the ra / longitude units
+int latunits #I the dec / latitude units
+
+double tlngref, tlatref
+int i
+pointer mw, ct
+pointer rg_projwcs(), mw_sctran()
+errchk mw_sctran()
+
+begin
+ # Initialize the projection transformation.
+ mw = rg_projwcs (projection, reflng, reflat, lngunits, latunits)
+
+ # Compile the transformation.
+ ct = mw_sctran (mw, "logical", "world", 03B)
+
+ # Evaluate the standard coordinates.
+ do i = 1, npts {
+
+ call mw_c2trand (ct, xi[i], eta[i], tlngref, tlatref)
+
+ switch (lngunits) {
+ case SKY_DEGREES:
+ lngfit[i] = tlngref
+ case SKY_RADIANS:
+ lngfit[i] = DEGTORAD(tlngref)
+ case SKY_HOURS:
+ lngfit[i] = tlngref / 15.0d0
+ default:
+ lngfit[i] = tlngref
+ }
+
+ switch (latunits) {
+ case SKY_DEGREES:
+ latfit[i] = tlatref
+ case SKY_RADIANS:
+ latfit[i] = DEGTORAD(tlatref)
+ case SKY_HOURS:
+ latfit[i] = tlatref / 15.0d0
+ default:
+ latfit[i] = tlatref
+ }
+
+ }
+
+ call mw_close (mw)
+end
+
+
+# RG_PROJWCS -- Set up a projection wcs given the projection type, the
+# coordinates of the reference point, and the reference point units.
+
+pointer procedure rg_projwcs (projection, reflng, reflat, lngunits, latunits)
+
+char projection[ARB] #I the projection type
+double reflng #I the ra / longitude reference point
+double reflat #I the dec / latitude reference point
+int lngunits #I the ra / longitude units
+int latunits #I the dec / latitude units
+
+int ndim
+pointer sp, projstr, projpars, wpars, ltm, ltv, cd, r, w, mw, axes
+pointer mw_open()
+
+begin
+ ndim = 2
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (projstr, SZ_FNAME, TY_CHAR)
+ call salloc (projpars, SZ_LINE, TY_CHAR)
+ call salloc (wpars, SZ_LINE, TY_CHAR)
+ call salloc (ltm, ndim * ndim, TY_DOUBLE)
+ call salloc (ltv, ndim, TY_DOUBLE)
+ call salloc (cd, ndim * ndim, TY_DOUBLE)
+ call salloc (r, ndim, TY_DOUBLE)
+ call salloc (w, ndim, TY_DOUBLE)
+ call salloc (axes, IM_MAXDIM, TY_INT)
+
+ # Open the wcs.
+ mw = mw_open (NULL, ndim)
+
+ # Set the axes and projection type.
+ Memi[axes] = 1
+ Memi[axes+1] = 2
+ if (projection[1] == EOS)
+ call mw_swtype (mw, Memi[axes], ndim, "linear", "")
+ else {
+ call sscan (projection)
+ call gargwrd (Memc[projstr], SZ_FNAME)
+ call gargstr (Memc[projpars], SZ_LINE)
+ call sprintf (Memc[wpars], SZ_LINE,
+ "axis 1: axtype = ra %s axis 2: axtype = dec %s")
+ call pargstr (Memc[projpars])
+ call pargstr (Memc[projpars])
+ call mw_swtype (mw, Memi[axes], ndim, Memc[projstr], Memc[wpars])
+ }
+
+
+ # Set the lterm.
+ call mw_mkidmd (Memd[ltm], ndim)
+ call aclrd (Memd[ltv], ndim)
+ call mw_sltermd (mw, Memd[ltm], Memd[ltv], ndim)
+
+ # Set the wterm.
+ call mw_mkidmd (Memd[cd], ndim)
+ call aclrd (Memd[r], ndim)
+ switch (lngunits) {
+ case SKY_DEGREES:
+ Memd[w] = reflng
+ case SKY_RADIANS:
+ Memd[w] = RADTODEG(reflng)
+ case SKY_HOURS:
+ Memd[w] = 15.0d0 * reflng
+ default:
+ Memd[w] = reflng
+ }
+ switch (latunits) {
+ case SKY_DEGREES:
+ Memd[w+1] = reflat
+ case SKY_RADIANS:
+ Memd[w+1] = RADTODEG(reflat)
+ case SKY_HOURS:
+ Memd[w+1] = 15.0d0 * reflat
+ default:
+ Memd[w+1] = reflat
+ }
+ call mw_swtermd (mw, Memd[r], Memd[w], Memd[cd], ndim)
+
+
+ call sfree (sp)
+
+ return (mw)
+end
+
diff --git a/pkg/images/lib/rgcontour.x b/pkg/images/lib/rgcontour.x
new file mode 100644
index 00000000..62ed1934
--- /dev/null
+++ b/pkg/images/lib/rgcontour.x
@@ -0,0 +1,475 @@
+include <error.h>
+include <mach.h>
+include <gset.h>
+include <config.h>
+include <xwhen.h>
+include <fset.h>
+
+
+define DUMMY 6
+define XCEN 0.5
+define YCEN 0.52
+define EDGE1 0.1
+define EDGE2 0.93
+define SZ_LABEL 10
+define SZ_FMT 20
+
+
+# RG_CONTOUR -- Produce a contour plot of a subrasteer.
+
+procedure rg_contour (gp, htitle, btitle, data, ncols, nlines)
+
+pointer gp #I pointer to graphics stream
+char htitle[ARB] #I the plot header title
+char btitle[ARB] #I the plot trailer title
+real data[ncols,ARB] #I input data
+int ncols, nlines #I dimensions of data
+
+bool perimeter
+int tcojmp[LEN_JUMPBUF]
+int epa, status, wkid
+int nset, ncontours, dashpat, nhi, old_onint
+int isizel, isizem, isizep, nrep, ncrt, ilab, nulbll, ioffd
+int ioffm, isolid, nla, nlm, first
+pointer sp, label, temp
+real interval, floor, ceiling, dmin, dmax, zero, finc, ybot
+real vx1, vx2, vy1, vy2, wx1, wx2, wy1, wy2
+real first_col, last_col, first_row, last_row
+real xlt, ybt, side, ext, hold[5]
+
+extern rg_onint()
+
+common /tcocom/ tcojmp
+common /conflg/ first
+common /noaolb/ hold
+common /conre4/ isizel, isizem , isizep, nrep, ncrt, ilab, nulbll, ioffd,
+ ext, ioffm, isolid, nla, nlm, xlt, ybt, side
+
+begin
+ # Return if the pointer is NULL.
+ if (gp == NULL)
+ return
+ call greactivate (gp, 0)
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (label, SZ_LINE, TY_CHAR)
+ call salloc (temp, ncols * nlines, TY_REAL)
+
+ # First of all, intialize conrec's block data before altering any
+ # parameters in common.
+ first = 1
+ call conbd
+
+ # Set the local variables.
+ zero = 0.0
+ floor = INDEFR
+ ceiling = INDEFR
+ nhi = -1
+ dashpat = 528
+
+ # Suppress the contour labelling by setting the common
+ # parameter "ilab" to zero.
+ ilab = 0
+
+ # User can specify either the number of contours or the contour
+ # interval, or let conrec pick a nice number. Set ncontours to 0
+ # and encode the FINC param expected by conrec.
+
+ ncontours = 0
+ if (ncontours <= 0) {
+ interval = 0.0
+ if (interval <= 0.0)
+ finc = 0
+ else
+ finc = interval
+ } else
+ finc = - abs (ncontours)
+
+ # Define the data limits.
+
+ first_col = 1.0
+ last_col = real (ncols)
+ first_row = 1.0
+ last_row = real (nlines)
+
+ # The floor and ceiling are in absolute units, but the zero shift is
+ # applied first, so correct the numbers for the zero shift. Zero is
+ # a special number for the floor and ceiling, so do not change value
+ # if set to zero.
+
+ call alimr (data, ncols * nlines, dmin, dmax)
+ if (IS_INDEFR(floor))
+ floor = dmin
+ floor = floor - zero
+ if (IS_INDEFR (ceiling))
+ ceiling = dmax
+ ceiling = ceiling - zero
+
+ # Make a copy of the image and contour this.
+ call amovr (data, Memr[temp], nlines * ncols)
+
+ # Apply the zero point shift.
+ if (abs (zero) > EPSILON)
+ call asubkr (Memr[temp], zero, Memr[temp], ncols * nlines)
+
+ # Open device and make contour plot.
+ call gopks (STDERR)
+ wkid = 1
+ call gclear (gp)
+ call gopwk (wkid, DUMMY, gp)
+ call gacwk (wkid)
+
+ # Always draw the perimeter.
+ perimeter = true
+
+ # The viewport can be set by the user. If not, the viewport is
+ # assumed to be centered on the device. In either case, the
+ # viewport to window mapping is established in rg_map_viewport
+ # and conrec's automatic mapping scheme is avoided by setting nset=1.
+ vx1 = 0.0
+ vx2 = 0.0
+ vy1 = 0.0
+ vy2 = 0.0
+ call rg_map_viewport (gp, ncols, nlines, vx1, vx2, vy1, vy2, false,
+ perimeter)
+ nset = 1
+
+ # Supress conrec's plot label generation.
+ ioffm = 1
+
+ # Install interrupt exception handler.
+ call zlocpr (rg_onint, epa)
+ call xwhen (X_INT, epa, old_onint)
+
+ # Make the contour plot. If an interrupt occurs ZSVJMP is reeentered
+ # with an error status.
+ call zsvjmp (tcojmp, status)
+ if (status == OK) {
+ call conrec (Memr[temp], ncols, ncols, nlines, floor, ceiling,
+ finc, nset, nhi, -dashpat)
+ } else {
+ call gcancel (gp)
+ call fseti (STDOUT, F_CANCEL, OK)
+ }
+
+ # Now find window and output text string title. The window is
+ # set to the full image coordinates for labelling.
+ if (perimeter) {
+
+ call gswind (gp, first_col, last_col, first_row, last_row)
+ call rg_perimeter (gp)
+
+ call ggview (gp, wx1, wx2, wy1, wy2)
+ call gseti (gp, G_WCS, 0)
+ ybot = min (wy2 + .06, 0.99)
+ call gtext (gp, (wx1 + wx2) / 2.0, ybot, htitle,
+ "h=c;v=t;f=b;s=.7")
+
+ # Add system id banner to plot
+ call gseti (gp, G_CLIP, NO)
+ ybot = max (wy1 - 0.08, 0.01)
+ call gtext (gp, (wx1 + wx2) / 2.0, ybot, btitle, "h=c;v=b;s=.5")
+
+ call sprintf (Memc[label], SZ_LINE,
+ "contoured from %g to %g, interval = %g")
+ call pargr (hold(1))
+ call pargr (hold(2))
+ call pargr (hold(3))
+ ybot = max (wy1 - 0.06, .03)
+ call gtext (gp, (wx1 + wx2) / 2.0, ybot, Memc[label],
+ "h=c;v=b;s=.6")
+ }
+
+ call gswind (gp, first_col, last_col, first_row, last_row)
+ call gamove (gp, last_col, last_row)
+ call gflush (gp)
+
+ call gdawk (wkid)
+ call gclks ()
+
+ call sfree (sp)
+end
+
+
+# RG_ONINT -- Interrupt handler for the task contour. Branches back to ZSVJMP
+# in the main routine to permit shutdown without an error message.
+
+procedure rg_onint (vex, next_handler)
+
+int vex #I virtual exception
+int next_handler #U not used
+
+int tcojmp[LEN_JUMPBUF]
+common /tcocom/ tcojmp
+
+begin
+ call xer_reset()
+ call zdojmp (tcojmp, vex)
+end
+
+
+# RG_PERIMETER -- draw and annotate the axes drawn around the perimeter
+# of the image pixels. The viewport and window have been set by
+# the calling procedure. Plotting is done in window coordinates.
+# This procedure is called by both crtpict and the ncar plotting routines
+# contour and hafton.
+
+procedure rg_perimeter (gp)
+
+pointer gp #I graphics descriptor
+
+real xs, xe, ys, ye
+int i, first_col, last_col, first_tick, last_tick, bias
+int nchar, dummy, first_row, last_row, cnt_step, cnt_label
+pointer sp, label, fmt1, fmt2, fmt3, fmt4
+real dist, kk, col, row, dx, dy, sz_char, cw, xsz, label_pos
+real xdist, ydist, xspace, yspace, k[3]
+data k/1.0,2.0,3.0/
+
+bool ggetb()
+int itoc()
+real ggetr()
+errchk ggwind, gseti, gctran, gline, gtext, itoc
+
+begin
+ call smark (sp)
+ call salloc (label, SZ_LABEL, TY_CHAR)
+ call salloc (fmt1, SZ_FMT, TY_CHAR)
+ call salloc (fmt2, SZ_FMT, TY_CHAR)
+ call salloc (fmt3, SZ_FMT, TY_CHAR)
+ call salloc (fmt4, SZ_FMT, TY_CHAR)
+
+ # First, get window coordinates and turn off clipping
+ call ggwind (gp, xs, xe, ys, ye)
+ call gseti (gp, G_CLIP, NO)
+
+ # A readable character width seems to be about 1.mm. A readable
+ # perimeter seperation seems to be about .80mm. If the physical
+ # size of the output device is contained in the graphcap file, the
+ # NDC sizes of these measurements can be determined. If not,
+ # the separation between perimeter axes equals one quarter character
+ # width or one quarter percent of frame, which ever is larger, and
+ # the character size is set to 0.40.
+
+ cw = max (ggetr (gp, "cw"), 0.01)
+ if (ggetb (gp, "xs")) {
+ xsz = ggetr (gp, "xs")
+ dist = .80 / (xsz * 1000.)
+ sz_char = dist / cw
+ } else {
+ # Get character width and calculate perimeter separation.
+ dist = cw * 0.25
+ sz_char = 0.40
+ }
+
+ # Convert distance to user coordinates
+ call ggscale (gp, xs, ys, dx, dy)
+ xdist = dist * dx
+ ydist = dist * dy
+
+ # Generate four possible format strings for gtext
+ call sprintf (Memc[fmt1], SZ_LINE, "h=c;v=t;s=%.2f")
+ call pargr (sz_char)
+ call sprintf (Memc[fmt2], SZ_LINE, "h=c;v=b;s=%.2f")
+ call pargr (sz_char)
+ call sprintf (Memc[fmt3], SZ_LINE, "h=r;v=c;s=%.2f")
+ call pargr (sz_char)
+ call sprintf (Memc[fmt4], SZ_LINE, "h=l;v=c;s=%.2f")
+ call pargr (sz_char)
+
+ # Draw inner and outer perimeter
+ kk = k[1]
+ do i = 1, 2 {
+ xspace = kk * xdist
+ yspace = kk * ydist
+ call gline (gp, xs - xspace, ys - yspace, xe + xspace, ys - yspace)
+ call gline (gp, xe + xspace, ys - yspace, xe + xspace, ye + yspace)
+ call gline (gp, xe + xspace, ye + yspace, xs - xspace, ye + yspace)
+ call gline (gp, xs - xspace, ye + yspace, xs - xspace, ys - yspace)
+ kk = k[2]
+ }
+
+ # Now draw x axis tick marks, along both the bottom and top of
+ # the picture. First find the endpoint integer pixels.
+
+ first_col = int (xs)
+ last_col = int (xe)
+
+ # Determine increments of ticks and tick labels for x axis
+ cnt_step = 1
+ cnt_label = 10
+ if (last_col - first_col > 256) {
+ cnt_step = 10
+ cnt_label = 100
+ } else if (last_col - first_col < 26) {
+ cnt_step = 1
+ cnt_label = 1
+ }
+
+ first_tick = first_col
+ bias = mod (first_tick, cnt_step)
+ last_tick = last_col + bias
+
+ do i = first_tick, last_tick, cnt_step {
+ col = real (i - bias)
+ call gline (gp, col, ys - k[1] * ydist, col, ys - k[2] * ydist)
+ call gline (gp, col, ye + k[1] * ydist, col, ye + k[2] * ydist)
+
+ if (mod ((i - bias), cnt_label) == 0) {
+ # Label tick mark; calculate number of characters needed
+ nchar = 3
+ if (int (col) == 0)
+ nchar = 1
+ if (int (col) >= 1000)
+ nchar = 4
+
+ dummy = itoc (int(col), Memc[label], nchar)
+
+ # Position label slightly below outer perimeter. Seperation
+ # is twenty percent of a character width, in WCS.
+ label_pos = ys - (k[2] * ydist + (cw * 0.20 * dy))
+ call gtext (gp, col, label_pos, Memc[label], Memc[fmt1])
+
+ # Position label slightly above outer perimeter
+ label_pos = ye + (k[2] * ydist + (cw * 0.20 * dy))
+ call gtext (gp, col, label_pos, Memc[label], Memc[fmt2])
+ }
+ }
+
+ # Label the y axis tick marks along the left and right sides of the
+ # picture. First find the integer pixel endpoints.
+
+ first_row = int (ys)
+ last_row = int (ye)
+
+ # Determine increments of ticks and tick labels for y axis
+ cnt_step = 1
+ cnt_label = 10
+ if (last_row - first_row > 256) {
+ cnt_step = 10
+ cnt_label = 100
+ } else if (last_row - first_row < 26) {
+ cnt_step = 1
+ cnt_label = 1
+ }
+
+ first_tick = first_row
+ bias = mod (first_tick, cnt_step)
+ last_tick = last_row + bias
+
+ do i = first_tick, last_tick, cnt_step {
+ row = real (i - bias)
+ call gline (gp, xs - k[1] * xdist, row, xs - k[2] * xdist, row)
+ call gline (gp, xe + k[1] * xdist, row, xe + k[2] * xdist, row)
+
+ if (mod ((i - bias), cnt_label) == 0) {
+ # Label tick mark; calculate number of characters needed
+ nchar = 3
+ if (int (row) == 0)
+ nchar = 1
+ else if (int (row) >= 1000)
+ nchar = 4
+
+ dummy = itoc (int(row), Memc[label], nchar)
+
+ # Position label slightly to the left of outer perimeter.
+ # Separation twenty percent of a character width, in WCS.
+ label_pos = xs - (k[2] * xdist + (cw * 0.20 * dx))
+ call gtext (gp, label_pos, row, Memc[label], Memc[fmt3])
+
+ # Position label slightly to the right of outer perimeter
+ label_pos = xe + (k[2] * xdist + (cw * 0.20 * dx))
+ call gtext (gp, label_pos, row, Memc[label], Memc[fmt4])
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# RG_MAP_VIEWPORT -- set device viewport for contour and hafton plots. If not
+# specified by user, a default viewport centered on the device is used.
+
+procedure rg_map_viewport (gp, ncols, nlines, ux1, ux2, uy1, uy2, fill,
+ perimeter)
+
+pointer gp #I graphics stream descriptor
+int ncols #I number of image cols
+int nlines #I number of image lines
+real ux1, ux2, uy1, uy2 #I/O NDC coordinates of requested viewort
+bool fill #I fill viewport
+bool perimeter #I draw the perimeter
+
+real ncolsr, nlinesr, ratio, aspect_ratio, xcen, ycen
+real x1, x2, y1, y2, ext, xdis, ydis
+bool fp_equalr()
+real ggetr()
+data ext /0.0625/
+
+begin
+ ncolsr = real (ncols)
+ nlinesr = real (nlines)
+
+ if (fp_equalr (ux1, 0.0) && fp_equalr (ux2, 0.0) &&
+ fp_equalr (uy1, 0.0) && fp_equalr (uy2, 0.0)) {
+
+ if (fill && ! perimeter) {
+ x1 = 0.0
+ x2 = 1.0
+ y1 = 0.0
+ y2 = 1.0
+ xcen = 0.5
+ ycen = 0.5
+ } else {
+ x1 = EDGE1
+ x2 = EDGE2
+ y1 = EDGE1
+ y2 = EDGE2
+ xcen = XCEN
+ ycen = YCEN
+ }
+
+ # Calculate optimum viewport, as in NCAR's conrec, hafton
+ if (! fill) {
+ ratio = min (ncolsr, nlinesr) / max (ncolsr, nlinesr)
+ if (ratio >= ext) {
+ if (ncols > nlines)
+ y2 = (y2 - y1) * nlinesr / ncolsr + y1
+ else
+ x2 = (x2 - x1) * ncolsr / nlinesr + x1
+ }
+ }
+
+ xdis = x2 - x1
+ ydis = y2 - y1
+
+ # So far, the viewport has been calculated so that equal numbers of
+ # image pixels map to equal distances in NDC space, regardless of
+ # the aspect ratio of the device. If the parameter "fill" has been
+ # set to no, the user wants to compensate for a non-unity aspect
+ # ratio and make equal numbers of image pixels map to into the same
+ # physical distance on the device, not the same NDC distance.
+
+ if (! fill) {
+ aspect_ratio = ggetr (gp, "ar")
+ if (fp_equalr (aspect_ratio, 0.0))
+ aspect_ratio = 1.0
+ if (aspect_ratio < 1.0)
+ xdis = xdis * aspect_ratio
+ else if (aspect_ratio > 1.0)
+ ydis = ydis / aspect_ratio
+ }
+
+ ux1 = xcen - (xdis / 2.0)
+ ux2 = xcen + (xdis / 2.0)
+ uy1 = ycen - (ydis / 2.0)
+ uy2 = ycen + (ydis / 2.0)
+ }
+
+ # Set window and viewport for WCS 1
+ call gseti (gp, G_WCS, 1)
+ call gsview (gp, ux1, ux2, uy1, uy2)
+ call gswind (gp, 1.0, ncolsr, 1.0, nlinesr)
+ call set (ux1, ux2, uy1, uy2, 1.0, ncolsr, 1.0, nlinesr, 1)
+end
diff --git a/pkg/images/lib/rgfft.x b/pkg/images/lib/rgfft.x
new file mode 100644
index 00000000..b986a9d7
--- /dev/null
+++ b/pkg/images/lib/rgfft.x
@@ -0,0 +1,269 @@
+
+# RG_SZFFT -- Compute the size of the required FFT given the dimension of the
+# image the window size and the fact that the FFT must be a power of 2.
+
+int procedure rg_szfft (npts, window)
+
+int npts #I the number of points in the data
+int window #I the width of the valid cross correlation
+
+int nfft, pow2
+
+begin
+ nfft = npts + window / 2
+
+ pow2 = 2
+ while (pow2 < nfft)
+ pow2 = pow2 * 2
+
+ return (pow2)
+end
+
+
+# RG_RLOAD -- Procedure to load a real array into the real part of a complex
+# array.
+
+procedure rg_rload (buf, ncols, nlines, fft, nxfft, nyfft)
+
+real buf[ARB] #I the input data buffer
+int ncols, nlines #I the size of the input buffer
+real fft[ARB] #O the out array to be fft'd
+int nxfft, nyfft #I the dimensions of the fft
+
+int i, dindex, findex
+
+begin
+ # Load the reference and image data.
+ dindex = 1
+ findex = 1
+ do i = 1, nlines {
+ call rg_rweave (buf[dindex], fft[findex], ncols)
+ dindex = dindex + ncols
+ findex = findex + 2 * nxfft
+ }
+end
+
+
+# RG_ILOAD -- Procedure to load a real array into the complex part of a complex
+# array.
+
+procedure rg_iload (buf, ncols, nlines, fft, nxfft, nyfft)
+
+real buf[ARB] #I the input data buffer
+int ncols, nlines #I the size of the input buffer
+real fft[ARB] #O the output array to be fft'd
+int nxfft, nyfft #I the dimensions of the fft
+
+int i, dindex, findex
+
+begin
+ # Load the reference and image data.
+ dindex = 1
+ findex = 1
+ do i = 1, nlines {
+ call rg_iweave (buf[dindex], fft[findex], ncols)
+ dindex = dindex + ncols
+ findex = findex + 2 * nxfft
+ }
+end
+
+
+# RG_RWEAVE -- Weave a real array into the real part of a complex array.
+# The output array must be twice as long as the input array.
+
+procedure rg_rweave (a, b, npts)
+
+real a[ARB] #I input array
+real b[ARB] #O output array
+int npts #I the number of data points
+
+int i
+
+begin
+ do i = 1, npts
+ b[2*i-1] = a[i]
+end
+
+
+# RG_IWEAVE -- Weave a real array into the complex part of a complex array.
+# The output array must be twice as long as the input array.
+
+procedure rg_iweave (a, b, npts)
+
+real a[ARB] #I the input array
+real b[ARB] #O the output array
+int npts #I the number of data points
+
+int i
+
+begin
+ do i = 1, npts
+ b[2*i] = a[i]
+end
+
+
+# RG_FOURN -- Replaces datas by its n-dimensional discreter Fourier transform,
+# if isign is input as 1. NN is an integer array of length ndim containing
+# the lengths of each dimension (number of complex values), which must all
+# be powers of 2. Data is a real array of length twice the product of these
+# lengths, in which the data are stored as in a multidimensional complex
+# Fortran array. If isign is input as -1, data is replaced by its inverse
+# transform times the product of the lengths of all dimensions.
+
+procedure rg_fourn (data, nn, ndim, isign)
+
+real data[ARB] #I/O input data and output fft
+int nn[ndim] #I array of dimension lengths
+int ndim #I number of dimensions
+int isign #I forward or inverse transform
+
+int idim, i1, i2, i3, ip1, ip2, ip3, ifp1, ifp2, i2rev, i3rev, k1, k2
+int ntot, nprev, n, nrem, pibit
+double wr, wi, wpr, wpi, wtemp, theta
+real tempr, tempi
+
+begin
+ ntot = 1
+ do idim = 1, ndim
+ ntot = ntot * nn[idim]
+
+ nprev = 1
+ do idim = 1, ndim {
+
+ n = nn[idim]
+ nrem = ntot / (n * nprev)
+ ip1 = 2 * nprev
+ ip2 = ip1 * n
+ ip3 = ip2 * nrem
+ i2rev = 1
+
+ do i2 = 1, ip2, ip1 {
+
+ if (i2 < i2rev) {
+ do i1 = i2, i2 + ip1 - 2, 2 {
+ do i3 = i1, ip3, ip2 {
+ i3rev = i2rev + i3 - i2
+ tempr = data [i3]
+ tempi = data[i3+1]
+ data[i3] = data[i3rev]
+ data[i3+1] = data[i3rev+1]
+ data[i3rev] = tempr
+ data[i3rev+1] = tempi
+ }
+ }
+ }
+
+ pibit = ip2 / 2
+ while ((pibit >= ip1) && (i2rev > pibit)) {
+ i2rev = i2rev - pibit
+ pibit = pibit / 2
+ }
+
+ i2rev = i2rev + pibit
+ }
+
+ ifp1 = ip1
+ while (ifp1 < ip2) {
+
+ ifp2 = 2 * ifp1
+ theta = isign * 6.28318530717959d0 / (ifp2 / ip1)
+ wpr = - 2.0d0 * dsin (0.5d0 * theta) ** 2
+ wpi = dsin (theta)
+ wr = 1.0d0
+ wi = 0.0d0
+
+ do i3 = 1, ifp1, ip1 {
+ do i1 = i3, i3 + ip1 - 2, 2 {
+ do i2 = i1, ip3, ifp2 {
+ k1 = i2
+ k2 = k1 + ifp1
+ tempr = sngl (wr) * data[k2] - sngl (wi) *
+ data[k2+1]
+ tempi = sngl (wr) * data[k2+1] + sngl (wi) *
+ data[k2]
+ data[k2] = data[k1] - tempr
+ data[k2+1] = data[k1+1] - tempi
+ data[k1] = data[k1] + tempr
+ data[k1+1] = data[k1+1] + tempi
+ }
+ }
+ wtemp = wr
+ wr = wr * wpr - wi * wpi + wr
+ wi = wi * wpr + wtemp * wpi + wi
+ }
+
+ ifp1 = ifp2
+ }
+ nprev = n * nprev
+ }
+end
+
+
+# RG_FSHIFT -- Center the array after doing the FFT.
+
+procedure rg_fshift (fft1, fft2, nx, ny)
+
+real fft1[nx,ARB] #I input fft array
+real fft2[nx,ARB] #O output fft array
+int nx, ny #I fft array dimensions
+
+int i, j
+real fac
+
+begin
+ fac = 1.0
+ do j = 1, ny {
+ do i = 1, nx, 2 {
+ fft2[i,j] = fac * fft1[i,j]
+ fft2[i+1,j] = fac * fft1[i+1,j]
+ fac = -fac
+ }
+ fac = -fac
+ }
+end
+
+
+# RG_MOVEXR -- Extract the portion of the FFT for which the computed lags
+# are valid. The dimensions of the the FFT are a power of two
+# and the 0 frequency is in the position nxfft / 2 + 1, nyfft / 2 + 1.
+
+procedure rg_movexr (fft, nxfft, nyfft, xcor, xwindow, ywindow)
+
+real fft[ARB] #I the input fft
+int nxfft, nyfft #I the dimensions of the input fft
+real xcor[ARB] #O the output cross-correlation function
+int xwindow, ywindow #I the cross-correlation function window
+
+int j, ix, iy, findex, xindex
+
+begin
+ # Compute the starting index of the extraction array.
+ ix = 1 + nxfft - 2 * (xwindow / 2)
+ iy = 1 + nyfft / 2 - ywindow / 2
+
+ # Copy the real part of the Fourier transform into the
+ # cross-correlation array.
+ findex = ix + 2 * nxfft * (iy - 1)
+ xindex = 1
+ do j = 1, ywindow {
+ call rg_extract (fft[findex], xcor[xindex], xwindow)
+ findex = findex + 2 * nxfft
+ xindex = xindex + xwindow
+ }
+end
+
+
+# RG_EXTRACT -- Extract the real part of a complex array.
+
+procedure rg_extract (a, b, npts)
+
+real a[ARB] #I the input array
+real b[ARB] #O the output array
+int npts #I the number of data points
+
+int i
+
+begin
+ do i = 1, npts
+ b[i] = a[2*i-1]
+end
diff --git a/pkg/images/lib/rglltran.x b/pkg/images/lib/rglltran.x
new file mode 100644
index 00000000..890cec0b
--- /dev/null
+++ b/pkg/images/lib/rglltran.x
@@ -0,0 +1,42 @@
+include <math.h>
+include <pkg/skywcs.h>
+
+# RG_LLTRANSFORM -- Transform the reference image world coordinates to the
+# input image world coordinate system.
+
+procedure rg_lltransform (cooref, cooin, rxlng, rylat, ixlng, iylat, npts)
+
+pointer cooref #I pointer to the reference image coordinate structure
+pointer cooin #I pointer to the input image coordinate structure
+double rxlng[ARB] #I the x refererence image world coordinates (degrees)
+double rylat[ARB] #I the y refererence image world coordinates (degrees)
+double ixlng[ARB] #O the x refererence image world coordinates (degrees)
+double iylat[ARB] #O the y refererence image world coordinates (degrees)
+int npts #I the number of coordinates
+
+int i
+double ilng, ilat, olng, olat
+int sk_stati()
+
+begin
+ if (sk_stati (cooref, S_PLNGAX) < sk_stati (cooref, S_PLATAX)) {
+ do i = 1, npts {
+ ilng = DEGTORAD (rxlng[i])
+ ilat = DEGTORAD (rylat[i])
+ call sk_lltran (cooref, cooin, ilng, ilat, INDEFD,
+ INDEFD, 0.0d0, 0.0d0, olng, olat)
+ ixlng[i] = RADTODEG (olng)
+ iylat[i] = RADTODEG (olat)
+ }
+ } else {
+ do i = 1, npts {
+ ilng = DEGTORAD (rylat[i])
+ ilat = DEGTORAD (rxlng[i])
+ call sk_lltran (cooref, cooin, ilng, ilat, INDEFD,
+ INDEFD, 0.0d0, 0.0d0, olng, olat)
+ ixlng[i] = RADTODEG (olat)
+ iylat[i] = RADTODEG (olng)
+ }
+ }
+end
+
diff --git a/pkg/images/lib/rgmerge.x b/pkg/images/lib/rgmerge.x
new file mode 100644
index 00000000..5e218bd0
--- /dev/null
+++ b/pkg/images/lib/rgmerge.x
@@ -0,0 +1,1023 @@
+include <mach.h>
+include <plset.h>
+include "xyxymatch.h"
+
+# RG_MATCH -- Compute the intersection of two lists using a pattern matching
+# algorithm. This algorithm is based on one developed by Edward Groth
+# 1986 A.J. 91, 1244. The algorithm matches pairs of coordinates from
+# two lists based on the triangles that can be formed from triplets of
+# points in each list. The algorithm is insensitive to coordinate translation,
+# rotation, magnification, or inversion and can tolerate distortions and
+# random errors.
+
+int procedure rg_match (xref, yref, nref, xin, yin, nin, reftri, reftrirat,
+ nreftri, nrmaxtri, nrefstars, intri, intrirat, nintri, ninmaxtri,
+ nliststars, tolerance, ptolerance, ratio, nreject)
+
+real xref[ARB] #I the reference x coordinates
+real yref[ARB] #I the reference y coordinates
+int nref #I the number of reference coordinates
+real xin[ARB] #I the input x coordinates
+real yin[ARB] #I the input y coordinates
+int nin #I the number of input coordinates
+int reftri[nrmaxtri,ARB] #U list of reference triangles
+real reftrirat[nrmaxtri,ARB] #U list of reference triangle parameters
+int nreftri #U number of reference triangles
+int nrmaxtri #I maximum number of reference triangles
+int nrefstars #I the number of reference stars
+int intri[ninmaxtri,ARB] #U list of input triangles
+real intrirat[ninmaxtri,ARB] #U list of input triangle parameters
+int nintri #U number of input triangles
+int ninmaxtri #I maximum number of input triangles
+int nliststars #I the number of input stars
+real tolerance #I the reference triangles matching tolerance
+real ptolerance #I the input triangles matching tolerance
+real ratio #I the maximum ratio of triangle sides
+int nreject #I maximum number of rejection iterations
+
+int i, nmerge, nkeep, nmatch, ncheck
+pointer sp, rindex, lindex
+int rg_tmerge(), rg_treject(), rg_tvote(), rg_triangle
+
+begin
+ # Match the triangles in the input list to those in the reference list.
+ if (nreftri < nintri)
+ nmerge = rg_tmerge (reftri, reftrirat, nreftri, nrmaxtri, intri,
+ intrirat, nintri, ninmaxtri)
+ else
+ nmerge = rg_tmerge (intri, intrirat, nintri, ninmaxtri, reftri,
+ reftrirat, nreftri, nrmaxtri)
+ if (nmerge <= 0)
+ return (0)
+
+ # Perform the rejection cycle.
+ nkeep = rg_treject (reftri, reftrirat, nreftri, nrmaxtri,
+ intri, intrirat, nintri, ninmaxtri, nmerge, nreject)
+ if (nkeep <= 0)
+ return (0)
+
+ # Match the coordinates.
+ nmatch = rg_tvote (reftri, nrmaxtri, nrefstars, intri, ninmaxtri,
+ nliststars, nkeep)
+ if (nmatch <= 0)
+ return (0)
+ else if (nmatch <= 3 && nkeep < nmerge)
+ return (0)
+
+ # If all the coordinates were not matched then make another pass
+ # through the triangles matching algorithm. If the number of
+ # matches decreases as a result of this then all the matches were
+ # not true matches and declare the list unmatched.
+ if (nmatch < min (nref, nin) && nmatch > 2) {
+
+ # Find the indices of the matched points.
+ call smark (sp)
+ call salloc (rindex, nmatch, TY_INT)
+ call salloc (lindex, nmatch, TY_INT)
+ do i = 1, nmatch {
+ Memi[rindex+i-1] = reftri[i,RG_MATCH]
+ Memi[lindex+i-1] = intri[i,RG_MATCH]
+ }
+
+ # Recompute the triangles.
+ nreftri = rg_triangle (xref, yref, Memi[rindex], nmatch, reftri,
+ reftrirat, nrmaxtri, nrefstars, tolerance, ratio)
+ nintri = rg_triangle (xin, yin, Memi[lindex], nmatch, intri,
+ intrirat, ninmaxtri, nliststars, ptolerance, ratio)
+
+ # Rematch the triangles.
+ if (nreftri < nintri)
+ nmerge = rg_tmerge (reftri, reftrirat, nreftri, nrmaxtri, intri,
+ intrirat, nintri, ninmaxtri)
+ else
+ nmerge = rg_tmerge (intri, intrirat, nintri, ninmaxtri, reftri,
+ reftrirat, nreftri, nrmaxtri)
+
+ # Reperform the rejection cycle.
+ if (nmerge > 0)
+ nkeep = rg_treject (reftri, reftrirat, nreftri, nrmaxtri,
+ intri, intrirat, nintri, ninmaxtri, nmerge, nreject)
+
+ # Reperform the vote.
+ if (nkeep > 0) {
+ ncheck = rg_tvote (reftri, nrmaxtri, nrefstars, intri,
+ ninmaxtri, nliststars, nkeep)
+ if (ncheck <= 3 && nkeep < nmerge)
+ ncheck = 0
+ } else
+ ncheck = 0
+
+ if (ncheck < nmatch)
+ nmatch = 0
+ else
+ nmatch = ncheck
+
+ call sfree (sp)
+ }
+
+ return (nmatch)
+end
+
+
+# RG_TRIANGLE -- Construct all the the possible triangles from
+# an input coordinate list. The triangles are constructed in such a way
+# that the shortest side of the triangle lies between vertices 1 and 2 and the
+# longest side between vertices 1 and 3. The parameters of each triangle
+# including the log of the perimeter, the ratio of the longest to shortest
+# side, the cosine of the angle at vertex 1, the tolerances in the ratio
+# and cosine and the sense of the triangle (clockwise or anti-clockwise)
+# are also computed. Triangles with a ratio greater than maxratio are
+# rejected as are triangles with vertices closer together than tolerance.
+
+int procedure rg_triangle (xref, yref, refindex, nrefstars, reftri, tripar,
+ nmaxtri, maxnpts, tolerance, maxratio)
+
+real xref[ARB] #I x reference coordinates
+real yref[ARB] #I y reference coordinates
+int refindex[ARB] #I the reference list sort index
+int nrefstars #I number of reference stars
+int reftri[nmaxtri,ARB] #O reference triangles
+real tripar[nmaxtri,ARB] #O triangle parameters
+int nmaxtri #I maximum number of triangles
+int maxnpts #I the maximum number of points
+real tolerance #I matching tolerance
+real maxratio #I maximum ratio of triangle sides
+
+int i, j, k, nsample, npts, ntri
+real rij, rjk, rki, dx1, dy1, dx2, dy2, dx3, dy3, r1, r2sq, r2, r3sq, r3
+real ratio, cosc, cosc2, sinc2, tol2, tol
+
+begin
+ # Create the tolerance.
+ tol2 = tolerance ** 2
+ nsample = max (1, nrefstars / maxnpts)
+ npts = min (nrefstars, nsample * maxnpts)
+
+ # Construct the triangles.
+ ntri = 1
+ do i = 1, npts - 2 * nsample, nsample {
+ do j = i + nsample, npts - nsample, nsample {
+ do k = j + nsample, npts, nsample {
+
+ # Compute the lengths of the three sides of the triangle,
+ # eliminating triangles with sides that are less than
+ # tolerance.
+ rij = (xref[refindex[i]] - xref[refindex[j]]) ** 2 +
+ (yref[refindex[i]] - yref[refindex[j]]) ** 2
+ if (rij <= tol2)
+ next
+ rjk = (xref[refindex[j]] - xref[refindex[k]]) ** 2 +
+ (yref[refindex[j]] - yref[refindex[k]]) ** 2
+ if (rjk <= tol2)
+ next
+ rki = (xref[refindex[k]] - xref[refindex[i]]) ** 2 +
+ (yref[refindex[k]] - yref[refindex[i]]) ** 2
+ if (rki <= tol2)
+ next
+
+ # Order the vertices with the shortest side of the triangle
+ # between vertices 1 and 2 and the intermediate side between
+ # vertices 2 and 3.
+ reftri[ntri,RG_INDEX] = ntri
+ if (rij <= rjk) {
+ if (rki <= rij) {
+ reftri[ntri,RG_X1] = refindex[k]
+ reftri[ntri,RG_X2] = refindex[i]
+ reftri[ntri,RG_X3] = refindex[j]
+ } else if (rki >= rjk) {
+ reftri[ntri,RG_X1] = refindex[i]
+ reftri[ntri,RG_X2] = refindex[j]
+ reftri[ntri,RG_X3] = refindex[k]
+ } else {
+ reftri[ntri,RG_X1] = refindex[j]
+ reftri[ntri,RG_X2] = refindex[i]
+ reftri[ntri,RG_X3] = refindex[k]
+ }
+ } else {
+ if (rki <= rjk) {
+ reftri[ntri,RG_X1] = refindex[i]
+ reftri[ntri,RG_X2] = refindex[k]
+ reftri[ntri,RG_X3] = refindex[j]
+ } else if (rki >= rij) {
+ reftri[ntri,RG_X1] = refindex[k]
+ reftri[ntri,RG_X2] = refindex[j]
+ reftri[ntri,RG_X3] = refindex[i]
+ } else {
+ reftri[ntri,RG_X1] = refindex[j]
+ reftri[ntri,RG_X2] = refindex[k]
+ reftri[ntri,RG_X3] = refindex[i]
+ }
+ }
+
+ # Compute the lengths of the sides.
+ dx1 = xref[reftri[ntri,RG_X3]] - xref[reftri[ntri,RG_X2]]
+ dy1 = yref[reftri[ntri,RG_X3]] - yref[reftri[ntri,RG_X2]]
+ dx2 = xref[reftri[ntri,RG_X2]] - xref[reftri[ntri,RG_X1]]
+ dy2 = yref[reftri[ntri,RG_X2]] - yref[reftri[ntri,RG_X1]]
+ dx3 = xref[reftri[ntri,RG_X3]] - xref[reftri[ntri,RG_X1]]
+ dy3 = yref[reftri[ntri,RG_X3]] - yref[reftri[ntri,RG_X1]]
+
+ # Compute the ratio of the longest side of the triangle
+ # to the shortest side.
+ r1 = sqrt (dx1 ** 2 + dy1 ** 2)
+ r2sq = dx2 ** 2 + dy2 ** 2
+ r2 = sqrt (r2sq)
+ r3sq = dx3 ** 2 + dy3 ** 2
+ r3 = sqrt (r3sq)
+ if (r2 <= 0.)
+ next
+ ratio = r3 / r2
+ if (ratio > maxratio)
+ next
+
+ # Compute the cos, cos ** 2 and sin ** 2 of the angle at
+ # vertex 1.
+ cosc = (dx3 * dx2 + dy3 * dy2) / (r3 * r2)
+ cosc2 = max (0.0, min (1.0, cosc * cosc))
+ sinc2 = max (0.0, min (1.0, 1.0 - cosc2))
+
+ # Determine whether the triangles vertices are arranged
+ # clockwise of anticlockwise.
+ if ((dx2 * dy1 - dy2 * dx1) > 0.0)
+ reftri[ntri,RG_CC] = YES
+ else
+ reftri[ntri,RG_CC] = NO
+
+ # Compute the tolerances.
+ tol = (1.0 / r3sq - cosc / (r3 * r2) + 1.0 / r2sq)
+ tripar[ntri,RG_TOLR] = 2.0 * ratio ** 2 * tol2 * tol
+ tripar[ntri,RG_TOLC] = 2.0 * sinc2 * tol2 * tol + 3.0 *
+ cosc2 * tol2 ** 2 * tol * tol
+
+ # Compute the perimeter.
+ tripar[ntri,RG_LOGP] = log (r1 + r2 + r3)
+ tripar[ntri,RG_RATIO] = ratio
+ tripar[ntri,RG_COS1] = cosc
+
+ ntri = ntri + 1
+ }
+ }
+ }
+
+ ntri = ntri - 1
+
+ # Sort the triangles in increasing order of ratio.
+ call rg_qsortr (tripar[1,RG_RATIO], reftri[1,RG_INDEX],
+ reftri[1,RG_INDEX], ntri)
+
+ return (ntri)
+end
+
+
+# RG_TMERGE -- Compute the intersection of two sorted files of triangles
+# using the tolerance parameter.
+
+int procedure rg_tmerge (reftri, rtripar, nrtri, nmrtri, listri, ltripar,
+ nltri, nmltri)
+
+int reftri[nmrtri,ARB] #U list of reference triangles
+real rtripar[nmrtri,ARB] #I reference triangle parameters
+int nrtri #I number of reference triangles
+int nmrtri #I maximum number of reference triangles
+int listri[nmltri,ARB] #U list of reference triangles
+real ltripar[nmltri,ARB] #I reference triangle parameters
+int nltri #I number of reference triangles
+int nmltri #I maximum number of reference triangles
+
+int rp, blp, lp, ninter, rindex, lindex, mindex
+real rmaxtol, lmaxtol, maxtol, dr, dr2, mdr2, dcos2, mdcos2, dtolr, dtolc
+
+begin
+ # Find the maximum tolerance for each list.
+ call alimr (rtripar[1,RG_TOLR], nrtri, maxtol, rmaxtol)
+ call alimr (ltripar[1,RG_TOLR], nltri, maxtol, lmaxtol)
+ maxtol = sqrt (rmaxtol + lmaxtol)
+
+ # Define the beginning of the search range for each triangle.
+ blp = 1
+
+ # Loop over all the triangles in the reference list.
+ ninter = 0
+ for (rp = 1; rp <= nrtri; rp = rp + 1) {
+
+ # Get the index for the reference triangle.
+ rindex = reftri[rp,RG_INDEX]
+
+ # Move to the first triangle in the input list that satisfies the
+ # ratio tolerance requirement.
+ for (; blp <= nltri; blp = blp + 1) {
+ lindex = listri[blp,RG_INDEX]
+ dr = rtripar[rindex,RG_RATIO] - ltripar[lindex,RG_RATIO]
+ if (dr <= maxtol)
+ break
+ }
+
+ # If the beginning of the search range becomes greater than
+ # the length of the list then there is no match.
+ if (blp > nltri)
+ break
+
+ # If the first triangle in the list is past the tolerance
+ # limit skip to the next reference triangle
+ if (dr < -maxtol)
+ next
+
+ # Search through the appropriate range of triangles for the
+ # closest fit.
+
+ # Initialize the tolerances.
+ mindex = 0
+ mdr2 = 0.5 * MAX_REAL
+ mdcos2 = 0.5 * MAX_REAL
+
+ for (lp = blp; lp <= nltri; lp = lp + 1) {
+
+ # Quit the loop if the next triangle is out of match range.
+ lindex = listri[lp,RG_INDEX]
+ dr = rtripar[rindex,RG_RATIO] - ltripar[lindex,RG_RATIO]
+ if (dr < -maxtol)
+ break
+
+ # Compute the tolerances for the two triangles.
+ dr2 = dr * dr
+ dcos2 = (rtripar[rindex,RG_COS1] - ltripar[lindex,RG_COS1]) ** 2
+ dtolr = rtripar[rindex,RG_TOLR] + ltripar[lindex,RG_TOLR]
+ dtolc = rtripar[rindex,RG_TOLC] + ltripar[lindex,RG_TOLC]
+
+ # Find the best of all possible matches.
+ if (dr2 <= dtolr && dcos2 <= dtolc) {
+ if ((dr2 + dcos2) < (mdr2 + mdcos2)) {
+ mindex = lindex
+ mdr2 = dr2
+ mdcos2 = dcos2
+ }
+ }
+
+ }
+
+ # Add the match to the list.
+ if (mindex > 0) {
+ ninter = ninter + 1
+ reftri[ninter,RG_MATCH] = rindex
+ listri[ninter,RG_MATCH] = mindex
+ }
+ }
+
+ return (ninter)
+end
+
+
+# RG_TREJECT -- Remove false matches from the list of matched triangles.
+
+int procedure rg_treject (reftri, rtripar, nrtri, nmrtri, listri, ltripar,
+ nltri, nmltri, nmatch, maxiter)
+
+int reftri[nmrtri,ARB] #U list of reference triangles
+real rtripar[nmrtri,ARB] #I reference triangle parameters
+int nrtri #I number of reference triangles
+int nmrtri #I maximum number of reference triangles
+int listri[nmltri,ARB] #U list of reference triangles
+real ltripar[nmltri,ARB] #I reference triangle parameters
+int nltri #I number of reference triangles
+int nmltri #I maximum number of reference triangles
+int nmatch #I initial number of matches
+int maxiter #I maximum number of rejection iterations
+
+double dif, mode, sum, sumsq
+int i, nrej, nplus, nminus, ntrue, nfalse, npts, ncount, niter, rindex
+int lindex
+pointer sp, adif
+real sigma, factor, locut, hicut
+double rg_moded()
+
+begin
+ call smark (sp)
+ call salloc (adif, nmatch, TY_DOUBLE)
+
+ # Accumulate the number of same sense and number of opposite sense
+ # matches as well as the log perimeter statistics.
+ sum = 0.0d0
+ sumsq = 0.0d0
+ nplus = 0
+ do i = 1, nmatch {
+ rindex = reftri[i,RG_MATCH]
+ lindex = listri[i,RG_MATCH]
+ dif = (rtripar[rindex,RG_LOGP] - ltripar[lindex,RG_LOGP])
+ Memd[adif+i-1] = dif
+ sum = sum + dif
+ sumsq = sumsq + dif * dif
+ if (reftri[rindex,RG_CC] == listri[lindex,RG_CC])
+ nplus = nplus + 1
+ }
+ nminus = nmatch - nplus
+
+ # Compute the mean, mode, and sigma of the logP distribution,
+ ntrue = abs (nplus - nminus)
+ nfalse = nplus + nminus - ntrue
+ #mean = sum / nmatch
+ if (nmatch <= 1)
+ sigma = 0.0
+ else
+ sigma = (sumsq - (sum / nmatch) * sum) / (nmatch - 1)
+ if (sigma <= 0.0) {
+ call sfree (sp)
+ return (nmatch)
+ } else
+ sigma = sqrt (sigma)
+ call asrtd (Memd[adif], Memd[adif], nmatch)
+ #if (mod (nmatch,2) == 1)
+ #median = Memd[adif+nmatch/2]
+ #else
+ #median = (Memd[adif+nmatch/2] + Memd[adif+(nmatch-1)/2]) / 2.0d0
+ mode = rg_moded (Memd[adif], nmatch, 10, 1.0d0, 0.1d0 * sigma,
+ 0.01d0 * sigma)
+ if (nfalse > ntrue)
+ factor = 1.0
+ else if ((0.1 * ntrue) > nfalse)
+ factor = 3.0
+ else
+ factor = 2.0
+
+ # Begin the rejection cycle.
+ npts = nmatch
+ niter = 0
+ repeat {
+
+ ncount = 0
+ nrej = 0
+ locut = mode - factor * sigma
+ hicut = mode + factor * sigma
+
+ # Reject matched triangles which are too far from the mean logP.
+ do i = 1, npts {
+ rindex = reftri[i,RG_MATCH]
+ lindex = listri[i,RG_MATCH]
+ dif = rtripar[rindex,RG_LOGP] - ltripar[lindex,RG_LOGP]
+ if (dif < locut || dif > hicut) {
+ sum = sum - dif
+ sumsq = sumsq - dif * dif
+ if (reftri[rindex,RG_CC] == listri[lindex,RG_CC])
+ nplus = nplus - 1
+ else
+ nminus = nminus - 1
+ nrej = nrej + 1
+ } else {
+ Memd[adif+ncount] = dif
+ ncount = ncount + 1
+ reftri[ncount,RG_MATCH] = rindex
+ listri[ncount,RG_MATCH] = lindex
+ }
+ }
+
+ # No more points were rejected.
+ npts = ncount
+ if (nrej <= 0)
+ break
+
+ # All the points were rejected.
+ if (npts <= 0)
+ break
+
+ # The rejection iteration limit was reached.
+ niter = niter + 1
+ if (niter >= maxiter)
+ break
+
+ # Compute the new mean and sigma of the logP distribution.
+ #mean = sum / npts
+ if (npts <= 1)
+ sigma = 0.0
+ else
+ sigma = (sumsq - (sum / npts) * sum) / (npts - 1)
+ if (sigma <= 0.0)
+ break
+ sigma = sqrt (sigma)
+ call asrtd (Memd[adif], Memd[adif], npts)
+ #if (mod (npts,2) == 1)
+ #median = Memd[adif+npts/2]
+ #else
+ #median = (Memd[adif+npts/2] + Memd[adif+(npts-1)/2]) / 2.0d0
+ mode = rg_moded (Memd[adif], npts, 10, 1.0d0, 0.10d0 * sigma,
+ 0.01d0 * sigma)
+
+ # Recompute the ksigma rejection criterion based on the number of
+ # same and opposite sense matches.
+ ntrue = abs (nplus - nminus)
+ nfalse = nplus + nminus - ntrue
+ if (nfalse > ntrue)
+ factor = 1.0
+ else if ((0.1 * ntrue) > nfalse)
+ factor = 3.0
+ else
+ factor = 2.0
+ }
+
+ # One last iteration to get rid of opposite sense of matches.
+ if (npts <= 0)
+ npts = 0
+ else if (nplus > nminus) {
+ ncount = 0
+ do i = 1, npts {
+ rindex = reftri[i,RG_MATCH]
+ lindex = listri[i,RG_MATCH]
+ if (reftri[rindex,RG_CC] == listri[lindex,RG_CC]) {
+ ncount = ncount + 1
+ reftri[ncount,RG_MATCH] = rindex
+ listri[ncount,RG_MATCH] = lindex
+ }
+ }
+ npts = ncount
+ } else {
+ ncount = 0
+ do i = 1, npts {
+ rindex = reftri[i,RG_MATCH]
+ lindex = listri[i,RG_MATCH]
+ if (reftri[rindex,RG_CC] != listri[lindex,RG_CC]) {
+ ncount = ncount + 1
+ reftri[ncount,RG_MATCH] = rindex
+ listri[ncount,RG_MATCH] = lindex
+ }
+ }
+ npts = ncount
+ }
+
+ call sfree (sp)
+ return (npts)
+end
+
+
+# RG_TVOTE -- Count the number a times a particular pair of
+# coordinates is matched in the set of matched triangles. If a particular
+# pair of points occurs in many triangles it is much more likely to be
+# a true match than if it occurs in very few. Since this vote array
+# may be quite sparsely occupied, use the PLIO package to store and
+# maintain the list.
+
+int procedure rg_tvote (reftri, nmrtri, nrefstars, listri, nmltri, nliststars,
+ nmatch)
+
+int reftri[nmrtri,ARB] #U reference triangles
+int nmrtri #I maximum number of reference triangles
+int nrefstars #I number of reference stars
+int listri[nmltri,ARB] #U input list triangles
+int nmltri #I maximum number of list triangles
+int nliststars #I number of list stars
+int nmatch #I number of match triangles
+
+int i, j, rp, lp, vp, pixval, tminvote, tmaxvote, minvote, maxvote, hmaxvote
+int ninter, axes[2], laxes[2], pvp
+pointer sp, vote, vindex, pl, lmatch, rmatch
+bool pl_linenotempty()
+pointer pl_create()
+
+begin
+ # Open the pixel list.
+ axes[1] = nliststars
+ axes[2] = nrefstars
+ pl = pl_create (2, axes, 16)
+
+ # Acumulate the votes.
+ do i = 1, nmatch {
+ rp = reftri[i,RG_MATCH]
+ lp = listri[i,RG_MATCH]
+ laxes[1] = listri[lp,RG_X1]
+ laxes[2] = reftri[rp,RG_X1]
+ if (! pl_linenotempty (pl, laxes))
+ call pl_point (pl, laxes[1], laxes[2], PIX_SET + PIX_VALUE(1))
+ else {
+ call pl_glpi (pl, laxes, pixval, 16, 1, PIX_SRC)
+ pixval = pixval + 1
+ call pl_point (pl, laxes[1], laxes[2], PIX_SET +
+ PIX_VALUE(pixval))
+ }
+ laxes[1] = listri[lp,RG_X2]
+ laxes[2] = reftri[rp,RG_X2]
+ if (! pl_linenotempty (pl, laxes))
+ call pl_point (pl, laxes[1], laxes[2], PIX_SET + PIX_VALUE(1))
+ else {
+ call pl_glpi (pl, laxes, pixval, 16, 1, PIX_SRC)
+ pixval = pixval + 1
+ call pl_point (pl, laxes[1], laxes[2], PIX_SET +
+ PIX_VALUE(pixval))
+ }
+ laxes[1] = listri[lp,RG_X3]
+ laxes[2] = reftri[rp,RG_X3]
+ if (! pl_linenotempty (pl, laxes))
+ call pl_point (pl, laxes[1], laxes[2], PIX_SET + PIX_VALUE(1))
+ else {
+ call pl_glpi (pl, laxes, pixval, 16, 1, PIX_SRC)
+ pixval = pixval + 1
+ call pl_point (pl, laxes[1], laxes[2], PIX_SET +
+ PIX_VALUE(pixval))
+ }
+ }
+
+ # Allocate temporary working space.
+ call smark (sp)
+ call salloc (vote, axes[1], TY_INT)
+ call salloc (vindex, axes[1], TY_INT)
+ call salloc (lmatch, axes[1], TY_INT)
+ call salloc (rmatch, axes[2], TY_INT)
+ call amovki (NO, Memi[lmatch], axes[1])
+ call amovki (NO, Memi[rmatch], axes[2])
+
+ # Find the maximum value in the mask.
+ minvote = MAX_INT
+ maxvote = -MAX_INT
+ do i = 1, axes[2] {
+ laxes[1] = 1
+ laxes[2] = i
+ if (! pl_linenotempty (pl, laxes))
+ next
+ call pl_glpi (pl, laxes, Memi[vote], 16, axes[1], PIX_SRC)
+ call alimi (Memi[vote], axes[1], tminvote, tmaxvote)
+ minvote = min (minvote, tminvote)
+ maxvote = max (maxvote, tmaxvote)
+ }
+ if (maxvote < 0) {
+ maxvote = 0
+ hmaxvote = 0
+ } else
+ hmaxvote = maxvote / 2
+
+ # Vote on the matched pairs.
+ ninter = 0
+ if (maxvote > 0) {
+ do j = 1, axes[2] {
+
+ # Sort the vote array.
+ do i = 1, axes[1]
+ Memi[vindex+i-1] = i
+ laxes[1] = 1
+ laxes[2] = j
+ call pl_glpi (pl, laxes, Memi[vote], 16, axes[1], PIX_SRC)
+ call rg_qsorti (Memi[vote], Memi[vindex], Memi[vindex],
+ axes[1])
+
+ # Reject points which have no votes, which have only a
+ # single vote if the maximum number of votest is > 1,
+ # less or equal to half the maximum number of votes,
+ # the same number of votes as the next largest index,
+ # or which have already been matched.
+
+ vp = Memi[vindex+axes[1]-1]
+ pvp = Memi[vindex+axes[1]-2]
+ if (Memi[vote+vp-1] <= 0)
+ next
+ if (Memi[vote+vp-1] == Memi[vote+pvp-1])
+ next
+ if (Memi[vote+vp-1] <= hmaxvote)
+ next
+ if (Memi[lmatch+vp-1] == YES || Memi[rmatch+j-1] == YES)
+ next
+ if (Memi[vote+vp-1] == 1 && (maxvote > 1 || nmatch > 1))
+ next
+
+ ninter = ninter + 1
+ reftri[ninter, RG_MATCH] = j
+ listri[ninter,RG_MATCH] = vp
+ Memi[rmatch+j-1] = YES
+ Memi[lmatch+vp-1] = YES
+ }
+ } else if (maxvote > 0) {
+ }
+
+ call sfree (sp)
+ call pl_close (pl)
+
+ return (ninter)
+end
+
+
+# RG_MLINCOEFF -- Compute the coefficients of a new linear transformation
+# using the first one to three matched stars as input.
+
+int procedure rg_mlincoeff (xref, yref, xlist, ylist, reftri, nmrtri, listri,
+ nmltri, nmatch, coeff, ncoeff)
+
+real xref[ARB] #I the x reference coordinates
+real yref[ARB] #I the y reference coordinates
+real xlist[ARB] #I the x list coordinates
+real ylist[ARB] #I the y list coordinates
+int reftri[nmrtri,ARB] #I list of reference triangles
+int nmrtri #I maximum number of reference triangles
+int listri[nmltri,ARB] #I list of reference triangles
+int nmltri #I maximum number of list triangles
+int nmatch #I number of matches
+real coeff[ARB] #O the new computed coefficients
+int ncoeff #I the number of coefficients
+
+int i, rindex, lindex, stat
+pointer sp, xr, yr, xin, yin
+int rg_lincoeff()
+
+begin
+ if (nmatch <= 0)
+ return (ERR)
+
+ call smark (sp)
+ call salloc (xr, nmatch, TY_REAL)
+ call salloc (yr, nmatch, TY_REAL)
+ call salloc (xin, nmatch, TY_REAL)
+ call salloc (yin, nmatch, TY_REAL)
+
+ # Load the points to be fit.
+ do i = 1, nmatch {
+ rindex = reftri[i,RG_MATCH]
+ lindex = listri[i,RG_MATCH]
+ Memr[xr+i-1] = xref[rindex]
+ Memr[yr+i-1] = yref[rindex]
+ Memr[xin+i-1] = xlist[lindex]
+ Memr[yin+i-1] = ylist[lindex]
+ }
+
+ # Compute the new coefficients.
+ stat = rg_lincoeff (Memr[xr], Memr[yr], Memr[xin], Memr[yin],
+ nmatch, coeff, ncoeff)
+
+ call sfree (sp)
+
+ return (stat)
+end
+
+
+# RG_MWRITE -- Write out the intersection of the two matched pixel lists to the
+# output file.
+
+procedure rg_mwrite (ofd, xref, yref, rlineno, xlist, ylist, ilineno,
+ reftri, nmrtri, listri, nmltri, nmatch, xformat, yformat)
+
+int ofd #I the output file descriptor
+real xref[ARB] #I the x reference coordinates
+real yref[ARB] #I the y reference coordinates
+int rlineno[ARB] #I the reference coordinate line numbers
+real xlist[ARB] #I the x list coordinates
+real ylist[ARB] #I the y list coordinates
+int ilineno[ARB] #I the input list line numbers
+int reftri[nmrtri,ARB] #I list of reference triangles
+int nmrtri #I maximum number of reference triangles
+int listri[nmltri,ARB] #I list of reference triangles
+int nmltri #I maximum number of list triangles
+int nmatch #I number of matches
+char xformat[ARB] #I the output x column format
+char yformat[ARB] #I the output y column format
+
+int i, lindex, rindex
+pointer sp, fmtstr
+
+begin
+ call smark (sp)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+
+ # Construct the format string.
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s %s %s %%5d %%5d\n")
+ if (xformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (xformat)
+ if (yformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (yformat)
+ if (xformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (xformat)
+ if (yformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (yformat)
+
+ do i = 1, nmatch {
+ rindex = reftri[i,RG_MATCH]
+ lindex = listri[i,RG_MATCH]
+ call fprintf (ofd, Memc[fmtstr])
+ call pargr (xref[rindex])
+ call pargr (yref[rindex])
+ call pargr (xlist[lindex])
+ call pargr (ylist[lindex])
+ call pargi (rlineno[rindex])
+ call pargi (ilineno[lindex])
+ }
+
+ call sfree (sp)
+end
+
+
+# RG_LMWRITE -- Write out the intersection of the matched celestial coordinate
+# and pixel lists to the output file.
+
+procedure rg_lmwrite (ofd, lngref, latref, rlineno, xlist, ylist, ilineno,
+ reftri, nmrtri, listri, nmltri, nmatch, lngformat, latformat,
+ xformat, yformat)
+
+int ofd #I the output file descriptor
+double lngref[ARB] #I the x reference coordinates
+double latref[ARB] #I the y reference coordinates
+int rlineno[ARB] #I the reference coordinate line numbers
+real xlist[ARB] #I the x list coordinates
+real ylist[ARB] #I the y list coordinates
+int ilineno[ARB] #I the input list line numbers
+int reftri[nmrtri,ARB] #I list of reference triangles
+int nmrtri #I maximum number of reference triangles
+int listri[nmltri,ARB] #I list of reference triangles
+int nmltri #I maximum number of list triangles
+int nmatch #I number of matches
+char lngformat[ARB] #I the output longitude column format
+char latformat[ARB] #I the output latitude column format
+char xformat[ARB] #I the output x column format
+char yformat[ARB] #I the output y column format
+
+int i, lindex, rindex
+pointer sp, fmtstr
+
+begin
+ call smark (sp)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+
+ # Construct the format string.
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s %s %s %%5d %%5d\n")
+ if (lngformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (lngformat)
+ if (latformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (latformat)
+ if (xformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (xformat)
+ if (yformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (yformat)
+
+ do i = 1, nmatch {
+ rindex = reftri[i,RG_MATCH]
+ lindex = listri[i,RG_MATCH]
+ call fprintf (ofd, Memc[fmtstr])
+ call pargd (lngref[rindex])
+ call pargd (latref[rindex])
+ call pargr (xlist[lindex])
+ call pargr (ylist[lindex])
+ call pargi (rlineno[rindex])
+ call pargi (ilineno[lindex])
+ }
+
+ call sfree (sp)
+end
+
+
+# RG_FACTORIAL -- Compute the combinatorial function which is defined as
+# n! / ((n - ngroup)! * ngroup!).
+
+int procedure rg_factorial (n, ngroup)
+
+int n #I input argument
+int ngroup #I combinatorial factor
+
+int i, fac, grfac
+
+begin
+ if (n <= 0)
+ return (1)
+
+ fac = n
+ do i = n - 1, n - 3 + 1, -1
+ fac = fac * i
+
+ grfac = ngroup
+ do i = ngroup - 1, 2, -1
+ grfac = grfac * i
+
+ return (fac / grfac)
+end
+
+
+# RG_MODED -- Compute mode of an array. The mode is found by binning
+# with a bin size based on the data range over a fraction of the
+# pixels about the median and a bin step which may be smaller than the
+# bin size. If there are too few points the median is returned.
+# The input array must be sorted.
+
+double procedure rg_moded (a, npts, nmin, zrange, fzbin, fzstep)
+
+double a[npts] #I the sorted input data array
+int npts #I the number of points
+int nmin #I the minimum number of points
+double zrange #I fraction of pixels around median to use
+double fzbin #I the bin size for the mode search
+double fzstep #I the step size for the mode search
+
+int x1, x2, x3, nmax
+double zstep, zbin, y1, y2, mode
+bool fp_equald()
+
+begin
+ # If there are too few points return the median.
+ if (npts < nmin) {
+ if (mod (npts,2) == 1)
+ return (a[1+npts/2])
+ else
+ return ((a[npts/2] + a[1+npts/2]) / 2.0d0)
+ }
+
+ # Compute the data range that will be used to do the mode search.
+ # If the data has no range then the constant value will be returned.
+ x1 = max (1, int (1.0d0 + npts * (1.0d0 - zrange) / 2.0d0))
+ x3 = min (npts, int (1.0d0 + npts * (1.0d0 + zrange) / 2.0d0))
+ if (fp_equald (a[x1], a[x3]))
+ return (a[x1])
+
+
+ # Compute the bin and step size. The bin size is based on the
+ # data range over a fraction of the pixels around the median
+ # and a bin step which may be smaller than the bin size.
+
+ zstep = fzstep #* (a[x3] - a[x1])
+ zbin = fzbin #* (a[x3] - a[x1])
+
+ nmax = 0
+ x2 = x1
+ for (y1 = a[x1]; x2 < x3; y1 = y1 + zstep) {
+ for (; a[x1] < y1; x1 = x1 + 1)
+ ;
+ y2 = y1 + zbin
+ for (; (x2 < x3) && (a[x2] < y2); x2 = x2 + 1)
+ ;
+ if (x2 - x1 > nmax) {
+ nmax = x2 - x1
+ if (mod (x2+x1,2) == 0)
+ mode = a[(x2+x1)/2]
+ else
+ mode = (a[(x2+x1)/2] + a[(x2+x1)/2+1]) / 2.0d0
+ }
+ }
+
+ return (mode)
+end
+
+
+#define NMIN 10 # Minimum number of pixels for mode calculation
+#define ZRANGE 0.8d0 # Fraction of pixels about median to use
+#define ZSTEP 0.01d0 # Step size for search for mode
+#define ZBIN 0.1d0 # Bin size for mode.
+#
+## RG_MODED -- Compute mode of an array. The mode is found by binning
+## with a bin size based on the data range over a fraction of the
+## pixels about the median and a bin step which may be smaller than the
+## bin size. If there are too few points the median is returned.
+## The input array must be sorted.
+#
+#double procedure rg_moded (a, n)
+#
+#double a[n] # Data array
+#int n # Number of points
+#
+#int i, j, k, nmax
+#real z1, z2, zstep, zbin
+#double mode
+#bool fp_equald()
+#
+#begin
+# if (n < NMIN)
+# return (a[n/2])
+#
+# # Compute the mode. The array must be sorted. Consider a
+# # range of values about the median point. Use a bin size which
+# # is ZBIN of the range. Step the bin limits in ZSTEP fraction of
+# # the bin size.
+#
+# i = 1 + n * (1. - ZRANGE) / 2.0d0
+# j = 1 + n * (1. + ZRANGE) / 2.0d0
+# z1 = a[i]
+# z2 = a[j]
+# if (fp_equald (z1, z2)) {
+# mode = z1
+# return (mode)
+# }
+#
+# zstep = ZSTEP * (z2 - z1)
+# zbin = ZBIN * (z2 - z1)
+#
+# z1 = z1 - zstep
+# k = i
+# nmax = 0
+# repeat {
+# z1 = z1 + zstep
+# z2 = z1 + zbin
+# for (; i < j && a[i] < z1; i=i+1)
+# ;
+# for (; k < j && a[k] < z2; k=k+1)
+# ;
+# if (k - i > nmax) {
+# nmax = k - i
+# mode = a[(i+k)/2]
+# }
+# } until (k >= j)
+#
+# return (mode)
+#end
+#
diff --git a/pkg/images/lib/rgsort.x b/pkg/images/lib/rgsort.x
new file mode 100644
index 00000000..afaab085
--- /dev/null
+++ b/pkg/images/lib/rgsort.x
@@ -0,0 +1,162 @@
+
+define LOGPTR 20 # log2(maxpts) (1e6)
+
+# RG_QSORTR -- Vector quicksort a real array. In this version the index array
+# is sorted not the data array. The input and output index arrays may be the
+# same.
+
+procedure rg_qsortr (data, a, b, npix)
+
+real data[ARB] #I the input data array
+int a[ARB] #I the input index array
+int b[ARB] #O the output index array
+int npix #I the number of pixels
+
+int i, j, lv[LOGPTR], p, uv[LOGPTR], temp
+real pivot
+
+begin
+ # Initialize the indices for an inplace sort.
+ call amovi (a, b, npix)
+
+ p = 1
+ lv[1] = 1
+ uv[1] = npix
+ while (p > 0) {
+
+ # If only one elem in subset pop stack otherwise pivot line.
+ if (lv[p] >= uv[p])
+ p = p - 1
+ else {
+ i = lv[p] - 1
+ j = uv[p]
+ pivot = data[b[j]]
+
+ while (i < j) {
+ for (i=i+1; data[b[i]] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (data[b[j]] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ p = p + 1 # push onto stack
+ }
+ }
+end
+
+
+# RG_QSORTI -- Vector quicksort an integer array. In this version the index
+# array is actually sorted not the data array. The input and output index
+# arrays may be the same.
+
+procedure rg_qsorti (data, a, b, npix)
+
+int data[ARB] # data array
+int a[ARB] # input index array
+int b[ARB] # output index array
+int npix # number of pixels
+
+int i, j, lv[LOGPTR], p, uv[LOGPTR], temp, pivot
+
+begin
+ # Initialize the indices for an inplace sort.
+ call amovi (a, b, npix)
+
+ p = 1
+ lv[1] = 1
+ uv[1] = npix
+ while (p > 0) {
+
+ # If only one elem in subset pop stack otherwise pivot line.
+ if (lv[p] >= uv[p])
+ p = p - 1
+ else {
+ i = lv[p] - 1
+ j = uv[p]
+ pivot = data[b[j]]
+
+ while (i < j) {
+ for (i=i+1; data[b[i]] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (data[b[j]] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ temp = b[j] # interchange elements
+ b[j] = b[i]
+ b[i] = temp
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ p = p + 1 # push onto stack
+ }
+ }
+end
+
+
+# RG_SQSORT -- Sort two real arrays of data in increasing order using a
+# secondary key. The data is assumed to have been already sorted on
+# the primary key. The input and output index arrays may be the same.
+
+procedure rg_sqsort (sdata, pdata, a, b, npix)
+
+real sdata[npix] #I the secondary key
+real pdata[npix] #I the primary key
+int a[npix] #I the sorted index from the primary key
+int b[npix] #O the sorted output index
+int npix #I number of pixels
+
+int i, ndup, first
+
+begin
+ # Copy the index array.
+ call amovi (a, b, npix)
+
+ # Initialize.
+ ndup = 0
+ for (i = 2; i <= npix; i = i + 1) {
+ if (pdata[b[i]] <= pdata[b[i-1]])
+ ndup = ndup + 1
+ else if (ndup > 0) {
+ first = i - 1 - ndup
+ call rg_qsortr (sdata, b[first], b[first], ndup + 1)
+ ndup = 0
+ }
+ }
+end
diff --git a/pkg/images/lib/rgtransform.x b/pkg/images/lib/rgtransform.x
new file mode 100644
index 00000000..da9f8210
--- /dev/null
+++ b/pkg/images/lib/rgtransform.x
@@ -0,0 +1,947 @@
+include <math.h>
+include <math/gsurfit.h>
+include "xyxymatch.h"
+
+# RG_GETREFTIE -- Get the reference pixel coordinate tie points by reading
+# the image cursor or a file.
+
+int procedure rg_getreftie (fd, xreftie, yreftie, ntie, file_type, interactive)
+
+int fd #I the input file descriptor
+real xreftie[ARB] #O the output x coordinates of the tie points
+real yreftie[ARB] #O the output y coordinates of the tie points
+int ntie #I the number of tie points
+int file_type #I the input file type
+bool interactive #I the
+
+int nref, wcs, key
+pointer sp, str
+int clgcur(), fscan(), nscan()
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print the prompt string.
+ if (interactive) {
+
+ # Issue prompt.
+ if (file_type == RG_REFFILE) {
+ call printf (
+ "\nMark 1-%d reference objects on the display\n")
+ } else {
+ call printf (
+ "\nMark the same %d input objects on the display\n")
+ }
+ call pargi (ntie)
+
+ # Mark the points
+ nref = 0
+ while (clgcur ("icommands", xreftie[nref+1], yreftie[nref+1],
+ wcs, key, Memc[str], SZ_LINE) != EOF) {
+ nref = nref + 1
+ if (file_type == RG_REFFILE) {
+ call printf (" Reference coordinate %d %0.3f %0.3f\n")
+ call pargi (nref)
+ call pargr (xreftie[nref])
+ call pargr (yreftie[nref])
+ } else {
+ call printf (" Input coordinate %d %0.3f %0.3f\n")
+ call pargi (nref)
+ call pargr (xreftie[nref])
+ call pargr (yreftie[nref])
+ }
+ if (nref >= ntie)
+ break
+ }
+
+ } else {
+
+ # Issue prompt.
+ if (fd == STDIN) {
+ if (file_type == RG_REFFILE) {
+ call printf (
+ "\nEnter coordinates of 1-%d reference objects\n")
+ } else {
+ call printf (
+ "Enter coordinates of %d corresponding input objects\n")
+ }
+ call pargi (ntie)
+ }
+
+ nref = 0
+ while (fscan (fd) != EOF) {
+ call gargr (xreftie[nref+1])
+ call gargr (yreftie[nref+1])
+ if (nscan() < 2)
+ break
+ nref = nref + 1
+ if (nref >= ntie)
+ break
+ call gargr (xreftie[nref+1])
+ call gargr (yreftie[nref+1])
+ if (nscan() < 4)
+ break
+ nref = nref + 1
+ if (nref >= ntie)
+ break
+ call gargr (xreftie[nref+1])
+ call gargr (yreftie[nref+1])
+ if (nscan() < 6)
+ break
+ nref = nref + 1
+ break
+ }
+
+ }
+
+ call sfree (sp)
+
+ return (nref)
+end
+
+
+# RG_GETREFCEL -- Get the reference pixel coordinate tie points by reading
+# the image cursor or a file.
+
+int procedure rg_getrefcel (fd, xreftie, yreftie, ntie, projection,
+ reflng, reflat, lngunits, latunits, file_type)
+
+int fd #I the input file descriptor
+real xreftie[ARB] #O the output x coordinates of the tie points
+real yreftie[ARB] #O the output y coordinates of the tie points
+int ntie #I the number of tie points
+char projection[ARB] #I the sky projection geometry
+double reflng #I the ra / longitude of the reference point
+double reflat #I the dec / latitude of the reference point
+int lngunits #I the ra / longitude units
+int latunits #I the dec / latitude units
+int file_type #I the input file type
+
+int nref
+pointer sp, dxref, dyref, str
+int fscan(), nscan()
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (dxref, ntie, TY_DOUBLE)
+ call salloc (dyref, ntie, TY_DOUBLE)
+
+ # Issue prompt.
+ if (fd == STDIN) {
+ if (file_type == RG_REFFILE) {
+ call printf (
+ "\nEnter coordinates of 1-%d reference objects\n")
+ } else {
+ call printf (
+ "Enter coordinates of %d corresponding input objects\n")
+ }
+ call pargi (ntie)
+ }
+
+ # Read in the tie point.
+ nref = 0
+ while (fscan (fd) != EOF) {
+ call gargd (Memd[dxref+nref])
+ call gargd (Memd[dyref+nref])
+ if (nscan() < 2)
+ break
+ nref = nref + 1
+ if (nref >= ntie)
+ break
+ call gargd (Memd[dxref+nref])
+ call gargd (Memd[dyref+nref])
+ if (nscan() < 4)
+ break
+ nref = nref + 1
+ if (nref >= ntie)
+ break
+ call gargd (Memd[dxref+nref])
+ call gargd (Memd[dyref+nref])
+ if (nscan() < 6)
+ break
+ nref = nref + 1
+ break
+ }
+
+ # Convert to standard coordinates.
+ if (nref > 0) {
+ call rg_celtostd (projection, Memd[dxref], Memd[dyref],
+ Memd[dxref], Memd[dyref], nref, reflng, reflat, lngunits,
+ latunits)
+ call amulkd (Memd[dxref], 3600.0d0, Memd[dxref], nref)
+ call amulkd (Memd[dyref], 3600.0d0, Memd[dyref], nref)
+ call achtdr (Memd[dxref], xreftie, nref)
+ call achtdr (Memd[dyref], yreftie, nref)
+ }
+
+ call sfree (sp)
+
+ return (nref)
+end
+
+
+# RG_PLINCOEFF -- Print the computed transformation on the standard output.
+
+procedure rg_plincoeff (xlabel, ylabel, xref, yref, xlist, ylist, ntie,
+ coeff, ncoeff)
+
+char xlabel[ARB] #I the x equation label
+char ylabel[ARB] #I the x equation label
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+real xlist[ARB] #I the input x input coordinates
+real ylist[ARB] #I the input y input coordinates
+int ntie #I number of tie points
+real coeff[ARB] #I the output coefficient array
+int ncoeff #I the number of coefficients
+
+int i
+real xmag, ymag, xrot, yrot
+
+begin
+ # List the tie points on the standard output.
+ if (ntie > 0) {
+ do i = 1, ntie {
+ call printf (
+ " tie point: %3d ref: %9.3f %9.3f input: %9.3f %9.3f\n")
+ call pargi (i)
+ call pargr (xref[i])
+ call pargr (yref[i])
+ call pargr (xlist[i])
+ call pargr (ylist[i])
+ }
+ call printf ("\n")
+ }
+
+ # Print the transformation coefficients to the standard output.
+ call printf ("Initial linear transformation\n")
+ call printf (" %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (xlabel)
+ call pargr (coeff[3])
+ call pargr (coeff[1])
+ call pargr (coeff[2])
+ call printf (" %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (ylabel)
+ call pargr (coeff[6])
+ call pargr (coeff[4])
+ call pargr (coeff[5])
+ call rg_ctogeo (coeff[1], -coeff[2], -coeff[4], coeff[5], xmag, ymag,
+ xrot, yrot)
+ call printf (
+ " dx: %0.2f dy: %0.2f xmag: %0.3f ymag: %0.3f xrot: %0.1f yrot: %0.1f\n")
+ call pargr (coeff[3])
+ call pargr (coeff[6])
+ call pargr (xmag)
+ call pargr (ymag)
+ call pargr (xrot)
+ call pargr (yrot)
+ call printf ("\n")
+end
+
+
+# RG_PMLINCOEFF -- Print the computed transformation on the standard output.
+
+procedure rg_pmlincoeff (xlabel, ylabel, coeff, ncoeff)
+
+char xlabel[ARB] #I the x equation label
+char ylabel[ARB] #I the x equation label
+real coeff[ARB] #I the output coefficient array
+int ncoeff #I the number of coefficients
+
+real xmag, ymag, xrot, yrot
+
+begin
+ # Write the matched transformation coefficients to the standard output.
+ call printf ("Matched triangles transformation\n")
+ call printf (" %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (xlabel)
+ call pargr (coeff[3])
+ call pargr (coeff[1])
+ call pargr (coeff[2])
+ call printf (" %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (ylabel)
+ call pargr (coeff[6])
+ call pargr (coeff[4])
+ call pargr (coeff[5])
+ call rg_ctogeo (coeff[1], -coeff[2], -coeff[4], coeff[5], xmag, ymag,
+ xrot, yrot)
+ call printf (
+ " dx: %0.2f dy: %0.2f xmag: %0.3f ymag: %0.3f xrot: %0.1f yrot: %0.1f\n")
+ call pargr (coeff[3])
+ call pargr (coeff[6])
+ call pargr (xmag)
+ call pargr (ymag)
+ call pargr (xrot)
+ call pargr (yrot)
+ call printf ("\n")
+end
+
+
+# RG_WLINCOEFF -- Write the computed transformation to the output file.
+
+procedure rg_wlincoeff (fd, xlabel, ylabel, xref, yref, xlist, ylist, ntie,
+ coeff, ncoeff)
+
+int fd #I pointer to the output file
+char xlabel[ARB] #I the x equation label
+char ylabel[ARB] #I the x equation label
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+real xlist[ARB] #I the input x input coordinates
+real ylist[ARB] #I the input y input coordinates
+int ntie #I number of tie points
+real coeff[ARB] #I the output coefficient array
+int ncoeff #I the number of coefficients
+
+int i
+real xmag, ymag, xrot, yrot
+
+begin
+ # List the tie points.
+ if (ntie > 0) {
+ do i = 1, ntie {
+ call fprintf (fd,
+ "# tie point: %3d ref: %9.3f %9.3f input: %9.3f %9.3f\n")
+ call pargi (i)
+ call pargr (xref[i])
+ call pargr (yref[i])
+ call pargr (xlist[i])
+ call pargr (ylist[i])
+ }
+ call fprintf (fd, "#\n")
+ }
+
+ # Write the transformation coefficients to the output file.
+ call fprintf (fd, "# Initial linear transformation\n")
+ call fprintf (fd,
+ "# %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (xlabel)
+ call pargr (coeff[3])
+ call pargr (coeff[1])
+ call pargr (coeff[2])
+ call fprintf (fd,
+ "# %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (ylabel)
+ call pargr (coeff[6])
+ call pargr (coeff[4])
+ call pargr (coeff[5])
+ call rg_ctogeo (coeff[1], -coeff[2], -coeff[4], coeff[5], xmag, ymag,
+ xrot, yrot)
+ call fprintf (fd,
+ "# dx: %0.2f dy: %0.2f xmag: %0.3f ymag: %0.3f xrot: %0.1f yrot: %0.1f\n")
+ call pargr (coeff[3])
+ call pargr (coeff[6])
+ call pargr (xmag)
+ call pargr (ymag)
+ call pargr (xrot)
+ call pargr (yrot)
+ call fprintf (fd, "#\n")
+end
+
+
+# RG_WMLINCOEFF -- Print the computed transformation on the standard output.
+
+procedure rg_wmlincoeff (ofd, xlabel, ylabel, coeff, ncoeff)
+
+int ofd #I the output file descriptor
+char xlabel[ARB] #I the x equation label
+char ylabel[ARB] #I the x equation label
+real coeff[ARB] #I the output coefficient array
+int ncoeff #I the number of coefficients
+
+real xmag, ymag, xrot, yrot
+
+begin
+ # Write the matched transformation coefficients to the output file.
+ call fprintf (ofd, "# Matched triangles transformation\n")
+ call fprintf (ofd,
+ "# %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (xlabel)
+ call pargr (coeff[3])
+ call pargr (coeff[1])
+ call pargr (coeff[2])
+ call fprintf (ofd,
+ "# %4.4s[tie] = %10g + %10g * x[tie] + %10g * y[tie]\n")
+ call pargstr (ylabel)
+ call pargr (coeff[6])
+ call pargr (coeff[4])
+ call pargr (coeff[5])
+ call rg_ctogeo (coeff[1], -coeff[2], -coeff[4], coeff[5], xmag, ymag,
+ xrot, yrot)
+ call fprintf (ofd,
+ "# dx: %0.2f dy: %0.2f xmag: %0.3f ymag: %0.3f xrot: %0.1f yrot: %0.1f\n")
+ call pargr (coeff[3])
+ call pargr (coeff[6])
+ call pargr (xmag)
+ call pargr (ymag)
+ call pargr (xrot)
+ call pargr (yrot)
+ call fprintf (ofd, "#\n")
+end
+
+
+# RG_LINCOEFF -- Compute the transformation given one to three tie points.
+
+int procedure rg_lincoeff (xref, yref, xlist, ylist, ntie, coeff, ncoeff)
+
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+real xlist[ARB] #I the input x input coordinates
+real ylist[ARB] #I the input y input coordinates
+int ntie #I number of tie points
+real coeff[ARB] #O the output coefficient array
+int ncoeff #I the number of coefficients
+
+int ier, xier, yier, nfcoeff
+pointer sp, wts, fcoeff, sx, sy
+real xmin, xmax, ymin, ymax
+int rg_onestar(), rg_twostar(), rg_threestar()
+
+begin
+ switch (ntie) {
+ case 0:
+ ier = ERR
+ case 1:
+ ier = rg_onestar (xref, yref, xlist, ylist, ntie, coeff, ncoeff)
+ case 2:
+ ier = rg_twostar (xref, yref, xlist, ylist, ntie, coeff, ncoeff)
+ case 3:
+ ier = rg_threestar (xref, yref, xlist, ylist, ntie,
+ coeff, ncoeff)
+ default:
+ call smark (sp)
+ call salloc (fcoeff, 3, TY_REAL)
+ call salloc (wts, ntie, TY_REAL)
+ call alimr (xlist, ntie, xmin, xmax)
+ call alimr (ylist, ntie, ymin, ymax)
+ call gsinit (sx, GS_POLYNOMIAL, 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call gsinit (sy, GS_POLYNOMIAL, 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call amovkr (1.0, Memr[wts], ntie)
+ call gsfit (sx, xlist, ylist, xref, Memr[wts], ntie, WTS_UNIFORM,
+ xier)
+ call gsfit (sy, xlist, ylist, yref, Memr[wts], ntie, WTS_UNIFORM,
+ yier)
+ if (xier == OK && xier == OK) {
+ call gscoeff (sx, Memr[fcoeff], nfcoeff)
+ coeff[3] = Memr[fcoeff]
+ coeff[1] = Memr[fcoeff+1]
+ coeff[2] = Memr[fcoeff+2]
+ call gscoeff (sy, Memr[fcoeff], nfcoeff)
+ coeff[6] = Memr[fcoeff]
+ coeff[4] = Memr[fcoeff+1]
+ coeff[5] = Memr[fcoeff+2]
+ ier = OK
+ } else
+ ier = ERR
+ call gsfree (sx)
+ call gsfree (sy)
+ call sfree (sp)
+ }
+
+ return (ier)
+end
+
+
+# RG_COMPUTE -- Transform the input list coordinates. The transformation
+# may be done in place.
+
+procedure rg_compute (xlist, ylist, xtrans, ytrans, nstars, coeff, ncoeff)
+
+real xlist[ARB] #I the input x coordinates
+real ylist[ARB] #I the input y coordinates
+real xtrans[ARB] #O the output x transformed coordinates
+real ytrans[ARB] #O the output y transformed coordinates
+int nstars #I the number of points
+real coeff[ARB] #I the input coefficient array
+int ncoeff #I the number of coefficients
+
+int i
+real xval, yval
+
+begin
+ do i = 1, nstars {
+ xval = xlist[i]
+ yval = ylist[i]
+ xtrans[i] = coeff[1] * xval + coeff[2] * yval + coeff[3]
+ ytrans[i] = coeff[4] * xval + coeff[5] * yval + coeff[6]
+ }
+end
+
+
+# RG_INTERSECT -- Compute the intersection of two sorted lists given a
+# matching tolerance.
+
+int procedure rg_intersection (ofd, xref, yref, refindex, rlineno, nrefstars,
+ xlist, ylist, xtrans, ytrans, listindex, ilineno, nliststars,
+ tolerance, xformat, yformat)
+
+int ofd #I the output file descriptor
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+int refindex[ARB] #I the input reference coordinates sort index
+int rlineno[ARB] #I the input reference coordinate line numbers
+int nrefstars #I the number of reference stars
+real xlist[ARB] #I the input x list coordinates
+real ylist[ARB] #I the input y list coordinates
+real xtrans[ARB] #I the input x transformed list coordinates
+real ytrans[ARB] #I the input y transformed list coordinates
+int listindex[ARB] #I the input list sort index
+int ilineno[ARB] #I the input input line numbers
+int nliststars #I the number of input stars
+real tolerance #I the matching tolerance
+char xformat[ARB] #I the output x coordinate format
+char yformat[ARB] #I the output y coordinate format
+
+int blp, rp, rindex, lp, lindex, rmatch, lmatch, ninter
+pointer sp, fmtstr
+real dx, dy, tol2, rmax2, r2
+
+begin
+ call smark (sp)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+
+ # Construct the fromat string
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s %s %s %%5d %%5d\n")
+ if (xformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (xformat)
+ if (yformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (yformat)
+ if (xformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (xformat)
+ if (yformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (yformat)
+
+ # Initialize the intersection routine.
+ tol2 = tolerance ** 2
+ blp = 1
+ ninter = 0
+
+ # Loop over the reference list stars.
+ for (rp = 1; rp <= nrefstars; rp = rp + 1) {
+
+ # Get the index of the reference star in question.
+ rindex = refindex[rp]
+
+ # Compute the start of the search range.
+ for (; blp <= nliststars; blp = blp + 1) {
+ lindex = listindex[blp]
+ dy = yref[rindex] - ytrans[lindex]
+ if (dy < tolerance)
+ break
+ }
+
+ # Break if the end of the input list is reached.
+ if (blp > nliststars)
+ break
+
+ # If one is outside the tolerance limits skip to next reference
+ # object.
+ if (dy < -tolerance)
+ next
+
+ # Find the closest match to the reference object.
+ rmax2 = tol2
+ rmatch = 0
+ lmatch = 0
+ for (lp = blp; lp <= nliststars; lp = lp + 1) {
+
+ # Compute the distance between the two points.
+ lindex = listindex[lp]
+ dy = yref[rindex] - ytrans[lindex]
+ if (dy < -tolerance)
+ break
+ dx = xref[rindex] - xtrans[lindex]
+ r2 = dx ** 2 + dy ** 2
+
+ # A match has been found.
+ if (r2 <= rmax2) {
+ rmax2 = r2
+ rmatch = rindex
+ lmatch = lindex
+ }
+ }
+
+ # A match was found so write the results to the output file.
+ if (rmatch > 0 && lmatch > 0) {
+ ninter = ninter + 1
+ call fprintf (ofd, Memc[fmtstr])
+ call pargr (xref[rmatch])
+ call pargr (yref[rmatch])
+ call pargr (xlist[lmatch])
+ call pargr (ylist[lmatch])
+ call pargi (rlineno[rmatch])
+ call pargi (ilineno[lmatch])
+ }
+ }
+
+ call sfree (sp)
+
+ return (ninter)
+end
+
+
+# RG_LLINTERSECT -- Compute the intersection of two sorted lists given a
+# matching tolerance.
+
+int procedure rg_llintersect (ofd, lngref, latref, xref, yref, refindex,
+ rlineno, nrefstars, xlist, ylist, xtrans, ytrans, listindex, ilineno,
+ nliststars, tolerance, lngformat, latformat, xformat, yformat)
+
+int ofd #I the output file descriptor
+double lngref[ARB] #I the input ra/longitude reference coordinates
+double latref[ARB] #I the input dec/latitude reference coordinates
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+int refindex[ARB] #I the input reference coordinates sort index
+int rlineno[ARB] #I the input reference coordinate line numbers
+int nrefstars #I the number of reference stars
+real xlist[ARB] #I the input x list coordinates
+real ylist[ARB] #I the input y list coordinates
+real xtrans[ARB] #I the input x transformed list coordinates
+real ytrans[ARB] #I the input y transformed list coordinates
+int listindex[ARB] #I the input list sort index
+int ilineno[ARB] #I the input input line numbers
+int nliststars #I the number of input stars
+real tolerance #I the matching tolerance
+char lngformat[ARB] #I the output ra / longitude coordinate format
+char latformat[ARB] #I the output dec / latitude coordinate format
+char xformat[ARB] #I the output x coordinate format
+char yformat[ARB] #I the output y coordinate format
+
+int blp, rp, rindex, lp, lindex, rmatch, lmatch, ninter
+pointer sp, fmtstr
+real dx, dy, tol2, rmax2, r2
+
+begin
+ call smark (sp)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+
+ # Construct the fromat string
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s %s %s %%5d %%5d\n")
+ if (lngformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (lngformat)
+ if (latformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (latformat)
+ if (xformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (xformat)
+ if (yformat[1] == EOS)
+ call pargstr ("%13.7g")
+ else
+ call pargstr (yformat)
+
+ # Initialize the intersection routine.
+ tol2 = tolerance ** 2
+ blp = 1
+ ninter = 0
+
+ # Loop over the reference list stars.
+ for (rp = 1; rp <= nrefstars; rp = rp + 1) {
+
+ # Get the index of the reference star in question.
+ rindex = refindex[rp]
+
+ # Compute the start of the search range.
+ for (; blp <= nliststars; blp = blp + 1) {
+ lindex = listindex[blp]
+ dy = yref[rindex] - ytrans[lindex]
+ if (dy < tolerance)
+ break
+ }
+
+ # Break if the end of the input list is reached.
+ if (blp > nliststars)
+ break
+
+ # If one is outside the tolerance limits skip to next reference
+ # object.
+ if (dy < -tolerance)
+ next
+
+ # Find the closest match to the reference object.
+ rmax2 = tol2
+ rmatch = 0
+ lmatch = 0
+ for (lp = blp; lp <= nliststars; lp = lp + 1) {
+
+ # Compute the distance between the two points.
+ lindex = listindex[lp]
+ dy = yref[rindex] - ytrans[lindex]
+ if (dy < -tolerance)
+ break
+ dx = xref[rindex] - xtrans[lindex]
+ r2 = dx ** 2 + dy ** 2
+
+ # A match has been found.
+ if (r2 <= rmax2) {
+ rmax2 = r2
+ rmatch = rindex
+ lmatch = lindex
+ }
+ }
+
+ # A match was found so write the results to the output file.
+ if (rmatch > 0 && lmatch > 0) {
+ ninter = ninter + 1
+ call fprintf (ofd, Memc[fmtstr])
+ call pargd (lngref[rmatch])
+ call pargd (latref[rmatch])
+ call pargr (xlist[lmatch])
+ call pargr (ylist[lmatch])
+ call pargi (rlineno[rmatch])
+ call pargi (ilineno[lmatch])
+ }
+ }
+
+ call sfree (sp)
+
+ return (ninter)
+end
+
+
+# RG_LMKCOEFF -- Given the geometry of a linear transformation compute
+# the coefficients required to tranform from the input to the reference
+# system.
+
+procedure rg_lmkcoeff (xin, yin, xmag, ymag, xrot, yrot, xout, yout,
+ coeff, ncoeff)
+
+real xin, yin #I the origin of the input coordinates
+real xmag, ymag #I the input x and y scale factors
+real xrot, yrot #I the iput x and y rotation factors
+real xout, yout #I the origin of the reference coordinates
+real coeff[ARB] #O the output coefficient array
+int ncoeff #I the number of coefficients
+
+begin
+ # Compute the x fit coefficients.
+ coeff[1] = xmag * cos (DEGTORAD(xrot))
+ coeff[2] = -ymag * sin (DEGTORAD(yrot))
+ coeff[3] = xout - coeff[1] * xin - coeff[2] * yin
+
+ # Compute the y fit coefficients.
+ coeff[4] = xmag * sin (DEGTORAD(xrot))
+ coeff[5] = ymag * cos (DEGTORAD(yrot))
+ coeff[6] = yout - coeff[4] * xin - coeff[5] * yin
+end
+
+
+# RG_ONESTAR -- Compute the transformation coefficients for a simple
+# shift operation.
+
+int procedure rg_onestar (xref, yref, xlist, ylist, ntie, coeff, ncoeff)
+
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+real xlist[ARB] #I the input x list coordinates
+real ylist[ARB] #I the input y list coordinates
+int ntie #I the number of tie points
+real coeff[ARB] #O the output coefficient array
+int ncoeff #I the number of coefficients
+
+begin
+ # Compute the x transformation.
+ coeff[1] = 1.0
+ coeff[2] = 0.0
+ coeff[3] = xref[1] - xlist[1]
+
+ # Compute the y transformation.
+ coeff[4] = 0.0
+ coeff[5] = 1.0
+ coeff[6] = yref[1] - ylist[1]
+
+ return (OK)
+end
+
+
+# RG_TWOSTAR -- Compute the transformation coefficients of a simple shift,
+# magnification, and rotation.
+
+int procedure rg_twostar (xref, yref, xlist, ylist, ntie, coeff, ncoeff)
+
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+real xlist[ARB] #I the input x list coordinates
+real ylist[ARB] #I the input y list coordinates
+int ntie #I the number of tie points
+real coeff[ARB] #O the output coefficient array
+int ncoeff #I the number of coefficients
+
+real rot, mag, dxlis, dylis, dxref, dyref, cosrot, sinrot
+real rg_posangle()
+
+begin
+ # Compute the deltas.
+ dxlis = xlist[2] - xlist[1]
+ dylis = ylist[2] - ylist[1]
+ dxref = xref[2] - xref[1]
+ dyref = yref[2] - yref[1]
+
+ # Compute the rotation angle.
+ rot = rg_posangle (dxref, dyref) - rg_posangle (dxlis, dylis)
+ cosrot = cos (rot)
+ sinrot = sin (rot)
+
+ # Compute the magnification factor.
+ mag = dxlis ** 2 + dylis ** 2
+ if (mag <= 0.0)
+ mag = 0.0
+ else
+ mag = sqrt ((dxref ** 2 + dyref ** 2) / mag)
+
+ # Compute the transformation coefficicents.
+ coeff[1] = mag * cosrot
+ coeff[2] = - mag * sinrot
+ coeff[3] = xref[1] - mag * cosrot * xlist[1] + mag * sinrot * ylist[1]
+ coeff[4] = mag * sinrot
+ coeff[5] = mag * cosrot
+ coeff[6] = yref[1] - mag * sinrot * xlist[1] - mag * cosrot * ylist[1]
+
+ return (OK)
+end
+
+
+# RG_THREESTAR -- Compute the transformation coefficients using a simple
+# shift, magnification in x and y, rotation, and skew.
+
+int procedure rg_threestar (xref, yref, xlist, ylist, ntie, coeff, ncoeff)
+
+real xref[ARB] #I the input x reference coordinates
+real yref[ARB] #I the input y reference coordinates
+real xlist[ARB] #I the input x list coordinates
+real ylist[ARB] #I the input y list coordinates
+int ntie #I the number of tie points
+real coeff[ARB] #O the output coefficient array
+int ncoeff #I the number of coefficients
+
+real dx23, dx13, dx12, dy23, dy13, dy12, det
+bool fp_equalr()
+int rg_twostar()
+
+begin
+ # Compute the deltas.
+ dx23 = xlist[2] - xlist[3]
+ dx13 = xlist[1] - xlist[3]
+ dx12 = xlist[1] - xlist[2]
+ dy23 = ylist[2] - ylist[3]
+ dy13 = ylist[1] - ylist[3]
+ dy12 = ylist[1] - ylist[2]
+
+ # Compute the determinant.
+ det = xlist[1] * dy23 - xlist[2] * dy13 + xlist[3] * dy12
+ if (fp_equalr (det, 0.0))
+ return (rg_twostar (xref, yref, xlist, ylist, ntie,
+ coeff, ncoeff))
+
+ # Compute the x transformation.
+ coeff[1] = (xref[1] * dy23 - xref[2] * dy13 + xref[3] * dy12) / det
+ coeff[2] = (-xref[1] * dx23 + xref[2] * dx13 - xref[3] * dx12) / det
+ coeff[3] = (xref[1] * (xlist[2] * ylist[3] - xlist[3] * ylist[2]) +
+ xref[2] * (ylist[1] * xlist[3] - xlist[1] * ylist[3]) +
+ xref[3] * (xlist[1] * ylist[2] - ylist[1] * xlist[2])) / det
+
+ # Compute the y transformation.
+ coeff[4] = (yref[1] * dy23 - yref[2] * dy13 + yref[3] * dy12) / det
+ coeff[5] = (-yref[1] * dx23 + yref[2] * dx13 - yref[3] * dx12) / det
+ coeff[6] = (yref[1] * (xlist[2] * ylist[3] - xlist[3] * ylist[2]) +
+ yref[2] * (ylist[1] * xlist[3] - xlist[1] * ylist[3]) +
+ yref[3] * (xlist[1] * ylist[2] - ylist[1] * xlist[2])) / det
+
+ return (OK)
+end
+
+
+# RG_POSANGLE -- Compute the position angle of a 2D vector. The angle is
+# measured counter-clockwise from the positive x axis.
+
+real procedure rg_posangle (x, y)
+
+real x #I the x vector component
+real y #I the y vector component
+
+real theta
+bool fp_equalr()
+
+begin
+ if (fp_equalr (y, 0.0)) { # 0-valued y component
+ if (x > 0.0)
+ theta = 0.0
+ else if (x < 0.0)
+ theta = PI
+ else
+ theta = 0.0
+ } else if (fp_equalr (x, 0.0)) { # 0-valued x component
+ if (y > 0.0)
+ theta = PI / 2.0
+ else if (y < 0.0)
+ theta = 3.0 * PI / 2.0
+ else
+ theta = 0.0
+ } else if (x > 0.0 && y > 0.0) { # 1st quadrant
+ theta = atan (y / x)
+ } else if (x > 0.0 && y < 0.0) { # 4th quadrant
+ theta = 2.0 * PI + atan (y / x)
+ } else if (x < 0.0 && y > 0.0) { # 2nd quadrant
+ theta = PI + atan (y / x)
+ } else if (x < 0.0 && y < 0.0) { # 3rd quadrant
+ theta = PI + atan (y / x)
+ }
+
+ return (theta)
+end
+
+
+# RG_CTOGEO -- Transform the linear transformation coefficients to useful
+# geometric parameters.
+
+procedure rg_ctogeo (a, b, c, d, xscale, yscale, xrot, yrot)
+
+real a #I the x coefficient of the x coordinate fit
+real b #I the y coefficient of the x coordinate fit
+real c #I the x coefficient of the y coordinate fit
+real d #I the y coefficient of the y coordinate fit
+real xscale #I output x scale
+real yscale #I output y scale
+real xrot #I rotation of point on x axis
+real yrot #I rotation of point on y axis
+
+bool fp_equalr()
+
+begin
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+
+ # Get the x and y axes rotation factors.
+ if (fp_equalr (a, 0.0) && fp_equalr (c, 0.0))
+ xrot = 0.0
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < 0.0)
+ xrot = xrot + 360.0
+
+ if (fp_equalr (b, 0.0) && fp_equalr (d, 0.0))
+ yrot = 0.0
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < 0.0)
+ yrot = yrot + 360.0
+end
diff --git a/pkg/images/lib/rgwrdstr.x b/pkg/images/lib/rgwrdstr.x
new file mode 100644
index 00000000..5c3cee28
--- /dev/null
+++ b/pkg/images/lib/rgwrdstr.x
@@ -0,0 +1,53 @@
+
+# RG_WRDSTR -- Search a dictionary string for a given string index number.
+# This is the opposite function of strdic(), that returns the index for
+# given string. The entries in the dictionary string are separated by
+# a delimiter character which is the first character of the dictionary
+# string. The index of the string found is returned as the function value.
+# Otherwise, if there is no string for that index, a zero is returned.
+
+int procedure rg_wrdstr (index, outstr, maxch, dict)
+
+int index #I String index
+char outstr[ARB] #O Output string as found in dictionary
+int maxch #I Maximum length of output string
+char dict[ARB] #IDictionary string
+
+int i, len, start, count
+
+int strlen()
+
+begin
+ # Clear the output string.
+ outstr[1] = EOS
+
+ # Return if the dictionary is not long enough.
+ if (dict[1] == EOS)
+ return (0)
+
+ # Initialize the counters.
+ count = 1
+ len = strlen (dict)
+
+ # Search the dictionary string. This loop only terminates
+ # successfully if the index is found. Otherwise the procedure
+ # returns with and error condition.
+ for (start = 2; count < index; start = start + 1) {
+ if (dict[start] == dict[1])
+ count = count + 1
+ if (start == len)
+ return (0)
+ }
+
+ # Extract the output string from the dictionary.
+ for (i = start; dict[i] != EOS && dict[i] != dict[1]; i = i + 1) {
+ if (i - start + 1 > maxch)
+ break
+ outstr[i - start + 1] = dict[i]
+ }
+ outstr[i - start + 1] = EOS
+
+ # Return index for output string.
+ return (count)
+end
+
diff --git a/pkg/images/lib/rgxymatch.x b/pkg/images/lib/rgxymatch.x
new file mode 100644
index 00000000..3b2b45cb
--- /dev/null
+++ b/pkg/images/lib/rgxymatch.x
@@ -0,0 +1,97 @@
+include <mwset.h>
+
+# RG_RXYL -- Compute the grid of logical coordinates.
+
+procedure rg_rxyl (xl, yl, nx, ny, x1, x2, y1, y2)
+
+double xl[ARB] #O array of output x coordinates
+double yl[ARB] #O array of output y coordinates
+int nx #I the size of the grid in x
+int ny #I the size of the grid in y
+double x1 #I the lower limit of the grid in x
+double x2 #I the upper limit of the grid in x
+double y1 #I the lower limit of the grid in y
+double y2 #I the upper limit of the grid in y
+
+double xstep, ystep, x, y
+int i, j, npts
+
+begin
+ if (nx == 1)
+ xstep = 0.0d0
+ else
+ xstep = (x2 - x1) / (nx - 1)
+ if (ny == 1)
+ ystep = 0.0d0
+ else
+ ystep = (y2 - y1) / (ny - 1)
+ npts = 0
+
+ y = y1
+ do j = 1, ny {
+ x = x1
+ do i = 1, nx {
+ npts = npts + 1
+ xl[npts] = x
+ yl[npts] = y
+ x = x + xstep
+ }
+ y = y + ystep
+ }
+end
+
+
+# RG_XYTOXY -- Compute the world coordinate list give the wcs descriptor
+# and the logical coordinates.
+
+pointer procedure rg_xytoxy (mw, xl, yl, xw, yw, npts, inwcs, outwcs, ax1, ax2)
+
+pointer mw #I the wcs descriptor
+double xl[ARB] #I the input logical x coordinate
+double yl[ARB] #I the input logical y coordinate
+double xw[ARB] #O the output world x coordinate
+double yw[ARB] #O the output world y coordinate
+int npts #I the number of coordinates.
+char inwcs[ARB] #I the input wcs
+char outwcs[ARB] #I the output wcs
+int ax1 #I the logical x axis
+int ax2 #I the logical y axis
+
+int i, axbits
+pointer ct
+double mw_c1trand()
+int mw_stati()
+pointer mw_sctran()
+errchk mw_sctran()
+
+begin
+ # Compile the transformation.
+ if (mw == NULL) {
+ ct = NULL
+ } else if (mw_stati (mw, MW_NDIM) >= 2) {
+ axbits = 2 ** (ax1 - 1) + 2 ** (ax2 - 1)
+ iferr (ct = mw_sctran (mw, inwcs, outwcs, axbits))
+ ct = NULL
+ } else {
+ axbits = 2 ** (ax1 - 1)
+ iferr (ct = mw_sctran (mw, inwcs, outwcs, axbits))
+ ct = NULL
+ }
+
+ # Compute the world coordinates.
+ if (ct == NULL) {
+ call amovd (xl, xw, npts)
+ call amovd (yl, yw, npts)
+ } else if (mw_stati (mw, MW_NDIM) == 2) {
+ do i = 1, npts
+ call mw_c2trand (ct, xl[i], yl[i], xw[i], yw[i])
+ } else {
+ do i = 1, npts {
+ xw[i] = mw_c1trand (ct, xl[i])
+ yw[i] = yl[i]
+ }
+ }
+
+ return (ct)
+end
+
diff --git a/pkg/images/lib/xymatch.x b/pkg/images/lib/xymatch.x
new file mode 100644
index 00000000..96907578
--- /dev/null
+++ b/pkg/images/lib/xymatch.x
@@ -0,0 +1,175 @@
+include "xyxymatch.h"
+
+# RG_RDXYI -- Read in the x and y coordinates from a file and set the
+# line number index.
+
+int procedure rg_rdxyi (fd, x, y, lineno, xcolumn, ycolumn)
+
+int fd #I the input file descriptor
+pointer x #U pointer to the x coordinates
+pointer y #U pointer to the y coordinates
+pointer lineno #U pointer to the line numbers
+int xcolumn #I column containing the x coordinate
+int ycolumn #I column containing the y coordinate
+
+int i, ip, bufsize, npts, lnpts, maxcols
+pointer sp, str
+real xval, yval
+int fscan(), nscan(), ctor()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ bufsize = DEF_BUFSIZE
+ call malloc (x, bufsize, TY_REAL)
+ call malloc (y, bufsize, TY_REAL)
+ call malloc (lineno, bufsize, TY_INT)
+ maxcols = max (xcolumn, ycolumn)
+
+ npts = 0
+ lnpts = 0
+ while (fscan(fd) != EOF) {
+
+ lnpts = lnpts + 1
+ xval = INDEFR
+ yval = INDEFR
+ do i = 1, maxcols {
+ call gargwrd (Memc[str], SZ_LINE)
+ if (i != nscan())
+ break
+ ip = 1
+ if (i == xcolumn) {
+ if (ctor (Memc[str], ip, xval) <= 0)
+ xval = INDEFR
+ } else if (i == ycolumn) {
+ if (ctor (Memc[str], ip, yval) <= 0)
+ yval = INDEFR
+ }
+ }
+ if (IS_INDEFR(xval) || IS_INDEFR(yval))
+ next
+
+ Memr[x+npts] = xval
+ Memr[y+npts] = yval
+ Memi[lineno+npts] = lnpts
+ npts = npts + 1
+ if (npts >= bufsize) {
+ bufsize = bufsize + DEF_BUFSIZE
+ call realloc (x, bufsize, TY_REAL)
+ call realloc (y, bufsize, TY_REAL)
+ call realloc (lineno, bufsize, TY_INT)
+ }
+ }
+
+ call sfree (sp)
+
+ return (npts)
+end
+
+
+# RG_SORT -- If the coordinates are not already sorted, sort the coordinates
+# first in y then in x. Remove points which are close together than a given
+# tolerance, if the coincident point remove flag is on.
+
+int procedure rg_sort (xcoord, ycoord, rsindex, npts, tolerance, sort, coincid)
+
+real xcoord[ARB] #I pointer to the x coordinates
+real ycoord[ARB] #I pointer to the y coordinates
+int rsindex[ARB] #I pointer to sort index
+int npts #I the number of objects
+real tolerance #I coincidence tolerance in pixels
+int sort #I sort the pixels ?
+int coincid #I remove coincident points
+
+int i, ndif
+int rg_xycoincide()
+
+begin
+ # Initialize the sort index.
+ do i = 1, npts
+ rsindex[i] = i
+
+ # Sort the pixels in y and then x if the arrays are unsorted.
+ if (sort == YES) {
+ call rg_qsortr (ycoord, rsindex, rsindex, npts)
+ call rg_sqsort (xcoord, ycoord, rsindex, rsindex, npts)
+ }
+
+ # Remove objects that are closer together than tolerance.
+ if (coincid == NO)
+ ndif = npts
+ else
+ ndif = rg_xycoincide (xcoord, ycoord, rsindex, rsindex, npts,
+ tolerance)
+
+ return (ndif)
+end
+
+
+# RG_XYCOINCIDE -- Remove points from a list which are closer together than
+# a specified tolerance. The arrays are assumed to be sorted first in y then
+# in x.
+
+int procedure rg_xycoincide (xcoord, ycoord, a, b, npts, tolerance)
+
+real xcoord[ARB] #I the input x coordinate values
+real ycoord[ARB] #I the input y coordinate values
+int a[ARB] #I the input sort index
+int b[ARB] #O the output sort index
+int npts #I the number of points
+real tolerance #I the coincidence tolerace
+
+int iprev, i, nunique
+real tol2, r2
+
+begin
+ tol2 = tolerance ** 2
+ nunique = npts
+
+ iprev = 1
+ repeat {
+
+ do i = iprev + 1, npts {
+
+ # Jump to the next object if this one has been deleted
+ # since all comparisons are then invalid.
+ if (a[iprev] == 0)
+ break
+
+ # Skip to the next object if this one has been deleted.
+ if (a[i] == 0)
+ next
+
+ # Check the tolerance limit in y and step to the next object
+ # if the bounds are exceeded.
+ r2 = (ycoord[a[i]] - ycoord[a[iprev]]) ** 2
+ if (r2 > tol2)
+ break
+
+ # Check the tolerance limit.
+ r2 = r2 + (xcoord[a[i]] - xcoord[a[iprev]]) ** 2
+ if (r2 <= tol2) {
+ a[i] = 0
+ nunique = nunique - 1
+ }
+ }
+
+ iprev = iprev + 1
+
+ } until (iprev >= npts)
+
+ # Reorder the index array.
+ if (nunique < npts) {
+ iprev = 0
+ do i = 1, npts {
+ if (a[i] != 0) {
+ iprev = iprev + 1
+ b[iprev] = a[i]
+ }
+ }
+ }
+
+ return (nunique)
+end
+
diff --git a/pkg/images/lib/xyxymatch.h b/pkg/images/lib/xyxymatch.h
new file mode 100644
index 00000000..50e44e74
--- /dev/null
+++ b/pkg/images/lib/xyxymatch.h
@@ -0,0 +1,35 @@
+# The definitions file for the LINXYMATCH task
+
+# Define the matching algorithms
+
+define RG_MATCHSTR "|tolerance|triangles|"
+define RG_TOLERANCE 1 # Match by tolerance only
+define RG_TRIANGLES 2 # Match by triangles
+
+# Define the reference and input files types
+
+define RG_REFFILE 1 # The input reference coordinate file
+define RG_INFILE 2 # The input coordinate file
+
+# Define some useful constants
+
+define MAX_NTIE 3 # Maximum number of tie points
+define MAX_NCOEFF 6 # Maximum number of coefficients
+define DEF_BUFSIZE 1000 # The default buffer size
+define SZ_TRIINDEX 6 # Number of triangle indices to save.
+define SZ_TRIPAR 5 # Number of triangle parameters
+
+# Define the structure of the internal arrays used by the trangles algorithm
+
+define RG_INDEX 1 # Sort index
+define RG_X1 2 # Vertex 1
+define RG_X2 3 # Vertex 2
+define RG_X3 4 # Vertex 3
+define RG_CC 5 # Counterclockwise ?
+define RG_MATCH 6 # Match index
+
+define RG_LOGP 1 # Log of the perimeter
+define RG_RATIO 2 # Ratio of longest to shortest side
+define RG_COS1 3 # Cos of angle at vertex 1
+define RG_TOLR 4 # Tolerance in the ratio
+define RG_TOLC 5 # Tolerance in the cosine
diff --git a/pkg/images/lib/zzdebug.x b/pkg/images/lib/zzdebug.x
new file mode 100644
index 00000000..d80be43f
--- /dev/null
+++ b/pkg/images/lib/zzdebug.x
@@ -0,0 +1,430 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+
+# Simples IMIO test routines.
+
+task mkimage = t_mkimage,
+ mktest = t_mktest,
+ cube = t_cube,
+ maxmin = t_maxmin,
+ gsubras = t_gsubras,
+ dump = t_dump
+
+
+include <imhdr.h>
+include <printf.h>
+include <ctype.h>
+include <mach.h>
+
+
+define NTYPES 7
+
+# MKIMAGE -- Make a new two dimensional image of a specified size
+# and datatype. The image pixels are all set to zero.
+
+procedure t_mkimage()
+
+int dtype
+real pixval
+int ncols, nlines
+char imname[SZ_FNAME]
+char title[SZ_LINE]
+short ty_code[NTYPES]
+
+real clgetr()
+char clgetc(), ch
+int clgeti(), stridx()
+
+string types "usilrdx" # Supported pixfile datatypes
+data ty_code /TY_USHORT, TY_SHORT, TY_INT, TY_LONG, TY_REAL,
+ TY_DOUBLE, TY_COMPLEX/
+begin
+ call clgstr ("image", imname, SZ_FNAME)
+ ncols = clgeti ("ncols")
+ nlines = clgeti ("nlines")
+ ch = clgetc ("datatype")
+ dtype = ty_code[stridx(ch,types)]
+ pixval = clgetr ("pixval")
+ call clgstr ("title", title, SZ_LINE)
+
+ call immake2 (imname, ncols, nlines, dtype, pixval, title)
+end
+
+
+# IMMAKE2 -- Make a two dimensional image of datatype [usilr] with all pixels
+# set to the given value.
+
+procedure immake2 (imname, ncols, nlines, dtype, pixval, title)
+
+char imname[ARB] # name of new image
+int ncols, nlines # image size
+int dtype # datatype
+real pixval # constant pixel value
+char title[ARB] # image title
+
+int i
+pointer im, buf
+pointer immap(), impl2r()
+
+begin
+ im = immap (imname, NEW_IMAGE, 0)
+
+ IM_PIXTYPE(im) = dtype
+ IM_LEN(im,1) = ncols
+ IM_LEN(im,2) = nlines
+ call strcpy (title, IM_TITLE(im), SZ_IMTITLE)
+
+ # Write out the lines.
+
+ do i = 1, nlines {
+ buf = impl2r (im, i)
+ call amovkr (pixval, Memr[buf], ncols)
+ }
+
+ call imunmap (im)
+end
+
+
+# MKTEST -- Make a test image.
+
+procedure t_mktest()
+
+char imname[SZ_FNAME]
+int ndim, dim[IM_MAXDIM]
+int i, j, k, scalar
+long offset
+int clgeti(), nscan(), clscan(), stridx()
+pointer buf, im, immap(), impl3l()
+
+int dtype
+string types "usilrdx" # Supported pixfile datatypes
+char ty_code[7], clgetc()
+data ty_code /TY_USHORT, TY_SHORT, TY_INT, TY_LONG, TY_REAL,
+ TY_DOUBLE, TY_COMPLEX, EOS/
+
+begin
+ call clgstr ("image_name", imname, SZ_FNAME)
+ dtype = ty_code[stridx (clgetc ("datatype"), types)]
+ ndim = clgeti ("ndim")
+
+ call amovki (1, dim, 3)
+ if (clscan ("axis_lengths") != EOF) {
+ do i = 1, ndim
+ call gargi (dim[i])
+ if (nscan() < ndim)
+ call error (1, "Insufficient dimensions")
+ }
+
+ im = immap (imname, NEW_IMAGE, 0)
+
+ IM_PIXTYPE(im) = dtype
+ do i = 1, ndim
+ IM_LEN(im,i) = dim[i]
+
+ do k = 1, dim[3]
+ do j = 1, dim[2] {
+ buf = impl3l (im, j, k)
+
+ # Pixel value eq pixel coords.
+ offset = 1
+ if (ndim > 1) {
+ if (dim[1] < 100)
+ scalar = 100
+ else
+ scalar = 1000
+ offset = offset + j * scalar
+ }
+
+ if (ndim > 2)
+ offset = offset + k * (scalar ** 2)
+
+ # Avoid integer overflow if large type short image.
+ if (IM_PIXTYPE(im) == TY_SHORT)
+ offset = min (MAX_SHORT, offset - dim[1])
+
+ # Initialize line of pixels.
+ do i = 0, dim[1]-1
+ Meml[buf+i] = offset + i
+ }
+
+ call imunmap (im)
+end
+
+
+# CUBE -- Get a subraster from an image, and print out the pixel values
+# on the standard output.
+
+define MAXDIM 3
+
+procedure t_cube()
+
+char imname[SZ_FNAME], fmt
+int i, nx, ny, nz, ndim
+int vs[IM_MAXDIM], ve[IM_MAXDIM]
+pointer im, ras, imgs3r(), immap()
+int clscan(), nscan()
+char clgetc()
+
+begin
+ call clgstr ("image_name", imname, SZ_FNAME)
+ fmt = clgetc ("numeric_format")
+
+ im = immap (imname, READ_ONLY, 0)
+
+ # Get the coordinates of the subraster to be extracted. Determine
+ # dimensionality of subraster.
+
+ if (clscan ("subraster_coordinates") != EOF) {
+ for (ndim=1; ndim <= MAXDIM; ndim=ndim+1) {
+ switch (fmt) {
+ case FMT_DECIMAL:
+ call gargi (vs[ndim])
+ call gargi (ve[ndim])
+ case FMT_OCTAL:
+ call gargrad (vs[ndim], 8)
+ call gargrad (ve[ndim], 8)
+ case FMT_HEX:
+ call gargrad (vs[ndim], 16)
+ call gargrad (ve[ndim], 16)
+ }
+
+ if (nscan() < ndim * 2) {
+ ndim = nscan() / 2
+ break
+ }
+ }
+ }
+
+ if (ndim == 0)
+ return
+
+ for (i=ndim+1; i <= MAXDIM; i=i+1) {
+ vs[i] = 1
+ ve[i] = 1
+ }
+
+ # Extract subraster from image. Print table on the standard
+ # output.
+
+ ras = imgs3r (im, vs[1], ve[1], vs[2], ve[2], vs[3], ve[3])
+ call imbln3 (im, nx, ny, nz)
+
+ call print_cube (STDOUT, Memr[ras], nx, ny, nz, vs, ve, fmt)
+ call imunmap (im)
+end
+
+
+# PRINT_CUBE -- Print a cube of pixels of type REAL on a file.
+
+procedure print_cube (fd, cube, nx, ny, nz, vs, ve, fmt)
+
+char fmt
+int fd, nx, ny, nz
+real cube[nx,ny,nz]
+int vs[MAXDIM], ve[MAXDIM], vinc[MAXDIM]
+int i, j, k
+errchk fprintf, pargi, pargr
+
+begin
+ do i = 1, MAXDIM # loop increments
+ if (vs[i] <= ve[i])
+ vinc[i] = 1
+ else
+ vinc[i] = -1
+
+ # Print table of pixel values on the standard output. Label bands,
+ # lines, and columns.
+
+ do k = 1, nz {
+ call fprintf (fd, "Band %0.0*:\n")
+ call pargc (fmt)
+ call pargi (vs[MAXDIM] + (k-1) * vinc[MAXDIM])
+
+ call fprintf (fd, "%9w")
+ do i = 1, nx { # label columns
+ call fprintf (fd, "%9* ")
+ call pargc (fmt)
+ call pargi (vs[1] + (i-1) * vinc[1])
+ }
+ call fprintf (fd, "\n")
+
+ do j = 1, ny {
+ call fprintf (fd, "%5* ")
+ call pargc (fmt)
+ call pargi (vs[2] + (j-1) * vinc[2])
+ do i = 1, nx { # print pixels
+ call fprintf (fd, "%12*")
+ call pargc (fmt)
+ call pargr (cube[i,j,k])
+ }
+ call fprintf (fd, "\n")
+ }
+ call fprintf (fd, "\n")
+ }
+end
+
+
+# MAXMIN -- Compute the minimum and maximum pixel values of an image.
+# Works for images of any dimensionality, size, or datatype.
+
+procedure t_maxmin()
+
+char imname[SZ_FNAME]
+real minval, maxval
+long v[IM_MAXDIM], clktime()
+pointer im, buf, immap(), imgnlr()
+
+begin
+ call clgstr ("imname", imname, SZ_FNAME)
+ call amovkl (long(1), v, IM_MAXDIM) # start vector
+
+ im = immap (imname, READ_WRITE, 0)
+
+ # Only calculate minimum, maximum pixel values if the current
+ # values are unknown, or if the image was modified since the
+ # old values were computed.
+
+ if (IM_LIMTIME(im) < IM_MTIME(im)) {
+ IM_MIN(im) = MAX_REAL
+ IM_MAX(im) = -MAX_REAL
+
+ while (imgnlr (im, buf, v) != EOF) {
+ call alimr (Memr[buf], IM_LEN(im,1), minval, maxval)
+ IM_MIN(im) = min (IM_MIN(im), minval)
+ IM_MAX(im) = max (IM_MAX(im), maxval)
+ }
+
+ IM_LIMTIME(im) = clktime (long(0))
+ }
+
+ call clputr ("minval", IM_MIN(im))
+ call clputr ("maxval", IM_MAX(im))
+
+ call imunmap (im)
+end
+
+
+define MAXDIM 3
+
+# GSUBRAS -- Get a type short subraster from an image, and print out the
+# minimum and maximum pixel values on the standard output.
+
+procedure t_gsubras()
+
+char imname[SZ_FNAME], fmt
+int i, nx, ny, nz, ndim
+int vs[IM_MAXDIM], ve[IM_MAXDIM]
+short minval, maxval
+pointer im, ras
+pointer imgs1s(), imgs2s(), imgs3s(), immap()
+int clscan(), nscan()
+char clgetc()
+
+begin
+ call clgstr ("image_name", imname, SZ_FNAME)
+ fmt = clgetc ("numeric_format")
+
+ im = immap (imname, READ_ONLY, 0)
+
+ # Get the coordinates of the subraster to be extracted. Determine
+ # dimensionality of subraster.
+
+ if (clscan ("subraster_coordinates") != EOF) {
+ for (ndim=1; ndim <= MAXDIM; ndim=ndim+1) {
+ switch (fmt) {
+ case FMT_DECIMAL:
+ call gargi (vs[ndim])
+ call gargi (ve[ndim])
+ case FMT_OCTAL:
+ call gargrad (vs[ndim], 8)
+ call gargrad (ve[ndim], 8)
+ case FMT_HEX:
+ call gargrad (vs[ndim], 16)
+ call gargrad (ve[ndim], 16)
+ }
+
+ if (nscan() < ndim * 2) {
+ ndim = nscan() / 2
+ break
+ }
+ }
+ ndim = min (MAXDIM, ndim)
+ }
+
+ if (ndim == 0)
+ return
+
+ for (i=ndim+1; i <= MAXDIM; i=i+1) {
+ vs[i] = 1
+ ve[i] = 1
+ }
+
+ # Extract subraster from image. Print table on the standard
+ # output.
+
+ switch (ndim) {
+ case 1:
+ ras = imgs1s (im, vs[1], ve[1])
+ call imbln1 (im, nx)
+ ny = 1
+ nz = 1
+ case 2:
+ ras = imgs2s (im, vs[1], ve[1], vs[2], ve[2])
+ call imbln2 (im, nx, ny)
+ nz = 1
+ case 3:
+ ras = imgs3s (im, vs[1], ve[1], vs[2], ve[2], vs[3], ve[3])
+ call imbln3 (im, nx, ny, nz)
+ }
+
+ minval = MAX_SHORT
+ maxval = -MAX_SHORT
+ call alims (Mems[ras], nx * ny * nz, minval, maxval)
+
+ call printf ("min = %0.0*, max = %0.0*\n")
+ call pargc (fmt)
+ call pargs (minval)
+ call pargc (fmt)
+ call pargs (maxval)
+
+ call imunmap (im)
+end
+
+
+# DUMP -- Dump the user area of an image header for diagnostic purposes.
+# Blanks are rendered into underscores to make them visible. This is a
+# throwaway task.
+
+procedure t_dump()
+
+char image[SZ_FNAME]
+int i
+pointer ip, im
+pointer immap()
+
+begin
+ call clgstr ("image", image, SZ_FNAME)
+ im = immap (image, READ_ONLY, 0)
+
+ # Print ruler.
+ do i = 1, 80
+ if (mod(i,10) == 0)
+ call putci (STDOUT, TO_DIGIT(i/10))
+ else
+ call putci (STDOUT, ' ')
+ call putci (STDOUT, '\n')
+
+ do i = 1, 80
+ call putci (STDOUT, TO_DIGIT(mod(i,10)))
+ call putci (STDOUT, '\n')
+
+ # Map blanks into underscores.
+ for (ip = IM_USERAREA(im); Memc[ip] != EOS; ip=ip+1)
+ if (Memc[ip] == ' ')
+ Memc[ip] = '_'
+
+ # Dump user area.
+ call putline (STDOUT, Memc[IM_USERAREA(im)])
+ call imunmap (im)
+end
+