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
/
object
/
function.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-20
|
10KB
|
332 lines
/*
* GRAPH, Version 1.00 - 4 August 1989
*
* Copyright 1989, David Gay. All Rights Reserved.
* This software is freely redistrubatable.
*/
/* The default/non virtual methods for class function */
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <math.h>
#include <string.h>
#include "object.h"
#include "object/default.h"
#include "object/function.h"
#include "file.h"
#include "graph.h"
#include "uio.h"
#include "coords.h"
#include "list.h"
#include "grph.h"
#include "user/eval.h"
#include "user/gadgets.h"
#include "tracker.h"
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
/* Draw a function */
void display_function(struct function *this)
{
int up;
point *pt;
struct RWindow *const rwin = this->o.g->io.rw;
int pen = this->selected ? (this->colour == 3 ? 2 : 3) : this->colour;
up = TRUE;
SetAPen(rwin->rp, pen);
SetDrMd(rwin->rp, JAM1);
/* Scan points (note that all types of function points have point as base c
lass) */
for (pt = first(&this->pts); succ(pt); pt = succ(pt))
{
if (pt->state & EXISTS)
{
if (up) RMove(rwin, pt->x, pt->y);
else RDraw(rwin, pt->x, pt->y);
up = this->showdisc && (pt->state & DISC);
}
else
up = TRUE;
}
}
/* Select function, redraw in new colour */
static void select_function(struct function *this)
{
this->selected = TRUE;
if (this->o.ok && this->o.g->ok && this->o.g->io.rw && this->calc)
display_function(this);
}
/* Deselect function */
static struct Region *deselect_function(struct function *this)
{
this->selected = FALSE;
if (this->o.ok && this->o.g->ok && this->o.g->io.rw && this->calc)
display_function(this);
return NULL; /* No refresh needed */
}
/* Did user press mouse on function ? */
static int down_function(struct function *this)
{
int inside = FALSE;
if (this->o.ok && this->calc)
{
struct graph *g = this->o.g;
point *pt;
long sx = ftol(g->io.rw->sx(g->io.rw, g->s.x));
long sy = ftol(g->io.rw->sy(g->io.rw, g->s.y));
long x0, y0, x1, y1;
int up = TRUE;
/* Check if mouse "near" drawn line */
for (pt = first(&this->pts); succ(pt); pt = succ(pt))
{
if (pt->state & EXISTS)
{
x1 = ftol(g->io.rw->sx(g->io.rw, pt->x));
y1 = ftol(g->io.rw->sy(g->io.rw, pt->y));
if (!up) /* segment exists, calc distance to it */
{
/* A little vectorial algebra */
long ab_x, ab_y, u_x, u_y, h, hd, dist_x, dist_y, dist;
ab_x = sx - x0; ab_y = sy - y0;
u_x = x1 - x0; u_y = y1 - y0;
h = (ab_x * u_x + ab_y * u_y);
hd = (u_x * u_x + u_y * u_y);
if (hd != 0 && 0 <= h && h <= hd) /* intersection on segmen
t */
{
dist_x = (hd * ab_x - h * u_x) / hd; dist_y = (hd * ab_
y - h * u_y) / hd;
dist = dist_x * dist_x + dist_y * dist_y;
if (dist < (FDIST * FDIST))
{
/* We're near segment ! */
inside = TRUE;
break;
}
}
/* Near point ? */
else if ((x1 - sx) * (x1 - sx) + (y1 - sy) * (y1 - sy) <= F
DIST * FDIST)
{
inside = TRUE;
break;
}
}
up = this->showdisc && (pt->state & DISC);
x0 = x1; y0 = y1;
}
else
up = TRUE;
}
}
return inside;
}
/* Impossible ... */
static void move_function(struct function *this)
{
}
/* Nothing to do */
static struct Region *up_function(struct function *this)
{
return NULL;
}
/* redraw function, calc if necessary */
static void draw_function(struct function *this, int allow_mes)
{
if (!this->calc) this->calc = this->calcf(this, allow_mes);
if (this->calc) display_function(this);
}
/* variable name changed. recalc necessary ? */
static void var_change_function(struct function *this, char *name)
{
if (this->calc && FindName(&this->used, name))
{
free_list(&this->pts, this->sizept);
this->calc = FALSE;
}
}
/* Write function to file */
static int save_function(struct function *this, FILE *f)
{
short tag = FUNCTION_TAG;
short end = FUNCTION_END;
short showdisc = this->showdisc; /* Can't write bitfields directly ... */
short nicedisc = this->nicedisc;
return WRITE(f, tag) &&
this->save(this, f) && /* Easier than rewriting this for each fun
ction */
WRITE(f, this->o.name) &&
WRITE(f, this->vname) &&
WRITE(f, this->min) &&
WRITE(f, this->max) &&
WRITE(f, this->steps) &&
WRITE(f, this->colour) &&
WRITE(f, showdisc) &&
WRITE(f, nicedisc) &&
WRITE(f, end);
}
/* Read a function from a file */
struct function *load_function(struct graph *g, FILE *f)
{
short tag;
struct function *this;
if (READ(f, tag)) /* Determine which type of function */
switch (tag)
{
case F_OF_X_TAG:
this = (struct function *)load_f_of_x(g, f);
break;
case X_Y_TAG:
this = (struct function *)load_x_y(g, f);
break;
case R_OF_T_TAG:
this = (struct function *)load_r_of_t(g, f);
break;
case R_T_TAG:
this = (struct function *)load_r_t(g, f);
break;
default:
message(g, "Not a graph file", (char *)NULL);
}
return this;
}
/* Read "standard" part of function from file */
int load_rest(struct function *this, FILE *f)
{
short showdisc, nicedisc, end;
if (READ(f, this->o.name) &&
READ(f, this->vname) &&
READ(f, this->min) &&
READ(f, this->max) &&
READ(f, this->steps) &&
READ(f, this->colour) &&
READ(f, showdisc) && /* Can't read bitfields directly */
READ(f, nicedisc) &&
READ(f, end) &&
end == FUNCTION_END)
{
this->showdisc = showdisc;
this->nicedisc = nicedisc;
return TRUE;
}
return FALSE;
}
/* Nothing to do (don't care about resolution) */
static int inform_function(struct function *this)
{
return TRUE;
}
/* idem */
static void confirm_function(struct object *this, int ok)
{
}
/* Standard function init */
void init_function(struct function *this, struct graph *g, char *name)
{
const static struct function def_f =
{
{
{ NULL }, NULL, "", FALSE, 0, 0,
/* Default methods */
(void *)uncalled, (void *)select_function, (void *)deselect_functio
n,
(void *)down_function, (void *)move_function, (void *)up_function,
(void *)uncalled, (void *)draw_function, (void *)ref_uncalled,
(void *)uncalled, (void *)var_change_function, (void *)save_functio
n,
(void *)inform_function, (void *)confirm_function
},
(void *)uncalled, (void *)uncalled,
"", NOVAL, NOVAL, INOVAL,
1, TRUE, TRUE, FALSE, FALSE
};
*this = def_f;
this->o.g = g;
strcpy(this->o.name, name);
init_var_list(&this->used);
}
/* Create a new function (ask user which type he wants) */
struct function *new_function(struct graph *g)
{
struct Requester *req;
struct Memory *m;
struct Gadget *gl = NULL, *fx, *xy, *rt, *r2;
char name[FNAMELEN];
int ret = FALSE;
struct function *o = NULL;
name[0] = '\0';
if ((m = NewMemory()) &&
(req = InitReq(50, 20, 230, 105, m)) &&
SetReqBorder(req, 1, m) &&
AddIntuiText(&req->ReqText, "Add Function", 67, 6, m) &&
AddText(&gl, 0, "Name ", FALSE, name, FNAMELEN, TRUE, 0, RELVERIFY, 51,
20, 100, 10, TRUE, m) &&
(fx = AddRadio(&gl, 0, "f(x)", TRUE, SELECTED, RELVERIFY, 28, 11, 40, 1
0, 10, m)) &&
(rt = AddRadio(&gl, 0, "r(theta)", TRUE, 0, RELVERIFY, 26, 105, 40, 10,
10, m)) &&
(xy = AddRadio(&gl, 0, "x(t),y(t)", TRUE, 0, RELVERIFY, 22, 11, 60, 10,
10, m)) &&
(r2 = AddRadio(&gl, 0, "r(t),theta(t)", TRUE, 0, RELVERIFY, 14, 105, 60
, 10, 10, m)) &&
AddBox(&gl, TRUE, "Ok", 0, RELVERIFY | ENDGADGET, 25, 80, 65, 15, FALSE
, m) &&
AddBox(&gl, FALSE, "Cancel", 0, RELVERIFY | ENDGADGET, 140, 80, 65, 15,
FALSE, m))
{
SetReqGadgets(req, gl);
if (ret = DoRequest(req, g, std_ghandler))
{
strip(name);
if (*name)
{
if (fx->Flags & SELECTED) o = (struct function *)new_f_of_x(g,
name);
else if (xy->Flags & SELECTED) o = (struct function *)new_x_y(g
, name);
else if (rt->Flags & SELECTED) o = (struct function *)new_r_of_
t(g, name);
else o = (struct function *)new_r_t(g, name);
}
else
message(g, "Blank names not allowed", (char *)NULL);
}
}
Free(m);
return o;
}