source: trunk/Jgraph/process.c @ 420

Last change on this file since 420 was 420, checked in by Nicholas Riley, 12 years ago

Jgraph: my changes - ANSIfication, few minor bug fixes; works on OS X 10.5 now

File size: 23.3 KB
Line 
1/*
2 * $Source: /tmp_mnt/n/fs/grad1/jsp/src/jgraph/RCS/process.c,v $
3 * $Revision: 8.3 $
4 * $Date: 92/11/30 11:42:35 $
5 * $Author: jsp $
6 */
7
8#include <stdio.h>
9#include <math.h>
10#include <string.h>
11
12#include "jgraph.h"
13
14#define ABS(a) ((a > 0.0) ? (a) : (-a))
15#define MAX(a, b) ((a > b) ? (a) : (b))
16#define MIN(a, b) ((a < b) ? (a) : (b))
17#define AXIS_CHAR(a) ((a->is_x) ? 'x' : 'y')
18#define HASH_DIR(a) ((a->hash_scale > 0.0) ? 1 : -1)
19
20static double Pi;
21
22void process_label(Label l, Graph g, int adjust);
23
24void process_title(Graph g)
25{
26
27  float ytitleloc;
28
29  if (g->title->x == FSIG) g->title->x = g->x_axis->psize / 2.0;
30    else g->title->x = ctop(g->title->x, g->x_axis);
31  if (g->title->y != FSIG) g->title->y = ctop(g->title->y, g->y_axis);
32  else {
33    ytitleloc = 0.0;
34    if (g->x_axis->draw_axis_label && g->x_axis->label->label != CNULL) 
35      ytitleloc = MIN(ytitleloc, g->x_axis->label->ymin); 
36    if (g->x_axis->draw_hash_labels)
37      ytitleloc = MIN(ytitleloc, g->x_axis->hl->ymin);
38    if (g->x_axis->draw_hash_marks)
39      ytitleloc = MIN(ytitleloc, g->x_axis->draw_hash_marks_at - HASH_SIZE);
40    if (g->legend->type == 'u')
41      ytitleloc = MIN(ytitleloc, g->legend->l->ymin);
42   
43    g->title->y = ytitleloc - 10.0;
44  }
45  process_label(g->title, g, 0);
46}
47
48void process_label_max_n_mins(Label l, float len, float height)
49{
50  float xlen, ylen, xheight, yheight;
51  float x, y;
52
53  xlen = len * cos(l->rotate * Pi / 180.00);
54  ylen = height * cos((l->rotate + 90.0) * Pi / 180.00);
55  xheight = len * sin(l->rotate * Pi / 180.00);
56  yheight = height * sin((l->rotate + 90.0) * Pi / 180.00);
57 
58  x = l->x;
59  y = l->y;
60
61  if (l->hj == 'c') {
62    x -= xlen / 2.0;
63    y -= xheight / 2.0;
64  } else if (l->hj == 'r') {
65    x -= xlen;
66    y -= xheight;
67  }
68  if (l->vj == 'c') {
69    x -= ylen / 2.0;
70    y -= yheight / 2.0;
71  } else if (l->vj == 't') {
72    x -= ylen;
73    y -= yheight;
74  }
75
76  l->xmin = MIN(x, x + xlen);
77  l->xmin = MIN(l->xmin, x + xlen + ylen);
78  l->xmin = MIN(l->xmin, x + ylen);
79
80  l->ymin = MIN(y, y + xheight);
81  l->ymin = MIN(l->ymin, y + yheight);
82  l->ymin = MIN(l->ymin, y + xheight + yheight);
83
84  l->xmax = MAX(x, x + xlen);
85  l->xmax = MAX(l->xmax, x + xlen + ylen);
86  l->xmax = MAX(l->xmax, x + ylen);
87
88  l->ymax = MAX(y, y + xheight);
89  l->ymax = MAX(l->ymax, y + yheight);
90  l->ymax = MAX(l->ymax, y + xheight + yheight);
91
92}
93
94void process_legend(Graph g)
95{
96  Legend l;
97  int anything;
98  float height, hdist, y, x, width, maxmark, maxmarky;
99  Curve c;
100  char *s;
101
102  l = g->legend;
103  if (l->type == 'n') return;
104  if (l->l->linesep == FSIG) l->l->linesep = l->l->fontsize;
105  l->anylines = 0;
106  maxmark = 0.0;
107  maxmarky = 0.0;
108  anything = 0;
109  for (c = first(g->curves); c != nil(g->curves); c = next(c)) {
110    if (c->l->label != CNULL) {
111      anything = 1;
112      if (c->marktype == 'l') {
113         maxmark = MAX(maxmark, c->lmark->xmax - c->lmark->xmin); 
114         maxmarky = MAX(maxmarky, c->lmark->ymax - c->lmark->ymin); 
115      } else if (c->marktype != 'n') {
116        maxmark = MAX(maxmark, ABS(c->marksize[0]));
117        maxmarky = MAX(maxmarky, ABS(c->marksize[1]));
118      }
119      if (c->linetype != '0') l->anylines = 1;
120    }
121  }
122  if (l->linelength == FSIG)
123    l->linelength = (l->anylines) ? (MAX(maxmark + 6.0, 24.0)) : 0.0;
124    else l->linelength = disttop(l->linelength, g->x_axis);
125  if (l->midspace == FSIG)
126    l->midspace = (l->anylines) ? 4.0 : (maxmark / 2.0) + 4.0;
127    else l->midspace = disttop(l->midspace, g->x_axis);
128  if (l->linebreak == FSIG)
129    l->linebreak = MAX(l->l->linesep * FCPI / FPPI, maxmarky);
130    else l->linebreak = disttop(l->linebreak, g->y_axis);
131
132  if (l->type == 'c') {
133    for (c = first(g->curves); c != nil(g->curves); c = next(c)) {
134      if (c->l->label != CNULL) process_label(c->l, g, 1);
135    }
136    return;
137  }
138
139  if (!anything) {
140    l->anylines = -1; 
141    return;
142  }
143
144  width = 0.0;
145  height = -l->linebreak;
146  for (c = first(g->curves); c != nil(g->curves); c = next(c)) {
147    if (c->l->label != CNULL) {
148      s = c->l->label;
149      copy_label(c->l, l->l);
150      c->l->x = 0.0;
151      c->l->y = 0.0;
152      c->l->rotate = 0.0;
153      c->l->hj = 'l';
154      c->l->vj = 'b';
155      c->l->label = s;
156      process_label(c->l, g, 0);
157      height += c->l->ymax + l->linebreak;
158      width = MAX(width, c->l->xmax);
159    }
160  }
161  hdist = (l->anylines) ? l->midspace + l->linelength : l->midspace;
162  width += hdist;
163
164  if (l->l->x == FSIG) {
165    if (l->l->hj == 'c') {
166      l->l->x = g->x_axis->psize / 2;
167    } else if (l->l->hj == 'l') {
168      if (l->l->vj == 'c') {
169        l->l->x = g->x_axis->psize;
170        if (g->y_axis->draw_axis_label) 
171          l->l->x = MAX(l->l->x, g->y_axis->label->xmax);
172        if (g->y_axis->draw_hash_labels) 
173          l->l->x = MAX(l->l->x, g->y_axis->hl->xmax);
174        if (g->y_axis->draw_hash_marks) {
175          l->l->x = MAX(l->l->x, g->y_axis->draw_hash_marks_at);
176          l->l->x = MAX(l->l->x, g->y_axis->draw_hash_marks_at + 
177                                 HASH_DIR(g->y_axis) * HASH_SIZE);
178        }
179        l->l->x += 15.0;
180      } else {
181        l->l->x = 0.0;
182      }
183    } else {
184      if (l->l->vj == 'c') {
185        l->l->x = 0.0;
186        if (g->y_axis->draw_axis_label) 
187          l->l->x = MIN(l->l->x, g->y_axis->label->xmin);
188        if (g->y_axis->draw_hash_labels) 
189          l->l->x = MIN(l->l->x, g->y_axis->hl->xmin);
190        if (g->y_axis->draw_hash_marks) {
191          l->l->x = MIN(l->l->x, g->y_axis->draw_hash_marks_at);
192          l->l->x = MIN(l->l->x, g->y_axis->draw_hash_marks_at + 
193                                 HASH_DIR(g->y_axis) * HASH_SIZE);
194        }
195        l->l->x = l->l->x - 15.0;
196      } else {
197        l->l->x = g->x_axis->psize;
198      }
199    }
200  } else {
201    l->l->x = ctop(l->l->x, g->x_axis);
202  }
203  if (l->l->y == FSIG) {
204    if (l->l->vj == 'c') {
205      l->l->y = g->y_axis->psize / 2.0;
206    } else if (l->l->vj == 'b') {
207      l->l->y = g->y_axis->psize;
208      if (g->x_axis->draw_axis_label) 
209        l->l->y = MAX(l->l->y, g->x_axis->label->ymax);
210      if (g->x_axis->draw_hash_labels) 
211        l->l->y = MAX(l->l->y, g->x_axis->hl->ymax);
212      if (g->x_axis->draw_hash_marks) {
213        l->l->y = MAX(l->l->y, g->x_axis->draw_hash_marks_at);
214        l->l->y = MAX(l->l->y, g->x_axis->draw_hash_marks_at + 
215                               HASH_DIR(g->x_axis) * HASH_SIZE);
216      }
217      l->l->y += 15.0;
218    } else {
219      l->l->y = 0.0;
220      if (g->x_axis->draw_axis_label) 
221        l->l->y = MIN(l->l->y, g->x_axis->label->ymin);
222      if (g->x_axis->draw_hash_labels) 
223        l->l->y = MIN(l->l->y, g->x_axis->hl->ymin);
224      if (g->x_axis->draw_hash_marks) {
225        l->l->y = MIN(l->l->y, g->x_axis->draw_hash_marks_at);
226        l->l->y = MIN(l->l->y, g->x_axis->draw_hash_marks_at + 
227                               HASH_DIR(g->x_axis) * HASH_SIZE);
228      }
229      l->l->y -= 15.0;
230    }
231  } else {
232    l->l->y = ctop(l->l->y, g->y_axis);
233  }
234
235  if (l->l->hj == 'l') x = 0.0;
236  else if (l->l->hj == 'c') x = - width/2.0;
237  else x = -width;
238
239  if (l->l->vj == 't') y = 0.0;
240  else if (l->l->vj == 'c') y = height / 2.0;
241  else y = height;
242
243  for (c = first(g->curves); c != nil(g->curves); c = next(c)) {
244    if (c->l->label != CNULL) {
245      c->l->x = hdist + x;
246      c->l->y = y;
247      c->l->vj = 't';
248      c->l->hj = 'l';
249      c->l->rotate = 0.0;
250      process_label(c->l, g, 0);
251      y = c->l->ymin - l->linebreak;
252    }
253  }
254 
255  process_label_max_n_mins(l->l, width, height);
256}
257
258float find_reasonable_hash_interval(Axis a)
259{
260  float s, d;
261
262  if (a->is_lg) return 0.0;
263  s = a->max - a->min;
264  d = 1.0;
265  if (s > 5.0) {
266    while(1) {
267      if (s / d < 6.0) return d;
268      d *= 2.0;
269      if (s / d < 6.0) return d;
270      d *= 2.5;
271      if (s / d < 6.0) return d;
272      d *= 2.0;
273    }
274  } else {
275    while(1) {
276      if (s / d > 2.0) return d;
277      d /= 2.0;
278      if (s / d > 2.0) return d;
279      d /= 2.5;
280      if (s / d > 2.0) return d;
281      d /= 2.0;
282    }
283  }
284}
285
286float find_reasonable_hash_start(Axis a)
287{
288  int i;
289 
290  if (a->is_lg) return 0.0;
291  if (a->max > 0.0 && a->min < 0.0) return 0.0;
292  i = ((int) (a->min / a->hash_interval));
293  return ((float) i) * a->hash_interval;
294}
295
296int find_reasonable_precision(Axis a)
297{
298  int i, b, b2, done;
299  float x, x2, tolerance;
300
301  if (a->hash_format == 'g' || a->hash_format == 'G') return 6;
302  if (a->hash_format == 'e' || a->hash_format == 'E') return 0;
303  if (a->is_lg) return 0;
304
305  tolerance = 0.000001;
306  b = 0;
307  x = a->hash_interval;
308
309  done = 0;
310  while(b < 6 && !done) {
311    i = (int) (x + 0.4);
312    x2 = i;
313    if (x2 - x < tolerance && x - x2 < tolerance) done = 1;
314    else {
315      b++;
316      x *= 10.0;
317      tolerance *= 10.0;
318    }
319  }
320
321  tolerance = 0.000001;
322  b2 = 0;
323  x = a->hash_start;
324
325  done = 0;
326  while(b2 < 6 && !done) {
327    i = (int) (x + 0.4);
328    x2 = i;
329    if (x2 - x < tolerance && x - x2 < tolerance) done = 1;
330    else {
331      b2++;
332      x *= 10.0;
333      tolerance *= 10.0;
334    }
335  }
336  return MAX(b, b2);
337}
338
339int find_reasonable_minor_hashes(Axis a)
340{
341  float d; 
342  int i;
343 
344  if (a->is_lg) {
345    d = a->log_base;
346    while(d > 10.0) d /= 10.0;
347    while(d <= 1.0) d *= 10.0;
348    i = (int) d;
349    return MAX((i - 2), 0);
350  } else {
351    d = a->hash_interval;
352    if (d == 0.0) return 0;
353    while(d > 10.0) d /= 10.0;
354    while(d <= 1.0) d *= 10.0;
355    i = (int) d;
356    if (((float) i) != d) return 0;
357    return i-1;
358  }
359}
360
361void process_axis1(Axis a, Graph g)
362{
363  float tmp;
364  int i;
365
366  if (a->min == FSIG) {
367    if (a->pmin == FSIG) {
368      error_header();
369      fprintf(stderr, 
370              "Graph %d: %c axis has no minimum, and cannot derive one\n",
371              g->num, AXIS_CHAR(a));
372      fprintf(stderr, "  Use %caxis min\n", AXIS_CHAR(a));
373      exit(1);
374    } else if (a->pmin <= 0.0 && a->is_lg) {
375      error_header();
376      fprintf(stderr, "Trying to derive %c axis\n", AXIS_CHAR(a));
377      fprintf(stderr, 
378        "        Minimum value %f will be -infinity with log axes\n", a->pmin);
379      exit(1);
380    } else a->min = a->pmin;
381  }
382  if (a->max == FSIG) {
383    if (a->pmax == FSIG) {
384      error_header();
385      fprintf(stderr, 
386              "Graph %d: %c axis has no maximum, and cannot derive one\n",
387              g->num, AXIS_CHAR(a));
388      fprintf(stderr, "  Use %caxis max\n", AXIS_CHAR(a));
389      exit(1);
390    } else if (a->pmax <= 0.0 && a->is_lg) {
391      error_header();
392      fprintf(stderr, "Trying to derive %c axis\n", AXIS_CHAR(a));
393      fprintf(stderr, 
394        "        Maximum value %f will be -infinity with log axes\n", a->pmax);
395      exit(1);
396    } else a->max = a->pmax;
397  }
398  if (a->max < a->min) {
399    tmp = a->max;  a->max = a->min;  a->min = tmp;
400  } else if (a->max == a->min) {
401    if (!a->is_lg) a->min -= 1;
402    a->max += 1;
403  }
404  a->psize = intop(a->size);
405  if (a->is_lg) {
406    if (a->min <= 0.0) {
407      error_header();
408      fprintf(stderr, 
409        "Graph %d, %c axis: Min value = %f.  This is -infinity with logrhythmic axes\n", 
410        g->num, (a->is_x) ? 'x' : 'y', a->min);
411      exit(1);
412    }
413    a->logfactor = log(a->log_base);
414    a->logmin = log(a->min) / a->logfactor;
415    a->factor = a->psize / (log(a->max) / a->logfactor - a->logmin);
416  } else {
417    a->factor = a->psize / (a->max - a->min);
418  }
419  if (a->gr_graytype == '0') {
420    a->gr_graytype = a->graytype;
421    for (i = 0; i < 3; i++) a->gr_gray[i] = a->gray[i];
422  }
423  if (a->mgr_graytype == '0') {
424    a->mgr_graytype = a->gr_graytype;
425    for (i = 0; i < 3; i++) a->mgr_gray[i] = a->gr_gray[i];
426  }
427}
428
429void process_axis2(Axis a, Graph g)
430{
431  float t1, t2, t3, minor_hashes, hloc, tmp;
432  float ymin, ymax, xmin, xmax;
433  int prec, i1;
434  Hash h;
435  String s;
436  Axis other;
437
438  other = (a->is_x) ? g->y_axis : g->x_axis;
439  if (a->draw_at == FSIG) 
440    a->draw_at = (HASH_DIR(a) == -1) ? 0.0 : other->psize;
441  else a->draw_at = ctop(a->draw_at, other);
442
443  if (a->hash_interval < 0.0) {
444    a->hash_interval = find_reasonable_hash_interval(a);
445    if (!a->start_given)
446      a->hash_start = find_reasonable_hash_start(a);
447  } else if (!a->start_given) a->hash_start = a->min;
448  if (a->minor_hashes < 0) {
449    a->minor_hashes = find_reasonable_minor_hashes(a);
450  }
451  if (a->precision < 0) a->precision = find_reasonable_precision(a);
452
453  for (h = first(a->hash_lines) ; h != nil(a->hash_lines); h = next(h)) {
454    h->loc = ctop(h->loc, a);
455  }
456 
457  for (s = first(a->hash_labels); s != nil(a->hash_labels); s = next(s)) {
458    s->s->x = ctop(s->s->x, a);
459    s->s->y = ctop(s->s->y, a);
460  }
461
462  if (((a->hash_interval != 0.0 && !a->is_lg) || a->is_lg) && a->auto_hash_marks) {
463    if (a->is_lg) {
464      for (t1 = 1.0; t1 > a->min; t1 /= a->log_base) ;
465      t2 = t1 * a->log_base - t1;
466    } else {
467      for (t1 = a->hash_start; t1 > a->min; t1 -= a->hash_interval) ;
468      t2 = a->hash_interval;
469    }
470    while (t1 <= a->max) {
471      hloc = ctop(t1, a);
472      if (hloc > -.05 && hloc < a->psize + .05) {
473        h = (Hash) get_node(a->hash_lines);
474        h->loc = hloc;
475        h->size = HASH_SIZE;
476        h->major = 1;
477        insert(h, a->hash_lines);
478        if (a->auto_hash_labels) {
479          s = (String) get_node (a->hash_labels);
480          s->s = new_label();
481          s->s->x = hloc;
482          s->s->y = hloc;
483          s->s->label = (char *) malloc (80);
484          if (a->precision >= 0) {
485            prec = a->precision;
486          } else {
487            if (ABS(t1) >= 1.0 || t1 == 0.0) prec = 0;
488            else {
489              tmp = ABS(t1);
490              prec = -1;
491              while(tmp < 1.0) {tmp *= 10.0; prec++;}
492            }
493          }
494          switch(a->hash_format) {
495            case 'G': sprintf(s->s->label, "%.*G", prec, t1); break;
496            case 'g': sprintf(s->s->label, "%.*g", prec, t1); break;
497            case 'E': sprintf(s->s->label, "%.*E", prec, t1); break;
498            case 'e': sprintf(s->s->label, "%.*e", prec, t1); break;
499            case 'f': sprintf(s->s->label, "%.*f", prec, t1); break;
500            default: fprintf(stderr, "Internal jgraph error: hl_st\n");
501                     exit(1);
502          }
503          insert(s, a->hash_labels);
504        }
505      }
506      minor_hashes = t2 / ((float) (a->minor_hashes + 1));
507      t3 = t1;
508      for (i1 = 1; i1 <= a->minor_hashes; i1++) {
509        t3 += minor_hashes;
510        hloc = ctop(t3, a);
511        if (hloc > -.05 && hloc < a->psize + .05) {
512          h = (Hash) get_node(a->hash_lines);
513          h->loc = hloc;
514          h->size = MHASH_SIZE;
515          h->major = 0;
516          insert(h, a->hash_lines);
517        }
518      }
519      if (a->is_lg) {
520        t1 *= a->log_base;
521        t2 = t1 * a->log_base - t1;
522      } else t1 += t2;
523    }
524  }
525
526  if (a->draw_hash_marks_at == FSIG)
527    a->draw_hash_marks_at = a->draw_at;
528  else a->draw_hash_marks_at = ctop(a->draw_hash_marks_at, other);
529  if (a->draw_hash_labels_at == FSIG)
530    a->draw_hash_labels_at = a->draw_hash_marks_at +
531      a->hash_scale * HASH_SIZE + HASH_DIR(a) * 3.0;
532  else a->draw_hash_labels_at = ctop(a->draw_hash_labels_at, other);
533
534  if (a->is_x) {
535    a->hl->y = a->draw_hash_labels_at; 
536    if (a->hl->hj == '0')
537      a->hl->hj = 'c';
538    if (a->hl->vj == '0')
539      a->hl->vj = (HASH_DIR(a) == -1) ? 't' : 'b';
540  } else {
541    a->hl->x = a->draw_hash_labels_at;
542    if (a->hl->vj == '0') a->hl->vj = 'c';
543    if (a->hl->hj == '0')
544      a->hl->hj = (HASH_DIR(a) == -1) ? 'r' : 'l';
545  }
546
547  ymin = (a->is_x) ? a->hl->y : 0;
548  ymax = (a->is_x) ? a->hl->y : a->psize;
549  xmin = (!a->is_x) ? a->hl->x : 0;
550  xmax = (!a->is_x) ? a->hl->x : a->psize;
551
552  for (s = first(a->hash_labels); s != nil(a->hash_labels); s = next(s)) {
553    if (a->is_x) a->hl->x = s->s->x; else a->hl->y = s->s->y;
554    a->hl->label = s->s->label;
555    process_label(a->hl, g, 0);
556    xmin = MIN(a->hl->xmin, xmin);
557    ymin = MIN(a->hl->ymin, ymin);
558    xmax = MAX(a->hl->xmax, xmax);
559    ymax = MAX(a->hl->ymax, ymax);
560  }
561  a->hl->xmin = xmin;
562  a->hl->ymin = ymin;
563  a->hl->xmax = xmax;
564  a->hl->ymax = ymax;
565
566  /* HERE -- now either test or continue */
567
568  if (a->is_x) {
569    if (a->label->x == FSIG) 
570      a->label->x = a->psize / 2.0;
571      else a->label->x = ctop(a->label->x, g->x_axis);
572    if (a->label->y == FSIG) {
573      ymin = 0.0;
574      ymax = other->psize;
575      if (a->draw_hash_labels) {
576        ymin = MIN(ymin, a->hl->ymin); 
577        ymax = MAX(ymax, a->hl->ymax); 
578      } 
579      if (a->draw_hash_marks) {
580        ymin = MIN(ymin, a->draw_hash_marks_at);
581        ymin = MIN(ymin, a->draw_hash_marks_at + a->hash_scale * HASH_SIZE);
582        ymax = MAX(ymax, a->draw_hash_marks_at);
583        ymax = MAX(ymax, a->draw_hash_marks_at + a->hash_scale * HASH_SIZE);
584      } 
585      a->label->y = (HASH_DIR(a) == -1) ? ymin - 8.0 : ymax + 8.0 ;
586    } else a->label->y = ctop(a->label->y, g->y_axis);
587    if (a->label->hj == '0') a->label->hj = 'c';
588    if (a->label->vj == '0') a->label->vj = (HASH_DIR(a) == -1) ? 't' : 'b' ;
589    if (a->label->rotate == FSIG) a->label->rotate = 0.0;
590  } else {
591    if (a->label->y == FSIG) 
592      a->label->y = a->psize / 2.0;
593      else a->label->y = ctop(a->label->y, g->y_axis);
594    if (a->label->x == FSIG) {
595      xmin = 0.0;
596      xmax = other->psize;
597      if (a->draw_hash_labels) {
598        xmin = MIN(xmin, a->hl->xmin); 
599        xmax = MAX(xmax, a->hl->xmax); 
600      } 
601      if (a->draw_hash_marks) {
602        xmin = MIN(xmin, a->draw_hash_marks_at);
603        xmin = MIN(xmin, a->draw_hash_marks_at + a->hash_scale * HASH_SIZE);
604        xmax = MAX(xmax, a->draw_hash_marks_at);
605        xmax = MAX(xmax, a->draw_hash_marks_at + a->hash_scale * HASH_SIZE);
606      } 
607      a->label->x = (HASH_DIR(a) == -1) ? xmin - 8.0 : xmax + 8.0 ;
608    } else a->label->x = ctop(a->label->x, g->x_axis);
609    if (a->label->hj == '0') a->label->hj = 'c';
610    if (a->label->vj == '0') a->label->vj = 'b';
611    if (a->label->rotate == FSIG) 
612      a->label->rotate = (HASH_DIR(a) == -1) ? 90.0 : -90.0;
613  }
614  process_label (a->label, g, 0);
615}
616
617void process_label(Label l, Graph g, int adjust)
618{
619  float len, height;
620  int f, i;
621  float fnl, tmp;
622  char *s;
623
624  if (l->label == CNULL) return;
625
626  if (adjust) {
627    l->x = ctop(l->x, g->x_axis);
628    l->y = ctop(l->y, g->y_axis);
629  }
630  if (l->linesep == FSIG) l->linesep = l->fontsize;
631
632  l->nlines = 0;
633  for (i = 0; l->label[i] != '\0'; i++) {
634    if (l->label[i] == '\n') {
635      l->label[i] = '\0';
636      l->nlines++;
637    }
638  }
639  fnl = (float) l->nlines;
640
641  len = 0.0;
642  s = l->label;
643  for (i = 0; i <= l->nlines; i++) {
644    tmp = l->fontsize * FCPI / FPPI * strlen(s) * 0.8;
645    len = MAX(len, tmp);
646    if (i != l->nlines) {
647      f = strlen(s);
648      s[f] = '\n';
649      s = &(s[f+1]);
650    }
651  }
652  height = (l->fontsize * (fnl+1) + l->linesep * fnl) * FCPI / FPPI;
653  process_label_max_n_mins(l, len, height);
654}
655   
656void process_strings(Graph g)
657{
658  String s;
659
660  for(s = first(g->strings); s != nil(g->strings); s = next(s)) {
661    process_label(s->s, g, 1);
662  }
663}
664
665void process_curve(Curve c, Graph g)
666{
667  if (c->bezier && (c->npts < 4 || (c->npts % 3 != 1))) {
668    error_header();
669    fprintf(stderr, "  Graph %d Curve %d:\n", g->num, c->num);
670    fprintf(stderr, "  Curve has %d points\n", c->npts);
671    fprintf(stderr, "  Bezier must have 3n + 1 points (n > 0)\n");
672    exit(1);
673  }
674  c->marksize[0] = (c->marksize[0] == FSIG) ? 
675                   4.0 : disttop(c->marksize[0], g->x_axis);
676  c->marksize[1] = (c->marksize[1] == FSIG) ? 
677                   4.0 : disttop(c->marksize[1], g->y_axis);
678  if (c->marktype == 'o') c->marksize[1] = c->marksize[0];
679  c->asize[0] = (c->asize[0] == FSIG) ? 
680                   6.0 : disttop(c->asize[0], g->x_axis);
681  c->asize[1] = (c->asize[1] == FSIG) ? 
682                   2.0 : disttop(c->asize[1], g->y_axis) / 2.0;
683  c->lmark->x = disttop(c->lmark->x, g->x_axis);
684  c->lmark->y = disttop(c->lmark->y, g->y_axis);
685  process_label(c->lmark, g, 0);
686  if (c->parg == FSIG) c->parg = 0.0;
687  if (c->aparg == FSIG) c->aparg = 0.0;
688  if (c->pparg == FSIG) c->pparg = 0.0;
689}
690
691void process_curves(Graph g)
692{
693  Curve c;
694  for(c = first(g->curves); c != nil(g->curves); c = next(c)) {
695    process_curve(c, g);
696  }
697}
698
699void process_label_extrema(Label l, Graph g)
700{
701  if (l->label == CNULL) return;
702  g->yminval = MIN(g->yminval, l->ymin);
703  g->ymaxval = MAX(g->ymaxval, l->ymax);
704  g->xminval = MIN(g->xminval, l->xmin);
705  g->xmaxval = MAX(g->xmaxval, l->xmax);
706}
707 
708void process_extrema(Graph g)  /* Finds all the minval/maxvals for bbox calc */
709{
710  Curve c;
711  String s;
712  Axis xa, ya;
713
714  xa = g->x_axis;
715  ya = g->y_axis;
716
717  g->xminval = 0.0;
718  g->yminval = 0.0;
719  g->xmaxval = xa->psize;
720  g->ymaxval = ya->psize;
721 
722  if (xa->draw_axis_label) process_label_extrema(xa->label, g);
723  if (ya->draw_axis_label) process_label_extrema(ya->label, g);
724  if (xa->draw_hash_labels) process_label_extrema(xa->hl, g);
725  if (ya->draw_hash_labels) process_label_extrema(ya->hl, g);
726
727  if (xa->draw_hash_marks) {
728      g->yminval = MIN(g->yminval, xa->draw_hash_marks_at);
729      g->yminval = MIN(g->yminval, 
730                       xa->draw_hash_marks_at + HASH_DIR(xa) * HASH_SIZE);
731      g->ymaxval = MAX(g->ymaxval, xa->draw_hash_marks_at);
732      g->ymaxval = MAX(g->ymaxval, 
733                       xa->draw_hash_marks_at + HASH_DIR(xa) * HASH_SIZE);
734  }
735  if (ya->draw_hash_marks) {
736      g->xminval = MIN(g->xminval, ya->draw_hash_marks_at);
737      g->xminval = MIN(g->xminval, 
738                       ya->draw_hash_marks_at + HASH_DIR(ya) * HASH_SIZE);
739      g->xmaxval = MAX(g->xmaxval, ya->draw_hash_marks_at);
740      g->xmaxval = MAX(g->xmaxval, 
741                       ya->draw_hash_marks_at + HASH_DIR(ya) * HASH_SIZE);
742  }
743  process_label_extrema(g->title, g); 
744
745  if (g->legend->type == 'c') {
746    for (c = first(g->curves); c != nil(g->curves); c = next(c)) {
747      process_label_extrema(c->l, g);
748    }
749  } else if (g->legend->type == 'u' && g->legend->anylines >= 0) {
750    process_label_extrema(g->legend->l, g);
751  }
752  for(s = first(g->strings); s != nil(g->strings); s = next(s)) {
753    process_label_extrema(s->s, g);
754  }
755}
756
757void process_graph(Graph g)
758{
759  g->x_translate = intop(g->x_translate);
760  g->y_translate = intop(g->y_translate);
761  process_axis1(g->x_axis, g);
762  process_axis1(g->y_axis, g);
763  process_axis2(g->x_axis, g);
764  process_axis2(g->y_axis, g);
765  process_curves(g);
766  process_legend(g);
767  process_strings(g);
768  process_title(g);
769  process_extrema(g);
770}
771
772void process_graphs(Graphs gs)
773{
774  Graphs the_g;
775  Graph g;
776  float diff, max_y, min_y, max_x, min_x;
777  int do_bb, i;
778
779  Pi = acos(-1.0);
780  for (the_g = first(gs); the_g != nil(gs); the_g = next(the_g)) {
781    for (g = first(the_g->g); g != nil(the_g->g); g = next(g)) process_graph(g);
782    max_x = 0.0;
783    min_x = 0.0;
784    max_y = 0.0;
785    min_y = 0.0;
786    for (g = first(the_g->g); g != nil(the_g->g); g = next(g)) {
787      max_y = MAX(max_y, g->y_translate + g->ymaxval);
788      min_y = MIN(min_y, g->y_translate + g->yminval);
789      max_x = MAX(max_x, g->x_translate + g->xmaxval);
790      min_x = MIN(min_x, g->x_translate + g->xminval);
791    }
792
793    if (the_g->height >= 0.00) {
794      the_g->height *= FCPI;
795      if (the_g->height > max_y - min_y) {
796        diff = (the_g->height - max_y + min_y) / 2.0;
797        max_y += diff;
798        min_y -= diff;
799      } else {
800        the_g->height = max_y - min_y;
801      }
802    } else {
803      the_g->height = max_y - min_y;
804    }
805    if (the_g->width >= 0.00) {
806      the_g->width *= FCPI;
807      if (the_g->width > max_x - min_x) {
808        diff = (the_g->width - max_x + min_x) / 2.0;
809        max_x += diff;
810        min_x -= diff;
811      } else {
812        the_g->width = max_x - min_x;
813      }
814    } else {
815      the_g->width = max_x - min_x;
816    }
817
818    do_bb = 1;
819    for (i = 0; i < 4; i++) do_bb = (do_bb && the_g->bb[i] == ISIG);
820    if (do_bb) {
821      the_g->bb[0] = (int) (min_x - 1.0);
822      the_g->bb[1] = (int) (min_y - 1.0);
823      the_g->bb[2] = (int) (max_x + 1.0);
824      the_g->bb[3] = (int) (max_y + 1.0);
825    } 
826  }
827}
Note: See TracBrowser for help on using the repository browser.