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 >
C/C++ Source or Header  |  1989-11-20  |  10KB  |  332 lines

  1. /*
  2.  *                 GRAPH, Version 1.00 - 4 August 1989
  3.  *
  4.  *            Copyright 1989, David Gay. All Rights Reserved.
  5.  *            This software is freely redistrubatable.
  6.  */
  7.  
  8. /* The default/non virtual methods for class function */
  9. #include <exec/types.h>
  10. #include <intuition/intuition.h>
  11. #include <graphics/text.h>
  12. #include <math.h>
  13. #include <string.h>
  14.  
  15. #include "object.h"
  16. #include "object/default.h"
  17. #include "object/function.h"
  18. #include "file.h"
  19. #include "graph.h"
  20. #include "uio.h"
  21. #include "coords.h"
  22. #include "list.h"
  23. #include "grph.h"
  24. #include "user/eval.h"
  25. #include "user/gadgets.h"
  26. #include "tracker.h"
  27.  
  28. #include <proto/exec.h>
  29. #include <proto/intuition.h>
  30. #include <proto/graphics.h>
  31.  
  32. /* Draw a function */
  33. void display_function(struct function *this)
  34. {
  35.     int up;
  36.     point *pt;
  37.     struct RWindow *const rwin = this->o.g->io.rw;
  38.     int pen = this->selected ? (this->colour == 3 ? 2 : 3) : this->colour;
  39.  
  40.     up = TRUE;
  41.  
  42.     SetAPen(rwin->rp, pen);
  43.     SetDrMd(rwin->rp, JAM1);
  44.  
  45.     /* Scan points (note that all types of function points have point as base c
  46. lass) */
  47.     for (pt = first(&this->pts); succ(pt); pt = succ(pt))
  48.     {
  49.         if (pt->state & EXISTS)
  50.         {
  51.             if (up) RMove(rwin, pt->x, pt->y);
  52.             else RDraw(rwin, pt->x, pt->y);
  53.             up = this->showdisc && (pt->state & DISC);
  54.         }
  55.         else
  56.             up = TRUE;
  57.     }
  58. }
  59.  
  60. /* Select function, redraw in new colour */
  61. static void select_function(struct function *this)
  62. {
  63.     this->selected = TRUE;
  64.     if (this->o.ok && this->o.g->ok && this->o.g->io.rw && this->calc)
  65.         display_function(this);
  66. }
  67.  
  68. /* Deselect function */
  69. static struct Region *deselect_function(struct function *this)
  70. {
  71.     this->selected = FALSE;
  72.     if (this->o.ok && this->o.g->ok && this->o.g->io.rw && this->calc)
  73.         display_function(this);
  74.     return NULL; /* No refresh needed */
  75. }
  76.  
  77. /* Did user press mouse on function ? */
  78. static int down_function(struct function *this)
  79. {
  80.     int inside = FALSE;
  81.  
  82.     if (this->o.ok && this->calc)
  83.     {
  84.         struct graph *g = this->o.g;
  85.         point *pt;
  86.         long sx = ftol(g->io.rw->sx(g->io.rw, g->s.x));
  87.         long sy = ftol(g->io.rw->sy(g->io.rw, g->s.y));
  88.         long x0, y0, x1, y1;
  89.         int up = TRUE;
  90.  
  91.         /* Check if mouse "near" drawn line */
  92.         for (pt = first(&this->pts); succ(pt); pt = succ(pt))
  93.         {
  94.             if (pt->state & EXISTS)
  95.             {
  96.                 x1 = ftol(g->io.rw->sx(g->io.rw, pt->x));
  97.                 y1 = ftol(g->io.rw->sy(g->io.rw, pt->y));
  98.  
  99.                 if (!up) /* segment exists, calc distance to it */
  100.                 {
  101.                     /* A little vectorial algebra */
  102.                     long ab_x, ab_y, u_x, u_y, h, hd, dist_x, dist_y, dist;
  103.  
  104.                     ab_x = sx - x0; ab_y = sy - y0;
  105.                     u_x = x1 - x0; u_y = y1 - y0;
  106.                     h = (ab_x * u_x + ab_y * u_y);
  107.                     hd = (u_x * u_x + u_y * u_y);
  108.                     if (hd != 0 && 0 <= h && h <= hd) /* intersection on segmen
  109. t */
  110.                     {
  111.                         dist_x = (hd * ab_x - h * u_x) / hd; dist_y = (hd * ab_
  112. y - h * u_y) / hd;
  113.                         dist = dist_x * dist_x + dist_y * dist_y;
  114.                         if (dist < (FDIST * FDIST))
  115.                         {
  116.                             /* We're near segment ! */
  117.                             inside = TRUE;
  118.                             break;
  119.                         }
  120.                     }
  121.                     /* Near point ? */
  122.                     else if ((x1 - sx) * (x1 - sx) + (y1 - sy) * (y1 - sy) <= F
  123. DIST * FDIST)
  124.                     {
  125.                         inside = TRUE;
  126.                         break;
  127.                     }
  128.                 }
  129.  
  130.                 up = this->showdisc && (pt->state & DISC);
  131.                 x0 = x1; y0 = y1;
  132.             }
  133.             else
  134.                 up = TRUE;
  135.  
  136.         }
  137.     }
  138.     return inside;
  139. }
  140.  
  141. /* Impossible ... */
  142. static void move_function(struct function *this)
  143. {
  144. }
  145.  
  146. /* Nothing to do */
  147. static struct Region *up_function(struct function *this)
  148. {
  149.     return NULL;
  150. }
  151.  
  152. /* redraw function, calc if necessary */
  153. static void draw_function(struct function *this, int allow_mes)
  154. {
  155.     if (!this->calc) this->calc = this->calcf(this, allow_mes);
  156.     if (this->calc) display_function(this);
  157. }
  158.  
  159. /* variable name changed. recalc necessary ? */
  160. static void var_change_function(struct function *this, char *name)
  161. {
  162.     if (this->calc && FindName(&this->used, name))
  163.     {
  164.         free_list(&this->pts, this->sizept);
  165.         this->calc = FALSE;
  166.     }
  167. }
  168.  
  169. /* Write function to file */
  170. static int save_function(struct function *this, FILE *f)
  171. {
  172.     short tag = FUNCTION_TAG;
  173.     short end = FUNCTION_END;
  174.     short showdisc = this->showdisc; /* Can't write bitfields directly ... */
  175.     short nicedisc = this->nicedisc;
  176.  
  177.     return WRITE(f, tag) &&
  178.            this->save(this, f) &&    /* Easier than rewriting this for each fun
  179. ction */
  180.            WRITE(f, this->o.name) &&
  181.            WRITE(f, this->vname) &&
  182.            WRITE(f, this->min) &&
  183.            WRITE(f, this->max) &&
  184.            WRITE(f, this->steps) &&
  185.            WRITE(f, this->colour) &&
  186.            WRITE(f, showdisc) &&
  187.            WRITE(f, nicedisc) &&
  188.            WRITE(f, end);
  189. }
  190.  
  191. /* Read a function from a file */
  192. struct function *load_function(struct graph *g, FILE *f)
  193. {
  194.     short tag;
  195.     struct function *this;
  196.  
  197.     if (READ(f, tag)) /* Determine which type of function */
  198.         switch (tag)
  199.         {
  200.             case F_OF_X_TAG:
  201.                 this = (struct function *)load_f_of_x(g, f);
  202.                 break;
  203.             case X_Y_TAG:
  204.                 this = (struct function *)load_x_y(g, f);
  205.                 break;
  206.             case R_OF_T_TAG:
  207.                 this = (struct function *)load_r_of_t(g, f);
  208.                 break;
  209.             case R_T_TAG:
  210.                 this = (struct function *)load_r_t(g, f);
  211.                 break;
  212.             default:
  213.                 message(g, "Not a graph file", (char *)NULL);
  214.         }
  215.     return this;
  216. }
  217.  
  218. /* Read "standard" part of function from file */
  219. int load_rest(struct function *this, FILE *f)
  220. {
  221.     short showdisc, nicedisc, end;
  222.  
  223.     if (READ(f, this->o.name) &&
  224.         READ(f, this->vname) &&
  225.         READ(f, this->min) &&
  226.         READ(f, this->max) &&
  227.         READ(f, this->steps) &&
  228.         READ(f, this->colour) &&
  229.         READ(f, showdisc) && /* Can't read bitfields directly */
  230.         READ(f, nicedisc) &&
  231.         READ(f, end) &&
  232.         end == FUNCTION_END)
  233.     {
  234.         this->showdisc = showdisc;
  235.         this->nicedisc = nicedisc;
  236.         return TRUE;
  237.     }
  238.     return FALSE;
  239. }
  240.  
  241. /* Nothing to do (don't care about resolution) */
  242. static int inform_function(struct function *this)
  243. {
  244.     return TRUE;
  245. }
  246.  
  247. /* idem */
  248. static void confirm_function(struct object *this, int ok)
  249. {
  250. }
  251.  
  252. /* Standard function init */
  253. void init_function(struct function *this, struct graph *g, char *name)
  254. {
  255.     const static struct function def_f =
  256.     {
  257.         {
  258.             { NULL }, NULL, "", FALSE, 0, 0,
  259.             /* Default methods */
  260.             (void *)uncalled, (void *)select_function, (void *)deselect_functio
  261. n,
  262.             (void *)down_function, (void *)move_function, (void *)up_function,
  263.             (void *)uncalled, (void *)draw_function, (void *)ref_uncalled,
  264.             (void *)uncalled, (void *)var_change_function, (void *)save_functio
  265. n,
  266.             (void *)inform_function, (void *)confirm_function
  267.         },
  268.         (void *)uncalled, (void *)uncalled,
  269.         "", NOVAL, NOVAL, INOVAL,
  270.         1, TRUE, TRUE, FALSE, FALSE
  271.     };
  272.  
  273.     *this = def_f;
  274.     this->o.g = g;
  275.     strcpy(this->o.name, name);
  276.     init_var_list(&this->used);
  277. }
  278.  
  279. /* Create a new function (ask user which type he wants) */
  280. struct function *new_function(struct graph *g)
  281. {
  282.     struct Requester *req;
  283.     struct Memory *m;
  284.     struct Gadget *gl = NULL, *fx, *xy, *rt, *r2;
  285.     char name[FNAMELEN];
  286.     int ret = FALSE;
  287.     struct function *o = NULL;
  288.  
  289.     name[0] = '\0';
  290.  
  291.     if ((m = NewMemory()) &&
  292.         (req = InitReq(50, 20, 230, 105, m)) &&
  293.         SetReqBorder(req, 1, m) &&
  294.         AddIntuiText(&req->ReqText, "Add Function", 67, 6, m) &&
  295.         AddText(&gl, 0, "Name ", FALSE, name, FNAMELEN, TRUE, 0, RELVERIFY, 51,
  296.  20, 100, 10, TRUE, m) &&
  297.         (fx = AddRadio(&gl, 0, "f(x)", TRUE, SELECTED, RELVERIFY, 28, 11, 40, 1
  298. 0, 10, m)) &&
  299.         (rt = AddRadio(&gl, 0, "r(theta)", TRUE, 0, RELVERIFY, 26, 105, 40, 10,
  300.  10, m)) &&
  301.         (xy = AddRadio(&gl, 0, "x(t),y(t)", TRUE, 0, RELVERIFY, 22, 11, 60, 10,
  302.  10, m)) &&
  303.         (r2 = AddRadio(&gl, 0, "r(t),theta(t)", TRUE, 0, RELVERIFY, 14, 105, 60
  304. , 10, 10, m)) &&
  305.         AddBox(&gl, TRUE, "Ok", 0, RELVERIFY | ENDGADGET, 25, 80, 65, 15, FALSE
  306. , m) &&
  307.         AddBox(&gl, FALSE, "Cancel", 0, RELVERIFY | ENDGADGET, 140, 80, 65, 15,
  308.  FALSE, m))
  309.     {
  310.         SetReqGadgets(req, gl);
  311.         if (ret = DoRequest(req, g, std_ghandler))
  312.         {
  313.             strip(name);
  314.             if (*name)
  315.             {
  316.                 if (fx->Flags & SELECTED) o = (struct function *)new_f_of_x(g,
  317. name);
  318.                 else if (xy->Flags & SELECTED) o = (struct function *)new_x_y(g
  319. , name);
  320.                 else if (rt->Flags & SELECTED) o = (struct function *)new_r_of_
  321. t(g, name);
  322.                 else o = (struct function *)new_r_t(g, name);
  323.             }
  324.             else
  325.                 message(g, "Blank names not allowed", (char *)NULL);
  326.         }
  327.     }
  328.     Free(m);
  329.     return o;
  330. }
  331.  
  332.