source: trunk/Jgraph/process.c@ 638

Last change on this file since 638 was 420, checked in by Nicholas Riley, 17 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.