home *** CD-ROM | disk | FTP | other *** search
- /*
- * GRAPH, Version 1.00 - 4 August 1989
- *
- * Copyright 1989, David Gay. All Rights Reserved.
- * This software is freely redistrubatable.
- */
-
- /* Set up a coordinate system in a Rastport */
- /* Copyright 1989, David Gay */
- #include <exec/types.h>
- #include <graphics/regions.h>
- #include <intuition/intuition.h>
- #include <proto/graphics.h>
- #include <proto/layers.h>
-
- #include <limits.h>
- #include <math.h>
-
- #include "coords.h"
- #include "tracker.h"
-
- extern int _FPERR;
-
- /* Actual structure used */
- struct RWin {
- struct RWindow rw;
- double xmin, xscale, ymin, yscale;
- double xoffset, yoffset;
- struct Region *clip, *oldRegion;
- int lostpos;
- };
-
- /*-------------------------------------------------------------------------*/
- /* RWindow definition */
- /*-------------------------------------------------------------------------*/
-
- /* convert double to integer, round down. cf floor */
- long ftol(double x)
- {
- if (x >= 0) return (long)x;
- else return (long)floor(x);
- }
-
- /* Do Move/Draw style operation func, checking for overflow, etc */
- static void rdo_RWin(struct RWin *this, void (*func)(struct RastPort *rp, long
- sx, long sy), double x, double y)
- {
- double sx, sy;
-
- if (this->lostpos) func = Move;
-
- _FPERR = 0;
- sx = this->rw.sx((struct RWindow *)this, x);
- sy = this->rw.sy((struct RWIndow *)this, y);
- /* Move, Draw only accept shorts */
- this->lostpos = (_FPERR != 0 || fabs(sx) > SHRT_MAX || fabs(sy) > SHRT_MAX)
- ;
-
- if (!this->lostpos) func(this->rw.rp, ftol(sx), ftol(sy));
- }
-
- /* The various conversion routines, to/from ints, for lin orr log scales, x or
- y ax */
- static double sx_lin(struct RWin *this, double x)
- {
- return (x - this->xmin) * this->xscale + this->xoffset;
- }
-
- static double sx_log(struct RWin *this, double x)
- {
- return (log10(x) - this->xmin) * this->xscale + this->xoffset;
- }
-
- static double sy_lin(struct RWin *this, double y)
- {
- return (y - this->ymin) * this->yscale + this->yoffset;
- }
-
- static double sy_log(struct RWin *this, double y)
- {
- return (log10(y) - this->ymin) * this->yscale + this->yoffset;
- }
-
- static double x_lin(struct RWin *this, long sx)
- {
- return (sx - this->xoffset) / this->xscale + this->xmin;
- }
-
- static double x_log(struct RWin *this, long sx)
- {
- return pow(10.0, (sx - this->xoffset) / this->xscale + this->xmin);
- }
-
- static double y_lin(struct RWin *this, long sy)
- {
- return (sy - this->yoffset) / this->yscale + this->ymin;
- }
-
- static double y_log(struct RWin *this, long sy)
- {
- return pow(10.0, (sy - this->yoffset) / this->yscale + this->ymin);
- }
-
- /* Delete a member of this class */
- static void delete_RWin(struct RWin *this)
- {
- if (this->clip)
- {
- InstallClipRegion(this->rw.rp->Layer, this->oldRegion);
- DisposeRegion(this->clip);
- }
- FreeMem(this, sizeof(struct RWin));
- }
-
- /* Create a coordinate system in Rastport rp (w by h pixels),
- {...}offset : offset in rp at which coords starts (normally > 0)
- {x,y}{min,max} : limits for coords
- logx, logy : logarithmic scale ?
- clip : setup clipping to {...}offset boundaries ?
- */
- struct RWindow *new_RWindow(struct RastPort *rp, long w, long h,
- long leftoffset, long bottomoffset, long rightoffse
- t, long topoffset,
- double xmin, double ymin, double xmax, double ymax,
-
- long logx, long logy, long clip)
- {
- long width, height;
- struct Rectangle rect;
- struct Region *r;
- struct RWin *this = AllocMem(sizeof(struct RWin), 0L);
-
- if (this)
- {
- /* Setup class methods, and private data */
- this->rw.delete = (void *)delete_RWin;
- this->rw.rdo = (void *)rdo_RWin;
- /* Setup scaling */
- this->rw.rp = rp;
- this->xoffset = leftoffset;
- this->yoffset = h - bottomoffset - 1;
- width = w - leftoffset - rightoffset - 1;
- height = h - bottomoffset - topoffset - 1;
- if (logx)
- {
- this->xmin = log10(xmin);
- this->xscale = width / (log10(xmax) - this->xmin);
- this->rw.sx = (void *)sx_log;
- this->rw.x = (void *)x_log;
- }
- else
- {
- this->xmin = xmin;
- this->xscale = width / (xmax - this->xmin);
- this->rw.sx = (void *)sx_lin;
- this->rw.x = (void *)x_lin;
- }
- if (logy)
- {
- this->ymin = log10(ymin);
- this->yscale = height / (this->ymin - log10(ymax));
- this->rw.sy = (void *)sy_log;
- this->rw.y = (void *)y_log;
- }
- else
- {
- this->ymin = ymin;
- this->yscale = height / (this->ymin - ymax);
- this->rw.sy = (void *)sy_lin;
- this->rw.y = (void *)y_lin;
- }
-
- if (clip)
- {
- /* Setup clipping */
- if (r = NewRegion())
- {
- rect.MinX = leftoffset;
- rect.MaxX = w - rightoffset - 1;
- rect.MinY = topoffset;
- rect.MaxY = h - bottomoffset - 1;
- if (OrRectRegion(r, &rect))
- {
- this->clip = r;
-
- /* Remark: Due to a bug(?) in InstallClipRegion, make sure that the currently
- installed region when EndRefresh is called is not NULL (trashed windows
- otherwise...). */
- this->oldRegion = InstallClipRegion(rp->Layer, r);
- }
- else
- {
- DisposeRegion(r);
- r = NULL;
- }
- }
- if (!r)
- {
- FreeMem(this, sizeof(struct RWin));
- this = NULL;
- }
- }
- else
- this->clip = NULL;
- }
- /* Return the newly allocated instance */
- return (struct RWindow *)this;
- }
-
-