home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff280.lzh
/
Graph
/
coords.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-20
|
6KB
|
210 lines
/*
* 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;
}