1 | #include "drawgraphics.h" |
---|
2 | |
---|
3 | /* Version 3.52c. Copyright (c) 1986-1993 by Joseph Felsenstein and |
---|
4 | Christopher A. Meacham. Additional code written by Hisashi Horino, |
---|
5 | Sean Lamont, Andrew Keefe, and Akiko Fuseki. |
---|
6 | Permission is granted to copy, distribute, |
---|
7 | and modify this program provided that (1) this copyright message is |
---|
8 | not removed and (2) no fee is charged for this program. */ |
---|
9 | |
---|
10 | #define maxnch 30 |
---|
11 | #define point '.' |
---|
12 | #define fontsize 3800 |
---|
13 | #define pi 3.141592653 |
---|
14 | #define epsilon 0.00001 |
---|
15 | #define xstart 10 |
---|
16 | #define ystart 35 |
---|
17 | #define gap 0.5 |
---|
18 | #define iterations 5 |
---|
19 | |
---|
20 | #ifdef MAC |
---|
21 | #undef maxnodes |
---|
22 | #define maxnodes 250 |
---|
23 | #endif |
---|
24 | |
---|
25 | typedef enum { fixed, radial, along} labelorient; |
---|
26 | FILE *treefile, *plotfile; |
---|
27 | char pltfilename[100]; |
---|
28 | long ntips, nextnode, strpwide, strpdeep, |
---|
29 | strptop, strpbottom, payge, numlines; |
---|
30 | double xmargin, ymargin, topoflabels, rightoflabels, leftoflabels, |
---|
31 | bottomoflabels, ark, maxx, maxy, minx, miny, scale, xscale, |
---|
32 | yscale, xoffset, yoffset, charht, xnow, ynow, xunitspercm, |
---|
33 | yunitspercm, xsize, ysize, xcorner, ycorner,labelheight, |
---|
34 | labelrotation, treeangle, expand, bscale,enthusiasm; |
---|
35 | boolean canbeplotted, preview, previewing, dotmatrix,haslengths, |
---|
36 | uselengths, regular, didreroot, rotate, empty, rescaled, |
---|
37 | notfirst, improve; |
---|
38 | double textlength[maxnodes], firstlet[maxnodes]; |
---|
39 | striptype stripe; |
---|
40 | plottertype plotter, oldplotter, previewer; |
---|
41 | growth grows; |
---|
42 | labelorient labeldirec; |
---|
43 | node *root, *where; |
---|
44 | node *nodep[maxnodes]; |
---|
45 | fonttype font; |
---|
46 | enum { yes, no } penchange, oldpenchange; |
---|
47 | char ch; |
---|
48 | char fontname[64]; |
---|
49 | long filesize; |
---|
50 | long strpdiv; |
---|
51 | |
---|
52 | openfile(fp,filename,mode,application,perm) |
---|
53 | FILE **fp; |
---|
54 | char *filename; |
---|
55 | char *mode; |
---|
56 | char *application; |
---|
57 | char *perm; |
---|
58 | { |
---|
59 | FILE *of; |
---|
60 | char file[100]; |
---|
61 | strcpy(file,filename); |
---|
62 | while (1){ |
---|
63 | of = fopen(file,mode); |
---|
64 | if (of) |
---|
65 | break; |
---|
66 | else { |
---|
67 | switch (*mode){ |
---|
68 | case 'r': |
---|
69 | printf("%s: can't read %s\n",application,file); |
---|
70 | file[0]='\0'; |
---|
71 | while (file[0] =='\0'){ |
---|
72 | printf("Please enter a new filename>"); |
---|
73 | gets(file);} |
---|
74 | break; |
---|
75 | case 'w': |
---|
76 | printf("%s: can't write %s\n",application,file); |
---|
77 | file[0] = '\0'; |
---|
78 | while (file[0] =='\0'){ |
---|
79 | printf("Please enter a new filename>"); |
---|
80 | gets(file);} |
---|
81 | break; |
---|
82 | } |
---|
83 | } |
---|
84 | } |
---|
85 | *fp=of; |
---|
86 | if (perm != NULL) |
---|
87 | strcpy(perm,file); |
---|
88 | } |
---|
89 | |
---|
90 | void uppercase(ch) |
---|
91 | Char *ch; |
---|
92 | { |
---|
93 | /* make ch upper-case */ |
---|
94 | *ch = (islower(*ch) ? toupper(*ch) : (*ch)); |
---|
95 | } /* uppercase */ |
---|
96 | |
---|
97 | /* Local variables for treeread: */ |
---|
98 | |
---|
99 | void getch(c) |
---|
100 | Char *c; |
---|
101 | { |
---|
102 | /* get next nonblank character */ |
---|
103 | do {*c = getc(treefile); |
---|
104 | } while ((*c == ' ')||(*c == '\n')||(*c == '\t')); |
---|
105 | } /* getch */ |
---|
106 | |
---|
107 | void processlength(p) |
---|
108 | node *p; |
---|
109 | { |
---|
110 | long digit, ordzero; |
---|
111 | double valyew, divisor; |
---|
112 | boolean pointread, minusread; |
---|
113 | |
---|
114 | ordzero = '0'; |
---|
115 | pointread = false; |
---|
116 | minusread = false; |
---|
117 | valyew = 0.0; |
---|
118 | divisor = 1.0; |
---|
119 | getch(&ch); |
---|
120 | digit = ch - ordzero; |
---|
121 | while (((unsigned long)digit <= 9) || (ch == '.') || (ch == '.')){ |
---|
122 | if (ch == '.') pointread = true; |
---|
123 | else if (ch == '-') minusread = true; |
---|
124 | else { |
---|
125 | valyew = valyew * 10.0 + digit; |
---|
126 | if (pointread) |
---|
127 | divisor *= 10.0; |
---|
128 | } |
---|
129 | getch(&ch); |
---|
130 | digit = ch - ordzero; |
---|
131 | } |
---|
132 | if (!minusread) |
---|
133 | p->oldlen = valyew / divisor; |
---|
134 | else |
---|
135 | p->oldlen = 0.0; |
---|
136 | /* processlength */ |
---|
137 | } |
---|
138 | |
---|
139 | void addelement(p, q) |
---|
140 | node **p, *q; |
---|
141 | { |
---|
142 | /* read in and add next part of tree, it will be node p |
---|
143 | and will be hooked to pointer q */ |
---|
144 | node *pp; |
---|
145 | long n,indx; |
---|
146 | boolean notlast; |
---|
147 | |
---|
148 | nextnode++; |
---|
149 | *p = (node *)Malloc((long)sizeof(node)); |
---|
150 | nodep[nextnode - 1] = *p; |
---|
151 | indx = nextnode; |
---|
152 | (*p)->index = indx; |
---|
153 | if (ch == '(') { |
---|
154 | (*p)->tip = false; |
---|
155 | pp = *p; |
---|
156 | notlast = true; |
---|
157 | while (notlast) { |
---|
158 | pp->next = (node *)Malloc((long)sizeof(node)); |
---|
159 | pp->next->tip = false; |
---|
160 | nextnode++; |
---|
161 | nodep[nextnode - 1] = pp->next; |
---|
162 | pp->next->index = indx; |
---|
163 | pp = pp->next; |
---|
164 | getch(&ch); |
---|
165 | addelement(&pp->back, pp); |
---|
166 | if (ch == ')') { |
---|
167 | notlast = false; |
---|
168 | do { |
---|
169 | getch(&ch); |
---|
170 | } while (ch != ':' && ch != ',' && ch != ')' && ch != '[' && |
---|
171 | ch != ';'); |
---|
172 | } |
---|
173 | } |
---|
174 | pp->next = *p; |
---|
175 | } else { |
---|
176 | (*p)->tip = true; |
---|
177 | ntips++; |
---|
178 | n = 1; |
---|
179 | do { |
---|
180 | if (!ebcdic && (ch & 255) == 255) |
---|
181 | ch = '\''; |
---|
182 | if (!ebcdic && (ch & 255) > 175) |
---|
183 | ch -= 48; |
---|
184 | if (!ebcdic && (ch & (~127)) != 0) |
---|
185 | ch -= 64; |
---|
186 | if (ch == '_') |
---|
187 | ch = ' '; |
---|
188 | if (n < maxnch) |
---|
189 | (*p)->nayme[n - 1] = ch; |
---|
190 | if (eoln(treefile)) { |
---|
191 | fscanf(treefile, "%*[^\n]"); |
---|
192 | (void)getc(treefile); |
---|
193 | } |
---|
194 | ch = getc(treefile); |
---|
195 | if (ch == '\n') |
---|
196 | ch = ' '; |
---|
197 | n++; |
---|
198 | } while (ch != ':' && ch != ',' && ch != ')'); |
---|
199 | if (n > maxnch) |
---|
200 | n = maxnch + 1; |
---|
201 | (*p)->naymlength = n - 1; |
---|
202 | } |
---|
203 | if (ch == ':') |
---|
204 | processlength(*p); |
---|
205 | else |
---|
206 | haslengths = (haslengths && q == NULL); |
---|
207 | (*p)->back = q; |
---|
208 | if (haslengths && q != NULL) |
---|
209 | (*p)->back->oldlen = (*p)->oldlen; |
---|
210 | (*p)->r = 0.0; |
---|
211 | (*p)->theta = 0.0; |
---|
212 | } /* addelement */ |
---|
213 | |
---|
214 | void treeread() |
---|
215 | { |
---|
216 | /* read a tree from the treefile and set up nodes and pointers */ |
---|
217 | haslengths = true; |
---|
218 | ntips = 0; |
---|
219 | nextnode = 0; |
---|
220 | getch(&ch); |
---|
221 | addelement(&root, NULL); |
---|
222 | root->oldlen = 0.0; |
---|
223 | fscanf(treefile, "%*[^\n]"); |
---|
224 | (void)getc(treefile); |
---|
225 | uselengths = haslengths; |
---|
226 | where = root; |
---|
227 | rotate = true; |
---|
228 | } /* treeread */ |
---|
229 | |
---|
230 | void initialparms() |
---|
231 | { |
---|
232 | /* initialize parameters */ |
---|
233 | |
---|
234 | getplotter(); |
---|
235 | plotrparms(); |
---|
236 | xmargin = 0.08 * xsize; |
---|
237 | ymargin = 0.08 * ysize; |
---|
238 | xscale = xunitspercm; |
---|
239 | yscale = yunitspercm; |
---|
240 | grows = vertical; |
---|
241 | treeangle = pi / 2.0; |
---|
242 | ark = 2 * pi; |
---|
243 | improve = true; |
---|
244 | regular = false; |
---|
245 | rescaled = true; |
---|
246 | bscale = 1.0; |
---|
247 | labeldirec = fixed; |
---|
248 | labelrotation = 0.0; |
---|
249 | charht = 0.3333; |
---|
250 | numlines = dotmatrix ? ((long)floor(yunitspercm * ysize + 0.5) / strpdeep):1; |
---|
251 | enthusiasm = 1.0/(double)ntips; |
---|
252 | } /* initialparms */ |
---|
253 | |
---|
254 | |
---|
255 | long showparms() |
---|
256 | { |
---|
257 | long i; |
---|
258 | long numtochange; |
---|
259 | Char ch,input[64]; |
---|
260 | double treea; |
---|
261 | |
---|
262 | putchar('\n'); |
---|
263 | if (previewer == tek) |
---|
264 | printf("%c\f", escape); |
---|
265 | else { |
---|
266 | for (i = 1; i <= 24; i++) |
---|
267 | putchar('\n'); |
---|
268 | } |
---|
269 | printf("Here are the settings: \n\n"); |
---|
270 | printf(" (1) Use branch lengths: "); |
---|
271 | if (haslengths) |
---|
272 | printf("%s\n",uselengths ? "Yes" : "No"); |
---|
273 | else |
---|
274 | printf("(no branch lengths available)\n"); |
---|
275 | printf(" (2) Angle of labels:"); |
---|
276 | if (labeldirec == fixed) { |
---|
277 | printf(" Fixed angle of"); |
---|
278 | if (labelrotation >= 10.0) |
---|
279 | printf("%6.1f", labelrotation); |
---|
280 | else if (labelrotation <= -10.0) |
---|
281 | printf("%7.1f", labelrotation); |
---|
282 | else if (labelrotation < 0.0) |
---|
283 | printf("%6.1f", labelrotation); |
---|
284 | else |
---|
285 | printf("%5.1f", labelrotation); |
---|
286 | printf(" degrees\n"); |
---|
287 | } else if (labeldirec == radial) |
---|
288 | printf(" Radial\n"); |
---|
289 | else |
---|
290 | printf(" Along branches\n"); |
---|
291 | printf(" (3) Rotation of tree:"); |
---|
292 | treea = treeangle * 180 / pi; |
---|
293 | if (treea >= 100.0) |
---|
294 | printf("%7.1f\n", treea); |
---|
295 | else if (treea >= 10.0) |
---|
296 | printf("%6.1f\n", treea); |
---|
297 | else if (treea <= -100.0) |
---|
298 | printf("%8.1f\n", treea); |
---|
299 | else if (treea <= -10.0) |
---|
300 | printf("%7.1f\n", treea); |
---|
301 | else if (treea < 0.0) |
---|
302 | printf("%6.1f\n", treea); |
---|
303 | else |
---|
304 | printf("%5.1f\n", treea); |
---|
305 | printf(" (4) Angle of arc for tree:"); |
---|
306 | treea = 180 * ark / pi; |
---|
307 | if (treea >= 100.0) |
---|
308 | printf("%7.1f\n", treea); |
---|
309 | else if (treea >= 10.0) |
---|
310 | printf("%6.1f\n", treea); |
---|
311 | else if (treea <= -100.0) |
---|
312 | printf("%8.1f\n", treea); |
---|
313 | else if (treea <= -10.0) |
---|
314 | printf("%7.1f\n", treea); |
---|
315 | else if (treea < 0.0) |
---|
316 | printf("%6.1f\n", treea); |
---|
317 | else |
---|
318 | printf("%5.1f\n", treea); |
---|
319 | printf(" (5) Iterate to improve tree: %s\n", |
---|
320 | (improve ? "Yes" : "No")); |
---|
321 | printf(" (6) Scale of branch length:"); |
---|
322 | if (rescaled) |
---|
323 | printf(" Automatically rescaled\n"); |
---|
324 | else |
---|
325 | printf(" Fixed:%6.2f cm per unit branch length\n", bscale); |
---|
326 | didreroot = false; |
---|
327 | printf(" (7) Horizontal margins:%6.2f cm\n", xmargin); |
---|
328 | printf(" (7) Vertical margins:%6.2f cm\n", ymargin); |
---|
329 | printf(" (8) Relative character height:%8.4f\n", charht); |
---|
330 | if (!improve) |
---|
331 | printf(" (9) Regularize the angles: %s\n",(regular ? "Yes" : "No")); |
---|
332 | else |
---|
333 | printf(" (9) Enthusiasm constant:%9.5f\n",enthusiasm); |
---|
334 | if (plotter == lw) |
---|
335 | printf(" (10) Font : %s\n",fontname); |
---|
336 | |
---|
337 | printf("\n\n Do you want to accept these? (Yes or No)\n"); |
---|
338 | for (;;) { |
---|
339 | printf(" Type Y or N or the number (1-%2ld) of the one to change: \n", |
---|
340 | (plotter == lw) ? 10L : 9L); |
---|
341 | gets(input); |
---|
342 | uppercase(&input[0]); |
---|
343 | ch=input[0]; |
---|
344 | numtochange = atoi(input); |
---|
345 | if ((ch == 'Y' || ch == 'N') || (numtochange >= 1 && numtochange <= |
---|
346 | ((plotter == lw) ? 10 : 9))) |
---|
347 | break; |
---|
348 | } |
---|
349 | return (ch == 'Y') ? -1 : numtochange; |
---|
350 | } /* showparms */ |
---|
351 | |
---|
352 | void rerootit(p) |
---|
353 | node *p; |
---|
354 | { |
---|
355 | node *q; |
---|
356 | |
---|
357 | q = root; |
---|
358 | while (q->next != root) |
---|
359 | q = q->next; |
---|
360 | q->next = root->next; |
---|
361 | q = p; |
---|
362 | while (q->next != p) |
---|
363 | q = q->next; |
---|
364 | root->next = p; |
---|
365 | q->next = root; |
---|
366 | } /* rerootit */ |
---|
367 | |
---|
368 | void reroot() |
---|
369 | { |
---|
370 | /* reroot the tree, traversing tree */ |
---|
371 | where = root->next; |
---|
372 | if (!rotate) |
---|
373 | rotate = where->back->tip; |
---|
374 | if (rotate) { |
---|
375 | where = where->next; |
---|
376 | rotate = false; |
---|
377 | } else { |
---|
378 | where = where->back; |
---|
379 | rotate = true; |
---|
380 | } |
---|
381 | rerootit(where); |
---|
382 | } /* reroot */ |
---|
383 | |
---|
384 | |
---|
385 | void getparms(numtochange) |
---|
386 | long numtochange; |
---|
387 | { |
---|
388 | /* get from user the relevant parameters for the plotter and diagram */ |
---|
389 | Char ch; |
---|
390 | boolean ok; |
---|
391 | |
---|
392 | if (numtochange == 0) { |
---|
393 | do { |
---|
394 | printf(" Type the number of one that you want to change (1-%2ld):\n", |
---|
395 | (plotter == lw) ? 10L : 9L); |
---|
396 | scanf("%ld%*[^\n]", &numtochange); |
---|
397 | (void)getchar(); |
---|
398 | } while (numtochange < 1 || numtochange > ((plotter == lw) ? 10 : 9)); |
---|
399 | } |
---|
400 | switch (numtochange) { |
---|
401 | |
---|
402 | case 1: |
---|
403 | if (haslengths) |
---|
404 | uselengths = !uselengths; |
---|
405 | else { |
---|
406 | printf("Cannot use lengths since not all of them exist\n"); |
---|
407 | uselengths = false; |
---|
408 | } |
---|
409 | break; |
---|
410 | |
---|
411 | case 2: |
---|
412 | printf("\nDo you want labels to be Fixed angle, Radial,"); |
---|
413 | printf(" or Along branches?\n"); |
---|
414 | do { |
---|
415 | printf(" Type F, R, or A\n"); |
---|
416 | scanf("%c%*[^\n]", &ch); |
---|
417 | (void)getchar(); |
---|
418 | if (ch == '\n') |
---|
419 | ch = ' '; |
---|
420 | uppercase(&ch); |
---|
421 | } while (ch != 'F' && ch != 'R' && ch != 'A'); |
---|
422 | switch (ch) { |
---|
423 | |
---|
424 | case 'A': |
---|
425 | labeldirec = along; |
---|
426 | break; |
---|
427 | |
---|
428 | case 'F': |
---|
429 | labeldirec = fixed; |
---|
430 | break; |
---|
431 | |
---|
432 | case 'R': |
---|
433 | labeldirec = radial; |
---|
434 | break; |
---|
435 | } |
---|
436 | if (labeldirec == fixed) { |
---|
437 | printf("Are the labels to be plotted vertically (90),\n"); |
---|
438 | printf(" horizontally (0), or downwards (-90) ?\n"); |
---|
439 | do { |
---|
440 | printf(" Choose an angle in degrees from 90 to -90: \n"); |
---|
441 | scanf("%lf%*[^\n]", &labelrotation); |
---|
442 | (void)getchar(); |
---|
443 | } while ((labelrotation < -90.0 || labelrotation > 90.0) && |
---|
444 | labelrotation != -99.0); |
---|
445 | } |
---|
446 | break; |
---|
447 | |
---|
448 | case 3: |
---|
449 | printf("\n At what angle is the tree to be plotted?\n"); |
---|
450 | do { |
---|
451 | printf(" Choose an angle in degrees from 360 to -360: \n"); |
---|
452 | scanf("%lf%*[^\n]", &treeangle); |
---|
453 | (void)getchar(); |
---|
454 | uppercase(&ch); |
---|
455 | } while (treeangle < -360.0 && treeangle > 360.0); |
---|
456 | treeangle = treeangle * pi / 180; |
---|
457 | break; |
---|
458 | |
---|
459 | case 4: |
---|
460 | printf(" How many degrees (up to 360) of arc\n"); |
---|
461 | printf(" should the tree occupy? (Currently it is %5.1f)\n", |
---|
462 | 180 * ark / pi); |
---|
463 | do { |
---|
464 | printf("Enter a number of degrees from 0 up to 360)\n"); |
---|
465 | scanf("%lf%*[^\n]", &ark); |
---|
466 | (void)getchar(); |
---|
467 | } while (ark <= 0.0 || ark > 360.0); |
---|
468 | ark = ark * pi / 180; |
---|
469 | break; |
---|
470 | |
---|
471 | case 5: |
---|
472 | improve = !improve; |
---|
473 | break; |
---|
474 | |
---|
475 | case 6: |
---|
476 | rescaled = !rescaled; |
---|
477 | if (!rescaled) { |
---|
478 | printf("Centimeters per unit branch length?\n"); |
---|
479 | scanf("%lf%*[^\n]", &bscale); |
---|
480 | (void)getchar(); |
---|
481 | } |
---|
482 | break; |
---|
483 | |
---|
484 | case 7: |
---|
485 | printf("\nThe tree will be drawn to fit in a rectangle which has \n"); |
---|
486 | printf(" margins in the horizontal and vertical directions of:\n"); |
---|
487 | printf("%6.2f cm (horizontal margin) and%6.2f cm (vertical margin)\n\n", |
---|
488 | xmargin, ymargin); |
---|
489 | do { |
---|
490 | printf(" New value (in cm) of horizontal margin?\n"); |
---|
491 | scanf("%lf%*[^\n]", &xmargin); |
---|
492 | (void)getchar(); |
---|
493 | ok = ((unsigned)xmargin < xsize / 2.0); |
---|
494 | if (!ok) |
---|
495 | printf(" Impossible value. Please retype it.\n"); |
---|
496 | } while (!ok); |
---|
497 | do { |
---|
498 | printf(" New value (in cm) of vertical margin?\n"); |
---|
499 | scanf("%lf%*[^\n]", &ymargin); |
---|
500 | (void)getchar(); |
---|
501 | ok = ((unsigned)ymargin < ysize / 2.0); |
---|
502 | if (!ok) |
---|
503 | printf(" Impossible value. Please retype it.\n"); |
---|
504 | } while (!ok); |
---|
505 | break; |
---|
506 | |
---|
507 | case 8: |
---|
508 | printf("New value of character height?\n"); |
---|
509 | scanf("%lf%*[^\n]", &charht); |
---|
510 | (void)getchar(); |
---|
511 | break; |
---|
512 | case 9: |
---|
513 | if (improve) { |
---|
514 | do { |
---|
515 | printf("Enthusiasm constant? (must be between 0 and 1)\n"); |
---|
516 | scanf("%lf%*[^\n]", &enthusiasm); |
---|
517 | getchar(); |
---|
518 | } while (enthusiasm <= 0.0 || enthusiasm > 1.0);} |
---|
519 | else |
---|
520 | regular = !regular; |
---|
521 | break; |
---|
522 | case 10: |
---|
523 | printf("Enter font name or \"Hershey\" for default font\n"); |
---|
524 | gets(fontname); |
---|
525 | break; |
---|
526 | } |
---|
527 | } /* getparms */ |
---|
528 | |
---|
529 | |
---|
530 | Local void getwidth(p) |
---|
531 | node *p; |
---|
532 | { |
---|
533 | /* get width and depth beyond each node */ |
---|
534 | double nw, nd; |
---|
535 | node *pp, *qq; |
---|
536 | |
---|
537 | nd = 0.0; |
---|
538 | if (p->tip) |
---|
539 | nw = 1.0; |
---|
540 | else { |
---|
541 | nw = 0.0; |
---|
542 | qq = p; |
---|
543 | pp = p->next; |
---|
544 | do { |
---|
545 | getwidth(pp->back); |
---|
546 | nw += pp->back->width; |
---|
547 | if (pp->back->depth > nd) |
---|
548 | nd = pp->back->depth; |
---|
549 | pp = pp->next; |
---|
550 | } while (pp != qq); |
---|
551 | } |
---|
552 | p->depth = nd + p->length; |
---|
553 | p->width = nw; |
---|
554 | } /* getwidth */ |
---|
555 | |
---|
556 | void plrtrans(p, theta, lower, upper) |
---|
557 | node *p; |
---|
558 | double theta, lower, upper; |
---|
559 | { |
---|
560 | /* polar coordinates of a node relative to start */ |
---|
561 | long num; |
---|
562 | double nn, pr, ptheta, angle, angle2, subangle, len; |
---|
563 | node *pp, *qq; |
---|
564 | |
---|
565 | nn = p->width; |
---|
566 | angle = theta; |
---|
567 | subangle = (upper - lower) / nn; |
---|
568 | qq = p; |
---|
569 | pp = p->next; |
---|
570 | if (p->tip) |
---|
571 | return; |
---|
572 | angle = upper; |
---|
573 | do { |
---|
574 | angle -= pp->back->width / 2.0 * subangle; |
---|
575 | pr = p->r; |
---|
576 | ptheta = p->theta; |
---|
577 | if (regular) { |
---|
578 | num = 1; |
---|
579 | while (num * subangle < 2 * pi) |
---|
580 | num *= 2; |
---|
581 | if (angle >= 0.0) |
---|
582 | angle2 = 2 * pi / num * (long)(num * angle / (2 * pi) + 0.5); |
---|
583 | else |
---|
584 | angle2 = 2 * pi / num * (long)(num * angle / (2 * pi) - 0.5); |
---|
585 | } else |
---|
586 | angle2 = angle; |
---|
587 | if (uselengths) |
---|
588 | len = pp->back->oldlen; |
---|
589 | else |
---|
590 | len = 1.0; |
---|
591 | pp->back->r = sqrt(len * len + pr * pr + 2 * len * pr * cos(angle2 - ptheta)); |
---|
592 | if (fabs(pr * cos(ptheta) + len * cos(angle2)) > epsilon) |
---|
593 | pp->back->theta = atan((pr * sin(ptheta) + len * sin(angle2)) / |
---|
594 | (pr * cos(ptheta) + len * cos(angle2))); |
---|
595 | else if (pr * sin(ptheta) + len * sin(angle2) >= 0.0) |
---|
596 | pp->back->theta = pi / 2; |
---|
597 | else |
---|
598 | pp->back->theta = 1.5 * pi; |
---|
599 | if (pr * cos(ptheta) + len * cos(angle2) < -epsilon) |
---|
600 | pp->back->theta += pi; |
---|
601 | if (!pp->back->tip) |
---|
602 | plrtrans(pp->back, pp->back->theta, |
---|
603 | angle - pp->back->width * subangle / 2.0, |
---|
604 | angle + pp->back->width * subangle / 2.0); |
---|
605 | else |
---|
606 | pp->back->oldtheta = angle2; |
---|
607 | angle -= pp->back->width / 2.0 * subangle; |
---|
608 | pp = pp->next; |
---|
609 | } while (pp != qq); |
---|
610 | } /* plrtrans */ |
---|
611 | |
---|
612 | void coordtrav(p, xx, yy) |
---|
613 | node *p; |
---|
614 | double *xx, *yy; |
---|
615 | { |
---|
616 | /* compute x and y coordinates */ |
---|
617 | long i; |
---|
618 | node *pp; |
---|
619 | |
---|
620 | if (!p->tip) { |
---|
621 | pp = p->next; |
---|
622 | while (pp != p) { |
---|
623 | coordtrav(pp->back, xx,yy); |
---|
624 | pp = pp->next; |
---|
625 | } |
---|
626 | } |
---|
627 | if (p->tip) { |
---|
628 | i = 1; |
---|
629 | while (nodep[i - 1] != p) |
---|
630 | i++; |
---|
631 | textlength[i - 1] = (double)lengthtext(p->nayme, p->naymlength, font); |
---|
632 | } |
---|
633 | (*xx) = p->r * cos(p->theta); |
---|
634 | (*yy) = p->r * sin(p->theta); |
---|
635 | if ((*xx) > maxx) |
---|
636 | maxx = (*xx); |
---|
637 | if ((*xx) < minx) |
---|
638 | minx = (*xx); |
---|
639 | if ((*yy) > maxy) |
---|
640 | maxy = (*yy); |
---|
641 | if ((*yy) < miny) |
---|
642 | miny = (*yy); |
---|
643 | p->xcoord = (*xx); |
---|
644 | p->ycoord = (*yy); |
---|
645 | } /* coordtrav */ |
---|
646 | |
---|
647 | |
---|
648 | double angleof(x, y) |
---|
649 | double x, y; |
---|
650 | { |
---|
651 | /* compute the angle of a vector */ |
---|
652 | double theta; |
---|
653 | |
---|
654 | if (fabs(x) > epsilon) |
---|
655 | theta = atan(y / x); |
---|
656 | else if (y >= 0.0) |
---|
657 | theta = pi / 2; |
---|
658 | else |
---|
659 | theta = 1.5 * pi; |
---|
660 | if (x < -epsilon) |
---|
661 | theta = pi + theta; |
---|
662 | if (theta > 2 * pi) |
---|
663 | theta -= 2 * pi; |
---|
664 | return theta; |
---|
665 | } /* angleof */ |
---|
666 | |
---|
667 | void polartrav(p,xx,yy,leftx,lefty,rightx,righty) |
---|
668 | node *p; |
---|
669 | double *xx,*yy,*leftx,*lefty,*rightx,*righty; |
---|
670 | { |
---|
671 | /* go through subtree getting left and right vectors */ |
---|
672 | double x, y; |
---|
673 | boolean lookatit; |
---|
674 | node *pp; |
---|
675 | |
---|
676 | lookatit = true; |
---|
677 | if (!p->tip) |
---|
678 | lookatit = (p->next->next->next != p || p->index != root->index); |
---|
679 | if (lookatit) { |
---|
680 | x = nodep[p->index - 1]->xcoord; |
---|
681 | y = nodep[p->index - 1]->ycoord; |
---|
682 | if ((y - (*yy)) * (*rightx) - (x - (*xx)) * (*righty) < 0.0) { |
---|
683 | (*rightx) = x - (*xx); |
---|
684 | (*righty) = y - (*yy); |
---|
685 | } |
---|
686 | if ((y - (*yy)) * (*leftx) - (x - (*xx)) * (*lefty) > 0.0 && |
---|
687 | !(notfirst && fabs((*rightx) - x + (*xx)) + |
---|
688 | fabs((*righty) - y + (*yy)) < epsilon)) { |
---|
689 | (*leftx) = x - (*xx); |
---|
690 | (*lefty) = y - (*yy); |
---|
691 | notfirst = true; |
---|
692 | } |
---|
693 | } |
---|
694 | if (p->tip) |
---|
695 | return; |
---|
696 | pp = p->next; |
---|
697 | while (pp != p) { |
---|
698 | if (pp != root) |
---|
699 | polartrav(pp->back,xx,yy,leftx,lefty,rightx,righty); |
---|
700 | pp = pp->next; |
---|
701 | } |
---|
702 | } /* polartrav */ |
---|
703 | |
---|
704 | void tilttrav(q,xx,yy,sinphi,cosphi) |
---|
705 | node *q; |
---|
706 | double *xx,*yy,*sinphi,*cosphi; |
---|
707 | { |
---|
708 | /* traverse to move successive nodes */ |
---|
709 | double x, y; |
---|
710 | node *pp; |
---|
711 | |
---|
712 | pp = nodep[q->index - 1]; |
---|
713 | x = pp->xcoord; |
---|
714 | y = pp->ycoord; |
---|
715 | pp->xcoord = (*xx) + (x - (*xx)) * (*cosphi) + (y - (*yy)) * (*sinphi); |
---|
716 | pp->ycoord = (*yy) + ((*xx) - x) * (*sinphi) + (y - (*yy)) * (*cosphi); |
---|
717 | if (q->tip) |
---|
718 | return; |
---|
719 | pp = q->next; |
---|
720 | while (pp != q) { |
---|
721 | if (pp != root) |
---|
722 | tilttrav(pp->back,xx,yy,sinphi,cosphi); |
---|
723 | pp = pp->next; |
---|
724 | } |
---|
725 | } /* tilttrav */ |
---|
726 | |
---|
727 | void polarize(p,xx,yy) |
---|
728 | node *p; |
---|
729 | double *xx,*yy; |
---|
730 | { |
---|
731 | double TEMP, TEMP1; |
---|
732 | |
---|
733 | if (fabs(p->xcoord - (*xx)) > epsilon) |
---|
734 | p->oldtheta = atan((p->ycoord - (*yy)) / (p->xcoord - (*xx))); |
---|
735 | else if (p->ycoord - (*yy) >= 0.0) |
---|
736 | p->oldtheta = pi / 2; |
---|
737 | else |
---|
738 | p->oldtheta = 1.5 * pi; |
---|
739 | if (p->xcoord - (*xx) < -epsilon) |
---|
740 | p->oldtheta += pi; |
---|
741 | if (fabs(p->xcoord - root->xcoord) > epsilon) |
---|
742 | p->theta = atan((p->ycoord - root->ycoord) / (p->xcoord - root->xcoord)); |
---|
743 | else if (p->ycoord - root->ycoord >= 0.0) |
---|
744 | p->theta = pi / 2; |
---|
745 | else |
---|
746 | p->theta = 1.5 * pi; |
---|
747 | if (p->xcoord - root->xcoord < -epsilon) |
---|
748 | p->theta += pi; |
---|
749 | TEMP = p->xcoord - root->xcoord; |
---|
750 | TEMP1 = p->ycoord - root->ycoord; |
---|
751 | p->r = sqrt(TEMP * TEMP + TEMP1 * TEMP1); |
---|
752 | } /* polarize */ |
---|
753 | |
---|
754 | void improvtrav(p) |
---|
755 | node *p; |
---|
756 | { |
---|
757 | /* traverse tree trying different tiltings at each node */ |
---|
758 | double xx, yy, leftx, lefty, rightx, righty, cosphi, sinphi; |
---|
759 | long n; |
---|
760 | double usedangle, langle, rangle, freeangle, meanangle, sumrot; |
---|
761 | node *pp, *qq; |
---|
762 | |
---|
763 | if (p->tip) |
---|
764 | return; |
---|
765 | xx = p->xcoord; |
---|
766 | yy = p->ycoord; |
---|
767 | if (p != root) { |
---|
768 | n = 0; |
---|
769 | usedangle = 0.0; |
---|
770 | pp = p->next; |
---|
771 | do { |
---|
772 | leftx = pp->back->xcoord - xx; |
---|
773 | lefty = pp->back->ycoord - yy; |
---|
774 | rightx = leftx; |
---|
775 | righty = lefty; |
---|
776 | notfirst = false; |
---|
777 | if (!pp->back->tip) |
---|
778 | polartrav(pp->back, &xx,&yy,&leftx,&lefty,&rightx,&righty); |
---|
779 | n++; |
---|
780 | langle = angleof(leftx, lefty); |
---|
781 | rangle = angleof(rightx, righty); |
---|
782 | if (rangle > langle) |
---|
783 | langle += 2 * pi; |
---|
784 | pp->lefttheta = langle; |
---|
785 | pp->righttheta = rangle; |
---|
786 | usedangle += langle - rangle; |
---|
787 | pp = pp->next; |
---|
788 | } while (pp != p->next); |
---|
789 | freeangle = 2 * pi - usedangle; |
---|
790 | meanangle = freeangle / n; |
---|
791 | sumrot = 0.0; |
---|
792 | qq = p; |
---|
793 | pp = p->next; |
---|
794 | while (pp != p) { |
---|
795 | langle = qq->righttheta; |
---|
796 | rangle = pp->lefttheta; |
---|
797 | if (rangle > langle) |
---|
798 | langle += 2 * pi; |
---|
799 | sumrot += enthusiasm * (meanangle - langle + rangle); |
---|
800 | cosphi = cos(sumrot); |
---|
801 | sinphi = sin(sumrot); |
---|
802 | if (pp != root) |
---|
803 | tilttrav(pp->back, &xx,&yy,&sinphi,&cosphi); |
---|
804 | qq = pp; |
---|
805 | pp = pp->next; |
---|
806 | } |
---|
807 | } |
---|
808 | pp = p->next; |
---|
809 | while (pp != p) { |
---|
810 | if (pp != root) |
---|
811 | polarize(pp->back, &xx,&yy); |
---|
812 | pp = pp->next; |
---|
813 | } |
---|
814 | pp = p->next; |
---|
815 | while (pp != p) { |
---|
816 | if (pp != root) |
---|
817 | improvtrav(pp->back); |
---|
818 | pp = pp->next; |
---|
819 | } |
---|
820 | } /* improvtrav */ |
---|
821 | |
---|
822 | void coordimprov(xx,yy) |
---|
823 | double *xx,*yy; |
---|
824 | { |
---|
825 | /* use angles calculation to improve node coordinate placement */ |
---|
826 | long i; |
---|
827 | for (i = 1; i <= iterations; i++) |
---|
828 | improvtrav(root); |
---|
829 | } /* coordimprov */ |
---|
830 | |
---|
831 | |
---|
832 | void calculate() |
---|
833 | { |
---|
834 | /* compute coordinates for tree */ |
---|
835 | double xx, yy; |
---|
836 | long i; |
---|
837 | double nttot, fontheight, labangle, top, bot, rig, lef; |
---|
838 | |
---|
839 | for (i = 0; i < nextnode; i++) |
---|
840 | nodep[i]->width = 1.0; |
---|
841 | for (i = 0; i < nextnode; i++) |
---|
842 | nodep[i]->xcoord = 0.0; |
---|
843 | for (i = 0; i < nextnode; i++) |
---|
844 | nodep[i]->ycoord = 0.0; |
---|
845 | if (!uselengths) { |
---|
846 | for (i = 0; i < nextnode; i++) |
---|
847 | nodep[i]->length = 1.0; |
---|
848 | } else { |
---|
849 | for (i = 0; i < nextnode; i++) |
---|
850 | nodep[i]->length = nodep[i]->oldlen; |
---|
851 | } |
---|
852 | getwidth(root); |
---|
853 | nttot = root->width; |
---|
854 | for (i = 0; i < nextnode; i++) |
---|
855 | nodep[i]->width = nodep[i]->width * ntips / nttot; |
---|
856 | plrtrans(root, treeangle, treeangle - ark / 2.0, treeangle + ark / 2.0); |
---|
857 | maxx = 0.0; |
---|
858 | minx = 0.0; |
---|
859 | maxy = 0.0; |
---|
860 | miny = 0.0; |
---|
861 | coordtrav(root, &xx,&yy); |
---|
862 | if (improve) { |
---|
863 | coordimprov(&xx,&yy); |
---|
864 | coordtrav(root, &xx,&yy); |
---|
865 | } |
---|
866 | fontheight = font[2]; |
---|
867 | if (labeldirec == fixed) |
---|
868 | labangle = pi * labelrotation / 180.0; |
---|
869 | for (i = 0; i < nextnode; i++) { |
---|
870 | if (nodep[i]->tip) |
---|
871 | textlength[i] /= fontheight; |
---|
872 | } |
---|
873 | if (ntips > 1) |
---|
874 | labelheight = charht * (maxx - minx) / (ntips - 1); |
---|
875 | else |
---|
876 | labelheight = charht * (maxx - minx); |
---|
877 | topoflabels = 0.0; |
---|
878 | bottomoflabels = 0.0; |
---|
879 | rightoflabels = 0.0; |
---|
880 | leftoflabels = 0.0; |
---|
881 | for (i = 0; i < nextnode; i++) { |
---|
882 | if (nodep[i]->tip) { |
---|
883 | if (labeldirec == radial) |
---|
884 | labangle = nodep[i]->theta; |
---|
885 | else if (labeldirec == along) |
---|
886 | labangle = nodep[i]->oldtheta; |
---|
887 | if (cos(labangle) < 0.0 && labeldirec != fixed) |
---|
888 | labangle -= pi; |
---|
889 | firstlet[i] = (double)lengthtext(nodep[i]->nayme,1L,font)/ fontheight; |
---|
890 | top = (nodep[i]->ycoord - maxy) / labelheight + sin(nodep[i]->oldtheta); |
---|
891 | rig = (nodep[i]->xcoord - maxx) / labelheight + cos(nodep[i]->oldtheta); |
---|
892 | bot = (miny - nodep[i]->ycoord) / labelheight - sin(nodep[i]->oldtheta); |
---|
893 | lef = (minx - nodep[i]->xcoord) / labelheight - cos(nodep[i]->oldtheta); |
---|
894 | if (cos(labangle) * cos(nodep[i]->oldtheta) + |
---|
895 | sin(labangle) * sin(nodep[i]->oldtheta) > 0.0) { |
---|
896 | if (sin(labangle) > 0.0) |
---|
897 | top += sin(labangle) * textlength[i]; |
---|
898 | top += sin(labangle - 1.25 * pi) * gap * firstlet[i]; |
---|
899 | if (sin(labangle) < 0.0) |
---|
900 | bot -= sin(labangle) * textlength[i]; |
---|
901 | bot -= sin(labangle - 0.75 * pi) * gap * firstlet[i]; |
---|
902 | if (sin(labangle) > 0.0) |
---|
903 | rig += cos(labangle - 0.75 * pi) * gap * firstlet[i]; |
---|
904 | else |
---|
905 | rig += cos(labangle - 1.25 * pi) * gap * firstlet[i]; |
---|
906 | rig += cos(labangle) * textlength[i]; |
---|
907 | if (sin(labangle) > 0.0) |
---|
908 | lef -= cos(labangle - 1.25 * pi) * gap * firstlet[i]; |
---|
909 | else |
---|
910 | lef -= cos(labangle - 0.75 * pi) * gap * firstlet[i]; |
---|
911 | } else { |
---|
912 | if (sin(labangle) < 0.0) |
---|
913 | top -= sin(labangle) * textlength[i]; |
---|
914 | top += sin(labangle + 0.25 * pi) * gap * firstlet[i]; |
---|
915 | if (sin(labangle) > 0.0) |
---|
916 | bot += sin(labangle) * textlength[i]; |
---|
917 | bot -= sin(labangle - 0.25 * pi) * gap * firstlet[i]; |
---|
918 | if (sin(labangle) > 0.0) |
---|
919 | rig += cos(labangle - 0.25 * pi) * gap * firstlet[i]; |
---|
920 | else |
---|
921 | rig += cos(labangle + 0.25 * pi) * gap * firstlet[i]; |
---|
922 | if (sin(labangle) < 0.0) |
---|
923 | rig += cos(labangle) * textlength[i]; |
---|
924 | if (sin(labangle) > 0.0) |
---|
925 | lef -= cos(labangle + 0.25 * pi) * gap * firstlet[i]; |
---|
926 | else |
---|
927 | lef -= cos(labangle - 0.25 * pi) * gap * firstlet[i]; |
---|
928 | lef += cos(labangle) * textlength[i]; |
---|
929 | } |
---|
930 | if (top > topoflabels) |
---|
931 | topoflabels = top; |
---|
932 | if (bot > bottomoflabels) |
---|
933 | bottomoflabels = bot; |
---|
934 | if (rig > rightoflabels) |
---|
935 | rightoflabels = rig; |
---|
936 | if (lef > leftoflabels) |
---|
937 | leftoflabels = lef; |
---|
938 | } |
---|
939 | } |
---|
940 | topoflabels *= labelheight; |
---|
941 | bottomoflabels *= labelheight; |
---|
942 | leftoflabels *= labelheight; |
---|
943 | rightoflabels *= labelheight; |
---|
944 | } /* calculate */ |
---|
945 | |
---|
946 | |
---|
947 | void rescale() |
---|
948 | { |
---|
949 | /* compute coordinates of tree for plot or preview device */ |
---|
950 | long i; |
---|
951 | double treeheight, treewidth, extrax, extray, temp; |
---|
952 | |
---|
953 | treeheight = maxy - miny + topoflabels + bottomoflabels; |
---|
954 | treewidth = maxx - minx + rightoflabels + leftoflabels; |
---|
955 | if (grows == vertical) { |
---|
956 | if (!rescaled) |
---|
957 | expand = bscale; |
---|
958 | else { |
---|
959 | expand = (xsize - 2 * xmargin) / treewidth; |
---|
960 | if ((ysize - 2 * ymargin) / treeheight < expand) |
---|
961 | expand = (ysize - 2 * ymargin) / treeheight; |
---|
962 | } |
---|
963 | extrax = (xsize - 2 * xmargin - treewidth * expand) / 2.0; |
---|
964 | extray = (ysize - 2 * ymargin - treeheight * expand) / 2.0; |
---|
965 | } else { |
---|
966 | if (!rescaled) |
---|
967 | expand = bscale; |
---|
968 | else { |
---|
969 | expand = (ysize - 2 * ymargin) / treewidth; |
---|
970 | if ((xsize - 2 * xmargin) / treeheight < expand) |
---|
971 | expand = (xsize - 2 * xmargin) / treeheight; |
---|
972 | } |
---|
973 | extrax = (xsize - 2 * xmargin - treeheight * expand) / 2.0; |
---|
974 | extray = (ysize - 2 * ymargin - treewidth * expand) / 2.0; |
---|
975 | } |
---|
976 | for (i = 0; i < (nextnode); i++) { |
---|
977 | nodep[i]->xcoord = expand * (nodep[i]->xcoord - minx + leftoflabels); |
---|
978 | nodep[i]->ycoord = expand * (nodep[i]->ycoord - miny + bottomoflabels); |
---|
979 | if (grows == horizontal) { |
---|
980 | temp = nodep[i]->ycoord; |
---|
981 | nodep[i]->ycoord = expand * treewidth - nodep[i]->xcoord; |
---|
982 | nodep[i]->xcoord = temp; |
---|
983 | } |
---|
984 | nodep[i]->xcoord += xmargin + extrax; |
---|
985 | nodep[i]->ycoord += ymargin + extray; |
---|
986 | } |
---|
987 | } /* rescale */ |
---|
988 | |
---|
989 | void plottree(p, q) |
---|
990 | node *p, *q; |
---|
991 | { |
---|
992 | /* plot part or all of tree on the plotting device */ |
---|
993 | double x1, y1, x2, y2; |
---|
994 | node *pp; |
---|
995 | |
---|
996 | x2 = xscale * (xoffset + p->xcoord); |
---|
997 | y2 = yscale * (yoffset + p->ycoord); |
---|
998 | if (p != root) { |
---|
999 | x1 = xscale * (xoffset + q->xcoord); |
---|
1000 | y1 = yscale * (yoffset + q->ycoord); |
---|
1001 | plot(penup, x1, y1); |
---|
1002 | plot(pendown, x2, y2); |
---|
1003 | } |
---|
1004 | if (p->tip) |
---|
1005 | return; |
---|
1006 | pp = p->next; |
---|
1007 | while (pp != p) { |
---|
1008 | plottree(pp->back, p); |
---|
1009 | pp = pp->next; |
---|
1010 | } |
---|
1011 | } /* plottree */ |
---|
1012 | |
---|
1013 | |
---|
1014 | void plotlabels(fontname) |
---|
1015 | char *fontname; |
---|
1016 | { |
---|
1017 | long i; |
---|
1018 | double compr, dx, dy, labangle; |
---|
1019 | boolean left, right; |
---|
1020 | node *lp; |
---|
1021 | |
---|
1022 | compr = xunitspercm / yunitspercm; |
---|
1023 | if (penchange == yes) |
---|
1024 | changepen(labelpen); |
---|
1025 | for (i = 0; i < (nextnode); i++) { |
---|
1026 | if (nodep[i]->tip) { |
---|
1027 | lp = nodep[i]; |
---|
1028 | labangle = labelrotation * pi / 180.0; |
---|
1029 | if (labeldirec == radial) |
---|
1030 | labangle = nodep[i]->theta; |
---|
1031 | else if (labeldirec == along) |
---|
1032 | labangle = nodep[i]->oldtheta; |
---|
1033 | if (cos(labangle) < 0.0) |
---|
1034 | labangle -= pi; |
---|
1035 | right = (cos(labangle) * cos(nodep[i]->oldtheta) + |
---|
1036 | sin(labangle) * sin(nodep[i]->oldtheta) > 0.0); |
---|
1037 | left = !right; |
---|
1038 | dx = labelheight * expand * cos(nodep[i]->oldtheta); |
---|
1039 | dy = labelheight * expand * sin(nodep[i]->oldtheta); |
---|
1040 | if (right) { |
---|
1041 | dx += labelheight * expand * 0.5 * firstlet[i] * cos(labangle - 0.75 * pi); |
---|
1042 | dy += labelheight * expand * 0.5 * firstlet[i] * sin(labangle - 0.75 * pi); |
---|
1043 | } |
---|
1044 | if (left) { |
---|
1045 | dx += labelheight * expand * 0.5 * firstlet[i] * cos(labangle - 0.25 * pi); |
---|
1046 | dy += labelheight * expand * 0.5 * firstlet[i] * sin(labangle - 0.25 * pi); |
---|
1047 | dx -= textlength[i] * labelheight * expand * cos(labangle); |
---|
1048 | dy -= textlength[i] * labelheight * expand * sin(labangle); |
---|
1049 | } |
---|
1050 | |
---|
1051 | plottext(lp->nayme, lp->naymlength, |
---|
1052 | labelheight * expand * xscale / compr, compr, |
---|
1053 | xscale * (lp->xcoord + dx + xoffset), |
---|
1054 | yscale * (lp->ycoord + dy + yoffset), -180 * labangle / pi, |
---|
1055 | font,fontname); |
---|
1056 | } |
---|
1057 | } |
---|
1058 | if (penchange == yes) |
---|
1059 | changepen(treepen); |
---|
1060 | } /* plotlabels */ |
---|
1061 | |
---|
1062 | |
---|
1063 | |
---|
1064 | main(argc, argv) |
---|
1065 | int argc; |
---|
1066 | Char *argv[]; |
---|
1067 | { |
---|
1068 | long i,n,stripedepth; |
---|
1069 | char filename1[100]; |
---|
1070 | #ifdef MAC |
---|
1071 | OSErr retcode; |
---|
1072 | FInfo fndrinfo; |
---|
1073 | macsetup("Drawtree","Preview"); |
---|
1074 | #endif |
---|
1075 | #ifdef TURBOC |
---|
1076 | if ((registerbgidriver(EGAVGA_driver) <0) || |
---|
1077 | (registerbgidriver(Herc_driver) <0) || |
---|
1078 | (registerbgidriver(CGA_driver) <0)){ |
---|
1079 | fprintf(stderr,"Graphics error: %s ",grapherrormsg(graphresult())); |
---|
1080 | exit(-1);} |
---|
1081 | #endif |
---|
1082 | strcpy(fontname,"Hershey"); |
---|
1083 | |
---|
1084 | openfile(&plotfile,PLOTFILE,"w",argv[0],pltfilename); |
---|
1085 | openfile(&treefile,TREEFILE,"r",argv[0],NULL); |
---|
1086 | |
---|
1087 | printf("DRAWTREE from PHYLIP version %s\n",VERSION); |
---|
1088 | printf("Reading tree ... \n"); |
---|
1089 | treeread(); |
---|
1090 | printf("Tree has been read.\n"); |
---|
1091 | printf("Loading the font ... \n"); |
---|
1092 | loadfont(font,argv[0]); |
---|
1093 | printf("Font loaded.\n"); |
---|
1094 | previewing = false; |
---|
1095 | initialparms(); |
---|
1096 | |
---|
1097 | canbeplotted = false; |
---|
1098 | while (!canbeplotted) { |
---|
1099 | do { |
---|
1100 | n=showparms(); |
---|
1101 | if ( n != -1) |
---|
1102 | getparms(n); |
---|
1103 | } while (n != -1); |
---|
1104 | calculate(); |
---|
1105 | rescale(); |
---|
1106 | canbeplotted = true; |
---|
1107 | if (preview) |
---|
1108 | canbeplotted=plotpreview(fontname,&xoffset,&yoffset,&scale,ntips,root); |
---|
1109 | } |
---|
1110 | if (dotmatrix) { |
---|
1111 | stripedepth = allocstripe(stripe,(strpwide/8), |
---|
1112 | ((long)(yunitspercm * ysize))); |
---|
1113 | strpdeep = stripedepth; |
---|
1114 | strpdiv = stripedepth; |
---|
1115 | } |
---|
1116 | previewing = false; |
---|
1117 | initplotter(ntips,fontname); |
---|
1118 | numlines = dotmatrix ? ((long)floor(yunitspercm * ysize + 0.5)/strpdeep):1; if (plotter != ibmpc) |
---|
1119 | printf("Writing plot file ...\n"); |
---|
1120 | drawit(fontname,&xoffset,&yoffset,numlines,root); |
---|
1121 | finishplotter(); |
---|
1122 | printf("Finished.\n"); |
---|
1123 | FClose(treefile); |
---|
1124 | FClose(plotfile); |
---|
1125 | printf("End of run.\n"); |
---|
1126 | #ifdef MAC |
---|
1127 | if (plotter == pict){ |
---|
1128 | strcpy(filename1,pltfilename); |
---|
1129 | retcode=GetFInfo(CtoPstr(filename1),0,&fndrinfo); |
---|
1130 | fndrinfo.fdType='PICT'; |
---|
1131 | fndrinfo.fdCreator='MDRW'; |
---|
1132 | strcpy(filename1,pltfilename); |
---|
1133 | retcode=SetFInfo(CtoPstr(PLOTFILE),0,&fndrinfo);} |
---|
1134 | if (plotter == lw){ |
---|
1135 | retcode=GetFInfo(CtoPstr(PLOTFILE),0,&fndrinfo); |
---|
1136 | fndrinfo.fdType='TEXT'; |
---|
1137 | retcode=SetFInfo(CtoPstr(PLOTFILE),0,&fndrinfo);} |
---|
1138 | #endif |
---|
1139 | exit(0); |
---|
1140 | } |
---|
1141 | |
---|
1142 | int eof(f) |
---|
1143 | FILE *f; |
---|
1144 | { |
---|
1145 | register long ch; |
---|
1146 | |
---|
1147 | if (feof(f)) |
---|
1148 | return 1; |
---|
1149 | if (f == stdin) |
---|
1150 | return 0; |
---|
1151 | ch = getc(f); |
---|
1152 | if (ch == EOF) |
---|
1153 | return 1; |
---|
1154 | ungetc(ch, f); |
---|
1155 | return 0; |
---|
1156 | } |
---|
1157 | |
---|
1158 | |
---|
1159 | int eoln(f) |
---|
1160 | FILE *f; |
---|
1161 | { |
---|
1162 | register long ch; |
---|
1163 | |
---|
1164 | ch = getc(f); |
---|
1165 | if (ch == EOF) |
---|
1166 | return 1; |
---|
1167 | ungetc(ch, f); |
---|
1168 | return (ch == '\n'); |
---|
1169 | } |
---|
1170 | |
---|
1171 | |
---|
1172 | void memerror() |
---|
1173 | { |
---|
1174 | printf("Error allocating memory\n"); |
---|
1175 | exit(-1); |
---|
1176 | } |
---|
1177 | |
---|
1178 | MALLOCRETURN *mymalloc(x) |
---|
1179 | long x; |
---|
1180 | { |
---|
1181 | MALLOCRETURN *mem; |
---|
1182 | mem = (MALLOCRETURN *)malloc(x); |
---|
1183 | if (!mem) |
---|
1184 | memerror(); |
---|
1185 | else |
---|
1186 | return (MALLOCRETURN *)mem; |
---|
1187 | } |
---|