michel@es.ele.tue.nl (& Berkelaar) (10/13/89)
Here is the graph3d graphics package I promised to send to interested people in comp.sources.wanted. Because of the large number of requests (this was my last such offer ever), I post the sources here. I am not the original author, you can find his name and email address in the README file. Please send all bug reports and questions to him. (He knows about me posting this). Don't forget to cut my signature away before unsharring! ------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # If this archive is complete, you will see the following message at the end: # "End of archive 1 (of 3)." # # Contents: # README graph3d.c # # Wrapped by tap@cs.utoronto.ca on Wed Oct 11 23:48:16 1989 # PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(2601 characters\) sed "s/^X//" >README <<'END_OF_README' XGraph3d - a 3d plotting package composed of 4 programs + 2 Xtest-data generating programs. X XCOMPILATION X----------- XCompile the programs by typing "make". X XView the manual pages by typing "nroff -man graph3d.man | more", etc. XThere is a manual page for each of the 6 program. X XCONTENTS X-------- XProcessing programs: X* graph3d X* graph3d-tek X* surface X* pswrap X XTest data generating programs: X* hills X* hat X X* The main program `graph3d' is a 3d version of the standard Xunix utility `graph'. It takes input of 3d points and does Xa projection onto 2d. X X* It can produce output in 3 formats: postscript, input for X`graph', and plot(5) format. Graph3d can be compiled with Xany of the plot(3) libraries to directly produce graphic Xoutput for particular devices. E.g., compiled with the X-l4014 library the program produces output for a tektronics X4014 terminal. This is useful since the output can be sent Xto an Xterm in tektronics mode for plotting. The Makefile Xknows how to build `graph3d-tek'. Graph3d contains various Xfeatures designed to make it work very simply withing the X Xenvironment. X X* Graph3d does hidden line removal by z-sorting and drawing Xfilled polygons. Thus it can produce plots with hidden Xlines removed for postscript output format. (But not for Xplot(5) format since that does not support drawing filled Xpolygons). X X* Graph3d can put up axis, and enclosing boxes, and can Xprint labels in places specified by 3d world points or 2d Xview points. It does NOT do axis with tick marks. X X* A very common thing to want to do is to plot a surface in X3d. The `surface' program takes a 2d matrix and interprets Xit as the description of a 3d surface, producing output for X`graph3d'. For efficiency the default output of surface is Xbinary format so that graph3d does not have to spend alot of Xtime reading real numbers. X X* The fourth program, `pswrap', puts a prologue and trailer Xaround the postscript output from `graph3d'. X X* One test program, `hills', produces random pyramids, and the Xother `hat', produces a hat like surface. The output from Xthese programs must be piped through `surface' before Xgiving it to `graph3d'. X XThese programs have been successfully compiled and run on Xsun3s, sun4s, and mips machines. X XThese programs are copyrighted, but only to prevent others Xfrom copyrighting and restricting access. Feel free to use Xit, change it, delete it, or sell it, but retain the Xcopyright notices. X XSend bugs and/or enhancements to tap@ai.toronto.edu X XTony Plate XDepartment of Computer Science, University of Toronto, X10 Kings College Road, Toronto, XOntario, CANADA M5S 1A4 END_OF_README if test 2601 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi if test -f graph3d.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"graph3d.c\" else echo shar: Extracting \"graph3d.c\" \(49102 characters\) sed "s/^X//" >graph3d.c <<'END_OF_graph3d.c' X/*******************************************************\ X* * X* @(#)graph3d.c 1/2/89 * X* Author: Tony Plate * X* Copyright (C) 1989 Tony Plate * X* This program may be freely distributed and * X* used, provided that this copyright notice is * X* retained intact. There is no warranty with * X* this software. * X* * X\*******************************************************/ X X#include <stdio.h> X#include <math.h> X#include <ctype.h> X Xchar *options_description[] = { X"Options: (an unambiguous substring is sufficient)", X"-2d : just work in 2 dimensions, like graph(1)", X"-3d : work in 3 dimensions (default)", X"-axis : draw an axis on the graph", X"-back : place the origin at the back", X"-border : put a square border around the graph", X"-bounds : print the bounds in the top left corner", X"-box : put a cubic box around the graph", X"-focus D : put the focus at distance D from the centre of the graph", X"-forcetty : write to the tty even if we don't own it", X"-front : place the origin at the front", X"-graph : produce output for graph(1)", X"-help : print this list", X"-hide : do hidden line removal by Z-sorting polygons", X"-label X Y string : put a label at offsets X and Y", X"-left : place the origin at the left", X"-noerase : don't erase the previous drawing, only applies when", X" the -plot option is selected", X"-noinvisibleborder : don't delimit the graph with an invisible border", X"-orient : draw a small labelled axis in the right hand corner", X"-plane D : put the projection plane at distance D from the center", X" of the graph", X"-plot : produce output in plot(5) format", X"-plot-scale S : make the scale for plot output equal to S", X"-ps : produce POSTSCRIPT output", X"-ps-scale S : make the scale for POSTSCRIPT output equal to S", X"-q1 : put the graph in the first quadrant", X"-q2 : put the graph in the second quadrant", X"-q3 : put the graph in the third quadrant", X"-q4 : put the graph in the fourth quadrant", X"-right : place the origin at the right", X"-show-rotations : show the rotations that would be used and", X" exit without drawing any graph", X"-stdout : send output to stdout", X"-tek : same as -plot", X"-tty <hostname>:X : send tektronics output directly to <hostname>:/dev/ttyX", X"-xfraction F : use fraction 0 <= F <=1 of the X dimension of the viewport", X"-xlow X : start using the X viewport at 0 <= X <= 1", X"-xrotation R : rotate the graph in the X plane by R degrees", X"-xscale S : scale the graph in the X direction by S", X"-yfraction F : use fraction 0 <= F <=1 of the Y dimension of the viewport", X"-ylow Y : start using the Y viewport at 0 <= Y <= 1", X"-yrotation R : rotate the graph in the Y plane by R degrees", X"-yscale S : scale the graph in the Y direction by S", X"-zrotation R : rotate the graph in the Z plane by R degrees", X"-zscale S : scale the graph in the Z direction by S", X NULL X}; X X#define DB(X) X#define DBDATA(X) X/* X * This program works as follows: X * (1) Read command line options X * (2) Read data - one point per line, & knows format from first line X * (3) Calculate size of image & the translation needed to put the centre X * of it at the origin. X * (4) Add axis or a box to the list of polygons if they were requested. X * (5) Create a cube & transform it into the viewing coordinates, in X * order to calculate the x & y scale factors neccessary to put X * the image in the viewing rectangle. X * (6) Make the transformations on the list of polygons, perspective is done X * by translating the object so that its centre is at the origin, and X * so that its longest dimension is one. X * Then it is rotated so that the angle of view is parallel with X * the z-axis, and the points are scaled by their position on the z-axis. X * (7) Convert the list of polygons to a vector of polygons (for sorting) X * (8) If hidden line removal is desired, Qsort the vector by z-position X * (9) Print out the polygons in the desired format X */ X Xtypedef float real; X Xtypedef struct SINGLE_POINT { X real x; X real y; X real z; X} SINGLE_POINT; X Xtypedef struct POINT_LIST { X SINGLE_POINT p; X struct POINT_LIST *next; X} POINT_LIST; X Xtypedef struct POINT { X SINGLE_POINT world; X SINGLE_POINT view; X} POINT; X Xtypedef struct POLYGON { X enum {LINE,POLY} type; X int n_points; X POINT *points; X real z_pos; /* for sorting to do hidden line removal */ X char *text; X struct POLYGON *next; X} POLYGON; X Xtypedef struct MIN_MAX { X SINGLE_POINT min; X SINGLE_POINT max; X SINGLE_POINT edge; X} MIN_MAX; X Xtypedef struct TRANSFORM { X real proj_focus; /* distance from the view origin */ X real proj_plane; /* distance in from the focus */ X real x_low; /* in view co-ordinates, [0-1] */ X real x_frac; /* in view co-ordinates, [0-1] */ X real x_view_scale; /* put the tranformed image in the viewport*/ X real x_view_move; X real x_scale; /* supplied scale factor (default 1) */ X real x_move; X real x_rot; X real sin_x_rot; X real cos_x_rot; X real y_low; X real y_frac; X real y_view_scale; X real y_view_move; X real y_scale; X real y_move; X real y_rot; X real sin_y_rot; X real cos_y_rot; X real z_scale; X real z_move; X real z_rot; X real z_view_scale; X real z_view_move; X real sin_z_rot; X real cos_z_rot; X} TRANSFORM; X Xtypedef struct STYLE { X enum {NONE,BOX,AXIS} axis_style; X enum {POST_SCRIPT,PLOT,GRAPH} output_style; X enum {FIRM,SOFT} scale_style; X enum {D2,D3} dimension; X int remove_hidden; X int border; X int bounds; X int invisible_border; X int orient; /* show a little labelled axis set in the corner */ X long ps_scale; X long plot_scale; X int erase; X real x_char_size; X real y_char_size; X} STYLE; X Xchar *my_name; Xint dont_change_out=0; Xchar *use_tty=NULL; XFILE *out; Xint compare_poly(); XPOLYGON **list_to_vec(); Xchar *getenv(); XPOINT_LIST *new_point(); Xchar *strip_quotes(); Xint force_tty = 0; X X#define DEG_TO_RAD(x) ((x) * 3.141592 / 180) X#define MIN(x,y) ( (x) < (y) ? (x) : (y) ) X#define set_min_max(x,min,max) {real internal_temp=(x); if (min>max) min=max=internal_temp; else if (internal_temp<min) min=internal_temp; else if (internal_temp>max) max=internal_temp;} X X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X POLYGON *poly_list,**poly_vec,*label_list,*axis_list; X int n_polys; X TRANSFORM t; X STYLE s; X MIN_MAX min_max; X my_name = argv[0]; X out = stdout; X poly_list = label_list = axis_list = NULL; X read_options(argv,&t,&s,&label_list); X if (s.output_style==PLOT) CheckTekTerminal(); X output_prologue(&t,&s); X n_polys = read_polys(&s,&poly_list,&label_list,stdin); /* read the input */ X find_min_max_world(poly_list,&min_max); /* find the min & max on all dimensions */ X if (s.bounds) add_bounds_label(&min_max,&label_list); X add_axis(&axis_list,&min_max,&t,&s); /* add axis or a box to the list of polygons */ X DB( show_poly_list_world(poly_list); ) X DB( show_min_max(&min_max); ) X calc_view_scale(&t,&min_max,&s); X DB( show_poly_list_world(poly_list); ) X transform_poly_list(poly_list,&t,&s); X transform_poly_list(axis_list,&t,&s); X poly_vec = list_to_vec(poly_list,n_polys); X DB( printf("Label list:\n"); show_poly_list_world(label_list); ) X DB( show_poly_vec_world(n_polys,poly_vec); ) X if (s.remove_hidden) qsort(poly_vec,n_polys,sizeof(POLYGON*),compare_poly); X DB( show_poly_vec_world(n_polys,poly_vec); ) X DB( show_poly_vec_view(n_polys,poly_vec); ) X /* output the axis list before the polygons */ X output_back_axis(axis_list,&s); X output_poly_vec(n_polys,poly_vec,&s); X /* and now output the axis that should be in front */ X output_front_axis(axis_list,&s); X output_label_list(label_list,&t,&s); X if (s.orient) output_orient(&t,&s); X output_epilogue(&t,&s); X} X Xread_options(argv,t,s,label_list) Xchar *argv[]; XTRANSFORM *t; XSTYLE *s; XPOLYGON **label_list; X{ X char *p; X int show_rotations=0; X /* set the rotations to put the origin in the left hand corner */ X t->proj_plane = 1.0; X t->proj_focus = 1.0; X t->x_low = 0.0; X t->x_frac = 1.0; X t->x_rot = -65; X t->x_scale = 1.0; X t->x_view_scale= 1.0; X t->x_view_move= 0.0; X t->y_low = 0.0; X t->y_frac = 1.0; X t->y_rot = 0; X t->y_scale = 1.0; X t->y_view_scale= 1.0; X t->y_view_move= 0.0; X t->z_rot = 30; X t->z_scale = 1.0; X t->z_view_scale= 1.0; X t->z_view_move= 0.0; X s->axis_style = NONE; X s->output_style = PLOT; X s->scale_style = FIRM; X s->dimension = D3; X s->remove_hidden = 0; X s->ps_scale = 10000; X s->plot_scale = 3120; /* just right for tektronics 4014 */ X s->erase = 1; X s->border = 0; X s->bounds = 0; X s->invisible_border = 1; X s->orient = 0; X while (p = *(++argv)) { X if (*p == '-') { X p++; X if (prefix(p,"2d")) { X s->dimension = D2; X t->x_rot = 0; X t->y_rot = 0; X t->z_rot = 0; X } else if (prefix(p,"3d")) { X s->dimension = D3; X } else if (prefix(p,"axis")) { X s->axis_style = AXIS; X } else if (prefix(p,"back")) { X t->x_rot = -65; X t->y_rot = 0; X t->z_rot = 150; X p += 3; X } else if (prefix(p,"border")) { X s->border = 1; X } else if (prefix(p,"bounds")) { X s->bounds = 1; X } else if (prefix(p,"box")) { X s->axis_style = BOX; X } else if (prefix(p,"forcetty")) { X force_tty = 1; X } else if (prefix(p,"focus")) { X if (!*(++argv)) { X fprintf(stderr,"%s: Expected distance after '-focus'\n",my_name); X exit(1); X } X t->proj_focus = atof(*argv); X p += 4; X } else if (prefix(p,"front")) { X t->x_rot = -65; X t->y_rot = 0; X t->z_rot = -30; X p += 4; X } else if (prefix(p,"graph")) { X s->output_style = GRAPH; X } else if (prefix(p,"help")) { X print_options(); X exit(0); X } else if (prefix(p,"hide")) { X s->remove_hidden = 1; X } else if (prefix(p,"label")) { X double x,y; X if (!argv[1] || !argv[2] || !argv[3]) X error("expected 3 more arguments with '-%s'",p); X x = atof(argv[1]); X y = atof(argv[2]); X add_poly(label_list,new_point(NULL,x,y,0.0),NULL,argv[3],0); X argv += 3; X } else if (prefix(p,"left")) { X t->x_rot = -65; X t->y_rot = 0; X t->z_rot = 30; X } else if (prefix(p,"noerase")) { X s->erase = 0; X } else if (prefix(p,"noinvisibleborder")) { X s->invisible_border = 0; X } else if (prefix(p,"orient")) { X s->orient = 1; X } else if (prefix(p,"plane")) { X if (!*(++argv)) error("Expected distance after '-%s'",p); X t->proj_plane = atof(*argv); X } else if (prefix(p,"plot")) { X s->output_style = PLOT; X } else if (prefix(p,"plot-scale")) { X s->output_style = PLOT; X if (!*(++argv)) error("Expected scale factor after '-%s'",p); X s->plot_scale = atoi(*argv); X } else if (prefix(p,"ps")) { X s->output_style = POST_SCRIPT; X } else if (prefix(p,"ps-scale")) { X s->output_style = POST_SCRIPT; X if (!*(++argv)) error("Expected scale factor after '-%s'",p); X s->ps_scale = atoi(*argv); X } else if (prefix(p,"q1")) { X t->x_frac = 0.5; X t->y_frac = 0.5; X t->x_low = 0.0; X t->y_low = 0.5; X } else if (prefix(p,"q2")) { X t->x_frac = 0.5; X t->y_frac = 0.5; X t->x_low = 0.5; X t->y_low = 0.5; X } else if (prefix(p,"q3")) { X t->x_frac = 0.5; X t->y_frac = 0.5; X t->x_low = 0.0; X t->y_low = 0.0; X } else if (prefix(p,"q4")) { X t->x_frac = 0.5; X t->y_frac = 0.5; X t->x_low = 0.5; X t->y_low = 0.0; X } else if (prefix(p,"right")) { X t->x_rot = -65; X t->y_rot = 0; X t->z_rot = -150; X } else if (prefix(p,"show-rotations")) { X show_rotations = 1; X } else if (prefix(p,"stdout")) { X dont_change_out=1; X } else if (prefix(p,"tty")) { X if (!*(++argv)) error("Expected tty name after \"%s\"",p); X use_tty = *argv; X } else if (prefix(p,"tek")) { X s->output_style = PLOT; X } else if (prefix(p,"xfraction")) { X if (!*(++argv)) error("Expected value after '-%s'",p); X t->x_frac = atof(*argv); X } else if (prefix(p,"xlow")) { X if (!*(++argv)) error("Expected value after '-%s'",p); X t->x_low = atof(*argv); X } else if (prefix(p,"xrotation")) { X if (!*(++argv)) error("Expected angle after '-%s'",p); X t->x_rot = atof(*argv); X } else if (prefix(p,"xscale")) { X if (!*(++argv)) error("Expected scale factor after '-%s'",p); X t->x_scale = atof(*argv); X } else if (prefix(p,"yfraction")) { X if (!*(++argv)) error("Expected value after '-%s'",p); X t->y_frac = atof(*argv); X } else if (prefix(p,"ylow")) { X if (!*(++argv)) error("Expected value after '-%s'",p); X t->y_low = atof(*argv); X } else if (prefix(p,"yrotation")) { X if (!*(++argv)) error("Expected angle after '-%s'",p); X t->y_rot = atof(*argv); X } else if (prefix(p,"yscale")) { X if (!*(++argv)) error("Expected scale factor after '-%s'",p); X t->y_scale = atof(*argv); X } else if (prefix(p,"zrotation")) { X if (!*(++argv)) error("Expected angle after '-%s'",p); X t->z_rot = atof(*argv); X } else if (prefix(p,"zscale")) { X if (!*(++argv)) error("Expected scale factor after '-%s'",p); X t->z_scale = atof(*argv); X } else { X goto bad_arg; X } X } else { X bad_arg: X error("Bad argument: '%s'",p); X } X } X t->sin_x_rot = sin(DEG_TO_RAD(t->x_rot)); X t->sin_y_rot = sin(DEG_TO_RAD(t->y_rot)); X t->sin_z_rot = sin(DEG_TO_RAD(t->z_rot)); X t->cos_x_rot = cos(DEG_TO_RAD(t->x_rot)); X t->cos_y_rot = cos(DEG_TO_RAD(t->y_rot)); X t->cos_z_rot = cos(DEG_TO_RAD(t->z_rot)); X switch (s->output_style) { X case POST_SCRIPT: X s->x_char_size = 0.01; X s->y_char_size = 1.0; X break; X case PLOT: X s->x_char_size = 0.014; X s->y_char_size = 0.025; X break; X case GRAPH: X s->x_char_size = 0.01; X s->y_char_size = 0.013; X break; X default: X fprintf(stderr,"%s: bad output_style %d\n",my_name,s->output_style); X exit(1); X } X X/* means no perspective X if (t->proj_plane == 0) { X fprintf(stderr,"%s: cannot have projection plane and focus in the same position\n",my_name); X exit(1); X } X*/ X if ((t->x_frac + t->x_low > 1) || (t->y_frac + t->y_low > 1)) { X fprintf(stderr, X "%s: bad combination of -h & -u or -w & -r values\n",my_name); X exit(1); X } X if (t->y_frac<0 || t->y_frac>1) { X fprintf(stderr,"stderr,%s: bad -h value (Y_FRAC)\n",my_name); X exit(1); X } X if (t->x_frac<0 || t->x_frac>1) { X fprintf(stderr,"%s: bad -w value (X_FRAC)\n",my_name); X exit(1); X } X if (t->y_low<0 || t->y_low>1) { X fprintf(stderr,"%s: bad -u value (Y_LOW)\n",my_name); X exit(1); X } X if (t->x_low<0 || t->x_low>1) { X fprintf(stderr,"%s: bad -r value (X_LOW)\n",my_name); X exit(1); X } X if (show_rotations) { X /* X printf("-focus %g distance of focus from view origin\n",t->proj_focus); X printf("-plane %g distance of the projection plan in from the focus\n",t->proj_plane); X printf("-sx %g x scale factor\n",t->x_scale); X printf("-sy %g y scale factor\n",t->y_scale); X printf("-sz %g z scale factor\n",t->z_scale); X */ X printf("-rx %g x rotation (degrees)\n",t->x_rot); X printf("-ry %g y rotation (degrees)\n",t->y_rot); X printf("-rz %g z rotation (degrees)\n",t->z_rot); X exit(0); X } X} X Xextern char *malloc(),*calloc(); X Xchar *malloc_fail(s) Xint s; X{ X char *p; X p = malloc(s); X if (p==NULL) { X fprintf(stderr,"%s: out of memory (requested %d)\n",my_name,s); X exit(1); X } X return p; X} X Xchar *calloc_fail(s,n) Xint s,n; X{ X char *p; X p = calloc(s,n); X if (p==NULL) { X fprintf(stderr,"%s: out of memory (requested %d x %d)\n",my_name,s,n); X exit(1); X } X return p; X} X XPOINT_LIST *new_point(spare_points,x,y,z) XPOINT_LIST **spare_points; Xreal x,y,z; X{ X POINT_LIST *point; X if (spare_points == NULL || *spare_points == NULL) X point = (POINT_LIST*)malloc_fail(sizeof(POINT_LIST)); X else { X point = *spare_points; X *spare_points = (*spare_points)->next; X } X point->next = NULL; X point->p.x = x; X point->p.y = y; X point->p.z = z; X return point; X} X Xchar *strip_quotes(str) Xchar *str; X{ X char *p; X while (*str==' ' || *str=='\t') str++; X if (*str=='"' || *str=='\'' || *str=='`') str++; X p = str; X while (p[0] && p[1]) p++; X while ((*p==' ' || *p=='\t' || *p=='\n') && p>str) p--; X if (*p!='"' && *p!='\'' && *p!='`') p++; X *p=0; X return str; X} X XPOLYGON *list_to_poly(points,text,last_point,is_poly) XPOINT_LIST *points; Xchar *text; XPOINT_LIST **last_point; Xint is_poly; X{ X int n; X POINT_LIST *p,*lp; X POLYGON *poly; X real z_max; X /* X * count the points X */ X *last_point = NULL; X if (points==NULL) return NULL; X poly = (POLYGON*)malloc_fail(sizeof(POLYGON)); X if (is_poly) X poly->type=POLY; X else X poly->type=LINE; X n = 1; X for (p=points;p->next!=NULL;p = p->next) n++; X if (n>1 && p->p.x==points->p.x && p->p.y==points->p.y && p->p.z==points->p.z) X { poly->type=POLY; n--; } X X poly->n_points = n; X poly->next = NULL; X poly->text = NULL; X if (has_content(text)) { X poly->text = malloc_fail(strlen(text)+1); X strcpy(poly->text,text); X } X poly->points = (POINT*)calloc_fail(sizeof(POINT),n); X z_max = -1e100; X /* X * transfer the points X */ X p=points; X for (n=0;n<poly->n_points;n++) { X poly->points[n].world = p->p; X if (p->p.z > z_max) z_max = p->p.z; X lp = p; X p = p->next; X } X poly->z_pos = z_max; /* z_sum / poly->n_points; */ X *last_point = lp; X return poly; X} X Xhas_content(p) Xchar *p; X{ X if (p==NULL) return 0; X for (;*p!=0;p++) if (!isspace(*p) && isprint(*p)) return 1; X return 0; X} X X/* X * add_poly() X * convert the point list to a vector, make a polygon record, and X * add it to the list of polygons X */ Xint add_poly(poly_list,point_list,spare_points,text,is_poly) XPOLYGON **poly_list; XPOINT_LIST *point_list; XPOINT_LIST **spare_points; Xchar *text; Xint is_poly; X{ X POLYGON *poly; X POINT_LIST *last_point; X if (!point_list) return 0; X poly = list_to_poly(point_list,text,&last_point,is_poly); X if (last_point!=NULL && spare_points != NULL) { X last_point->next = *spare_points; X *spare_points = point_list; X } X if (poly!=NULL) { X poly->next = *poly_list; X *poly_list = poly; X return 1; X } else { X return 0; X } X} X Xchar *find_binary_format_text(str,len,in,record) Xchar *str; XFILE *in; Xint len,record; X{ X char c; X char *t = NULL; X if ((c=getc(in))!='t') { X ungetc(c,in); X return NULL; X } else { X t = str; X while ((*t=getc(in))!=0 && *t!=EOF && *t!='\n') { X t++; X if (t >= str+len) { X fprintf(stderr,"%s: string too long!, point %d\n",my_name,record); X exit(1); X } X } X *t = 0; X return str; X } X} X Xint read_polys(s,poly_list,label_list,in) XSTYLE *s; XPOLYGON **poly_list; XPOLYGON **label_list; XFILE *in; X{ X POINT_LIST *point_list,*point_cur,*spare_points; X float x,y,z; X char str[500],*t,label[500]; X int c; X int n_polys; X int done,n,record; X point_list = point_cur = spare_points = 0; X /* X * The first line tells us the format of the file, it will X * be an ascii line. If it is not recognised, we just read text. X */ X fgets(str,500,in); X n_polys = 0; X record = 0; X if (!strcmp(str,"binary format float4\n")) { X /* X * read a binary format input file X */ X done = 0; X point_list = point_cur = NULL; X while (!done && !feof(in)) { X c = getc(in); X while (c==' ') c = getc(in); X if (c==EOF) break; X str[0] = 0; X record++; X if (c == 'm' || c == 'n') { X if (fread(&x,sizeof(x),1,in)!=1 || fread(&y,sizeof(y),1,in)!=1 || fread(&z,sizeof(z),1,in)!=1) X done = 1; X DB( else printf("%c %g %g %g\n",c,x,y,z); ) X } DB( else printf("%c\n",c); ) X if (!done) { X switch (c) { X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X case '.': /* read a regular point in ascii */ X ungetc(c,in); X t = fgets(str,500,in); X if (s->dimension == D3) X n = sscanf(str," %e %e %e %[^\n]",&x,&y,&z,label); X else { X n = sscanf(str," %e %e %[^\n]",&x,&y,label); X if (n) n++; X z = 0.0; X } X if (n==3) label[0]=0; X DBDATA(fprintf(stderr,"Ascii point, %g %g %g %s\n",x,y,z,label);); X if (n<3) { X fprintf(stderr,"%s: couldn't find 3 numbers on input, point %d\n",my_name,record); X exit(1); X } X /* add another point to the list of points */ X if (point_cur == NULL) X point_list = point_cur = new_point(&spare_points,x,y,z); X else X point_cur = point_cur->next = new_point(&spare_points,x,y,z); X if (n==4) { X n_polys += add_poly(poly_list,point_list,&spare_points,strip_quotes(label),0); X point_list = point_cur = NULL; X } X break; X X case '"': /* read an ascii label */ X ungetc(c,in); X t = fgets(str,500,in); X DBDATA(fprintf(stderr,"Ascii label %s\n",t);); X n_polys += add_poly(poly_list,point_list,&spare_points,strip_quotes(t),0); X point_list = point_cur = NULL; X break; X X case 'j': /* end a polygon and join it back to the first point */ X t = find_binary_format_text(str,500,in,record); X DBDATA(fprintf(stderr,"j record %s\n",t);); X n_polys += add_poly(poly_list,point_list,&spare_points,t,1); X point_list = point_cur = NULL; X break; X X case 'm': /* begin a new point, line or polygon */ X DBDATA(fprintf(stderr,"m record, %g %g %g\n",x,y,z);); X n_polys += add_poly(poly_list,point_list,&spare_points,NULL,0); X point_cur = point_list = new_point(&spare_points,x,y,z); X if (t = find_binary_format_text(str,500,in,record)) { X n_polys += add_poly(poly_list,point_list,&spare_points,t,0); X point_list = point_cur = NULL; X } X break; X X case 'n': /* continue a line */ X DBDATA(fprintf(stderr,"n record, %g %g %g\n",x,y,z);); X if (point_cur == NULL) X point_list = point_cur = new_point(&spare_points,x,y,z); X else X point_cur = point_cur->next = new_point(&spare_points,x,y,z); X break; X X case 'J': /* end a polygon and join it back to the first point - ascii format */ X t = find_binary_format_text(str,500,in,record); X DBDATA(fprintf(stderr,"J record %s\n",t);); X n_polys += add_poly(poly_list,point_list,&spare_points,t,1); X point_list = point_cur = NULL; X break; X X case 'M': /* begin a new point, line or polygon - ascii format */ X t = fgets(str,500,in); X if (t==NULL || sscanf(t," %e %e %e",&x,&y,&z)!=3) { X fprintf(stderr,"%s: bad format on M input, point %d\n",my_name,c,record); X exit(1); X } X DBDATA(fprintf(stderr,"M record, %g %g %g\n",x,y,z);); X n_polys += add_poly(poly_list,point_list,&spare_points,NULL,0); X point_cur = point_list = new_point(&spare_points,x,y,z); X if (t = find_binary_format_text(str,500,in,record)) { X n_polys += add_poly(poly_list,point_list,&spare_points,t,0); X point_list = point_cur = NULL; X } X break; X X case 'N': /* continue a line - ascii format */ X t = fgets(str,500,in); X if (t==NULL || sscanf(t," %e %e %e",&x,&y,&z)!=3) { X fprintf(stderr,"%s: bad format on N input, point %d\n",my_name,c,record); X exit(1); X } X DBDATA(fprintf(stderr,"N record, %g %g %g\n",x,y,z);); X if (point_cur == NULL) X point_list = point_cur = new_point(&spare_points,x,y,z); X else X point_cur = point_cur->next = new_point(&spare_points,x,y,z); X break; X X case 't': /* some text to place at the last point X also causes then end of a line */ X case 'L': /* label in view co-ordinates */ X X ungetc('t',in); X if (t = find_binary_format_text(str,500,in,record)) { X if (sscanf(t,"ABEL: %e %e %[^\n]",&x,&y,label)==3) { X DBDATA(fprintf(stderr,"LABEL record, %g %g %s\n",x,y,label);); X n_polys += add_poly(poly_list,point_list,&spare_points,NULL,0); X z = 0.0; X point_list = new_point(&spare_points,x,y,z); X add_poly(label_list,point_list,&spare_points, X strip_quotes(label),0); X point_list = point_cur = NULL; X } else { X DBDATA(fprintf(stderr,"t record %s\n",t);); X n_polys += add_poly(poly_list,point_list,&spare_points,t,0); X point_list = point_cur = NULL; X } X } else { X fprintf(stderr,"%s: internal error: binary text\n",my_name); X exit(1); X } X break; X default: X fprintf(stderr,"%s: bad format on input, char %d, point %d\n",my_name,c,record); X exit(1); X } X } X } X n_polys += add_poly(poly_list,point_list,&spare_points,NULL,0); X } else { X /* X * read an ascii format input file X */ X do { X record++; X n = sscanf(str,"LABEL: %e %e %[^\n]",&x,&y,label); X if (n>0 && n<3) { X fprintf(stderr,"%s: bad format on label, point %d\n",my_name,record); X exit(1); X } else if (n==3) { X n_polys += add_poly(poly_list,point_list,&spare_points,NULL,0); X z = 0.0; X point_list = new_point(&spare_points,x,y,z); X add_poly(label_list,point_list,&spare_points,strip_quotes(label),0); X point_list = point_cur = NULL; X } else { /* n==0 */ X if (s->dimension == D3) X n = sscanf(str," %e %e %e %[^\n]",&x,&y,&z,label); X else { X n = sscanf(str," %e %e %[^\n]",&x,&y,label); X if (n) n++; X z = 0.0; X } X if (n==0) { X /* X * just a label X */ X n_polys += add_poly(poly_list,point_list,&spare_points,strip_quotes(str),0); X point_list = point_cur = NULL; X } else if (n>=3) { /* add another point to the list of points */ X if (point_cur == NULL) X point_list = point_cur = new_point(&spare_points,x,y,z); X else X point_cur = point_cur->next = new_point(&spare_points,x,y,z); X } else if (n>0) { X fprintf(stderr,"%s: couldn't find 3 numbers on input, line %d\n",my_name,record); X exit(1); X } X if (n==4) { X n_polys += add_poly(poly_list,point_list,&spare_points,strip_quotes(label),0); X point_list = point_cur = NULL; X } X } X } while (fgets(str,500,in)!=NULL); X n_polys += add_poly(poly_list,point_list,&spare_points,NULL,0); X } X return n_polys; X} X Xint compare_poly(poly1,poly2) XPOLYGON **poly1,**poly2; X{ X if ((*poly1)->z_pos < (*poly2)->z_pos) return -1; X if ((*poly1)->z_pos > (*poly2)->z_pos) return 1; X if ((*poly1)->z_pos == (*poly2)->z_pos) return 0; X} X Xshow_poly_vec_world(n_polys,poly_vec) Xint n_polys; XPOLYGON **poly_vec; X{ X int i; X printf("WORLD POLYGON VECTOR:\n"); X for (i=0;i<n_polys;i++) X show_poly_world(poly_vec[i]); X printf("\n"); X} X Xshow_poly_list_world(poly_list) XPOLYGON *poly_list; X{ X POLYGON *poly; X printf("WORLD POLYGON LIST:\n"); X for (poly = poly_list ; poly!=NULL ; poly = poly->next) X show_poly_world(poly); X printf("\n"); X} X Xshow_poly_world(poly) XPOLYGON *poly; X{ X int i; X if (poly==NULL) { X printf("!!! NULL pointer to polygon !!!\n"); X return; X } X printf("World %s, n=%d z=%10g text=\"%s\" (",(poly->type==LINE?"LINE":"POLY"),poly->n_points,poly->z_pos,poly->text); X for (i=0;i<poly->n_points;i++) { X show_single_point(&(poly->points[i].world)); X /* printf("(%g %g %g)",poly->points[i].world.x,poly->points[i].world.y,poly->points[i].world.z); */ X if (i<poly->n_points-1) putchar(' '); X } X printf(")\n"); X} X Xshow_poly_vec_view(n_polys,poly_vec) Xint n_polys; XPOLYGON **poly_vec; X{ X int i; X printf("VIEW POLYGON VECTOR:\n"); X for (i=0;i<n_polys;i++) X show_poly_view(poly_vec[i]); X printf("\n"); X} X Xshow_poly_list_view(poly_list) XPOLYGON *poly_list; X{ X POLYGON *poly; X printf("VIEW POLYGON LIST:\n"); X for (poly = poly_list ; poly!=NULL ; poly = poly->next) X show_poly_view(poly); X printf("\n"); X} X Xshow_poly_view(poly) XPOLYGON *poly; X{ X int i; X if (poly==NULL) { X printf("!!! NULL pointer to polygon !!!\n"); X return; X } X printf("View %s, n=%d z=%6g text=\"%s\" (",(poly->type==LINE?"LINE":"POLY"),poly->n_points,poly->z_pos,poly->text); X for (i=0;i<poly->n_points;i++) { X show_single_point(&(poly->points[i].view)); X /* printf("(%g %g %g)",poly->points[i].view.x,poly->points[i].view.y,poly->points[i].view.z); */ X if (i<poly->n_points-1) putchar(' '); X } X printf(")\n"); X} X Xshow_single_point(p) XSINGLE_POINT *p; X{ X printf("(%g %g %g)",p->x,p->y,p->z); X} X XPOLYGON **list_to_vec(poly_list,n_polys) XPOLYGON *poly_list; Xint n_polys; X{ X int i; X POLYGON **vec; X POLYGON *poly; X vec = (POLYGON**)calloc_fail(sizeof(POLYGON*),n_polys); X for ((poly = poly_list),i=0; poly!=NULL; (poly = poly->next),i++) { X vec[i] = poly; X } X return vec; X} X Xshow_min_max(m) XMIN_MAX *m; X{ X printf("MIN: "); X show_single_point(&(m->min)); X printf("\nMAX: "); X show_single_point(&(m->max)); X printf("\nEDGE: "); X show_single_point(&(m->edge)); X printf("\n"); X} X Xfind_min_max_world(poly_list,m) XPOLYGON *poly_list; XMIN_MAX *m; X{ X POLYGON *poly; X int i; X m->min.x = m->min.y = m->min.z = 1.0; X m->max.x = m->max.y = m->max.z = 0.0; X for (poly = poly_list; poly!=NULL; poly = poly->next) X for (i=0;i<poly->n_points;i++) { X set_min_max(poly->points[i].world.x,m->min.x,m->max.x); X set_min_max(poly->points[i].world.y,m->min.y,m->max.y); X set_min_max(poly->points[i].world.z,m->min.z,m->max.z); X } X m->edge.x = m->max.x - m->min.x; X m->edge.y = m->max.y - m->min.y; X m->edge.z = m->max.z - m->min.z; X} X Xadd_bounds_label(m,label_list) XMIN_MAX *m; XPOLYGON **label_list; X{ X char s[100]; X sprintf(s,"%g -x- %g %g -y- %g %g -z- %g", X m->min.x,m->max.x,m->min.y,m->max.y,m->min.z,m->max.z); X add_poly(label_list,new_point(NULL,1.0,-1.0,0.0),NULL,s,0); X} X Xfind_min_max_view(poly_list,m) XPOLYGON *poly_list; XMIN_MAX *m; X{ X POLYGON *poly; X int i; X m->min.x = m->min.y = m->min.z = 1.0; X m->max.x = m->max.y = m->max.z = 0.0; X for (poly = poly_list; poly!=NULL; poly = poly->next) X for (i=0;i<poly->n_points;i++) { X set_min_max(poly->points[i].view.x,m->min.x,m->max.x); X set_min_max(poly->points[i].view.y,m->min.y,m->max.y); X set_min_max(poly->points[i].view.z,m->min.z,m->max.z); X } X m->edge.x = m->max.x - m->min.x; X m->edge.y = m->max.y - m->min.y; X m->edge.z = m->max.z - m->min.z; X} X Xint add_axis(poly_list,m,t,s) XPOLYGON **poly_list; XMIN_MAX *m; XTRANSFORM *t; XSTYLE *s; X{ X POINT_LIST *point_list,*spare_points; X int n=0; X point_list = spare_points = NULL; X switch (s->axis_style) { X case NONE: X break; X case AXIS: X if (m->max.x > m->min.x) { X point_list = new_point(&spare_points,m->min.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->max.x,m->min.y,m->min.z); X n++; X add_poly(poly_list,point_list,&spare_points,getenv("3D_X_AXIS_LABEL"),0); X } X if (m->max.y > m->min.y) { X point_list = new_point(&spare_points,m->min.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->min.x,m->max.y,m->min.z); X n++; X add_poly(poly_list,point_list,&spare_points,getenv("3D_Y_AXIS_LABEL"),0); X } X if (s->dimension==D3 && m->max.z > m->min.z) { X point_list = new_point(&spare_points,m->min.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->min.x,m->min.y,m->max.z); X n++; X add_poly(poly_list,point_list,&spare_points,getenv("3D_Z_AXIS_LABEL"),0); X } X break; X case BOX: X point_list = new_point(&spare_points,m->min.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->max.x,m->min.y,m->min.z); X add_poly(poly_list,point_list,&spare_points,getenv("3D_X_AXIS_LABEL"),0); X X point_list = new_point(&spare_points,m->min.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->min.x,m->max.y,m->min.z); X add_poly(poly_list,point_list,&spare_points,getenv("3D_Y_AXIS_LABEL"),0); X X point_list = new_point(&spare_points,m->max.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->max.x,m->max.y,m->min.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X point_list = new_point(&spare_points,m->min.x,m->max.y,m->min.z); X point_list->next = new_point(&spare_points,m->max.x,m->max.y,m->min.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X n = 4; X if (s->dimension==D2) break; X X point_list = new_point(&spare_points,m->min.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->min.x,m->min.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,getenv("3D_Z_AXIS_LABEL"),0); X X point_list = new_point(&spare_points,m->max.x,m->min.y,m->min.z); X point_list->next = new_point(&spare_points,m->max.x,m->min.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X point_list = new_point(&spare_points,m->min.x,m->max.y,m->min.z); X point_list->next = new_point(&spare_points,m->min.x,m->max.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X point_list = new_point(&spare_points,m->max.x,m->max.y,m->min.z); X point_list->next = new_point(&spare_points,m->max.x,m->max.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X point_list = new_point(&spare_points,m->min.x,m->min.y,m->max.z); X point_list->next = new_point(&spare_points,m->max.x,m->min.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X point_list = new_point(&spare_points,m->min.x,m->max.y,m->max.z); X point_list->next = new_point(&spare_points,m->max.x,m->max.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X point_list = new_point(&spare_points,m->min.x,m->min.y,m->max.z); X point_list->next = new_point(&spare_points,m->min.x,m->max.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X point_list = new_point(&spare_points,m->max.x,m->min.y,m->max.z); X point_list->next = new_point(&spare_points,m->max.x,m->max.y,m->max.z); X add_poly(poly_list,point_list,&spare_points,NULL,0); X X n=12; X break; X default: X fprintf(stderr,"%s: bad axis style (%d) in add_axis()\n",s->axis_style); X exit(1); X } X return n; X} X Xcalc_view_scale(t,m,s) XTRANSFORM *t; XMIN_MAX *m; XSTYLE *s; X{ X POLYGON *poly; X POINT_LIST *point_list,*point_cur,*spare_points; X MIN_MAX mv; X real edge; X /* X * calculate the translation to put the centre of the object at the origin X */ X t->x_move = -(m->max.x + m->min.x)/2; X t->y_move = -(m->max.y + m->min.y)/2; X t->z_move = -(m->max.z + m->min.z)/2; X edge = sqrt(m->edge.x*m->edge.x + m->edge.y*m->edge.y + m->edge.z*m->edge.z); X t->proj_focus *= 3 * edge; X t->proj_plane *= edge; X poly = NULL; X point_list = point_cur = spare_points = NULL; X point_cur = point_list = new_point(&spare_points,m->min.x,m->min.y,m->min.z); X point_cur = point_cur->next = new_point(&spare_points,m->max.x,m->min.y,m->min.z); X point_cur = point_cur->next = new_point(&spare_points,m->max.x,m->max.y,m->min.z); X point_cur = point_cur->next = new_point(&spare_points,m->max.x,m->max.y,m->max.z); X point_cur = point_cur->next = new_point(&spare_points,m->max.x,m->min.y,m->max.z); X point_cur = point_cur->next = new_point(&spare_points,m->min.x,m->min.y,m->max.z); X point_cur = point_cur->next = new_point(&spare_points,m->min.x,m->max.y,m->max.z); X point_cur = point_cur->next = new_point(&spare_points,m->min.x,m->max.y,m->min.z); X add_poly(&poly,point_list,&spare_points,NULL,0); X transform_poly_list(poly,t,s); X find_min_max_view(poly,&mv); X DB( printf("WORLD CORNER POLY:\n"); show_poly_world(poly); ) X DB( printf("VIEW CORNER POLY:\n"); show_poly_view(poly); ) X DB( printf("VIEW MIN MAX:\n"); show_min_max(&mv); ) X t->x_view_scale = t->x_frac/mv.edge.x; X t->y_view_scale = t->y_frac/mv.edge.y; X if (s->scale_style==FIRM) X t->x_view_scale = t->y_view_scale = MIN(t->x_view_scale,t->y_view_scale); X t->x_view_move = t->x_low; X t->y_view_move = t->y_low; X t->x_view_move -= mv.min.x * t->x_view_scale; X t->y_view_move -= mv.min.y * t->y_view_scale; X /* t->z_view_move -= mv.min.z; */ X /* delete - we just toss away the memory allocated for the points above */ X /* for debugging: */ X DB( transform_poly_list(poly,t,s); ) X DB( printf("RETRANSFORMED VIEW CORNER POLY:\n"); show_poly_view(poly); ) X} X Xtransform_poly_list(p,t,s) XPOLYGON *p; XTRANSFORM *t; XSTYLE *s; X{ X for (;p!=NULL;p = p->next) transform_poly(p,t,s); X} X Xtransform_poly(p,t,s) XPOLYGON *p; XTRANSFORM *t; XSTYLE *s; X{ X real z_sum=0.0; X int i; X for (i=0;i<p->n_points;i++) { X transform_point(p->points+i,t); X z_sum += p->points[i].view.z; X } X p->z_pos = z_sum/p->n_points; X} X Xtransform_point(p,t) XPOINT *p; XTRANSFORM *t; X{ X register real x1,y1,z1,x2,y2,z2; X /* translate & scale to bring object centre to origin */ X x1 = t->x_scale*p->world.x + t->x_move; X y1 = t->y_scale*p->world.y + t->y_move; X z1 = t->z_scale*p->world.z + t->z_move; X /* rotate around y axis */ X z2 = z1*t->cos_y_rot + x1*t->sin_y_rot; X x2 = -z1*t->sin_y_rot + x1*t->cos_y_rot; X y2 = y1; X /* rotate around z axis */ X x1 = x2*t->cos_z_rot + y2*t->sin_z_rot; X y1 = -x2*t->sin_z_rot + y2*t->cos_z_rot; X z1 = z2; X /* rotate around x axis */ X y2 = y1*t->cos_x_rot - z1*t->sin_x_rot; X z2 = y1*t->sin_x_rot + z1*t->cos_x_rot; X x2 = x1; X /* scale according to distance from the projection focus */ X if (t->proj_plane != 0.0) { X p->view.x = (x2 * t->x_view_scale * t->proj_plane/(t->proj_focus-z2)) + t->x_view_move; X p->view.y = (y2 * t->y_view_scale * t->proj_plane/(t->proj_focus-z2)) + t->y_view_move; X } else { X p->view.x = (x2 * t->x_view_scale) + t->x_view_move; X p->view.y = (y2 * t->y_view_scale) + t->y_view_move; X } X p->view.z = z2; X} X Xoutput_prologue(t,s) XTRANSFORM *t; XSTYLE *s; X{ X /* X * prologue X */ X switch (s->output_style) { X case GRAPH: X if (s->border) X fprintf(out,"%.5f %.5f\n%.5f %.5f\n%.5f %.5f\n%.5f %.5f\n%.5f %.5f \" \n", X t->x_low,t->y_low, X t->x_low+t->x_frac,t->y_low, X t->x_low+t->x_frac,t->y_low+t->y_frac, X t->x_low,t->y_low+t->y_frac, X t->x_low,t->y_low); X else if (s->invisible_border) X fprintf(out,"%.5f %.5f \" \n%.5f %.5f \" \n%.5f %.5f \" \n%.5f %.5f \" \n", X t->x_low,t->y_low, X t->x_low+t->x_frac,t->y_low, X t->x_low+t->x_frac,t->y_low+t->y_frac, X t->x_low,t->y_low+t->y_frac); X break; X case POST_SCRIPT: X if (s->border) X fprintf(out,"save %.0f %.0f moveto %.0f %.0f lineto %.0f %.0f lineto %.0f %.0f lineto closepath stroke restore\n", X t->x_low*s->ps_scale,t->y_low*s->ps_scale, X (t->x_low+t->x_frac)*s->ps_scale,t->y_low*s->ps_scale, X (t->x_low+t->x_frac)*s->ps_scale,(t->y_low+t->y_frac)*s->ps_scale, X t->x_low*s->ps_scale,(t->y_low+t->y_frac)*s->ps_scale); X else if (s->invisible_border) X fprintf(out,"save %.0f %.0f moveto %.0f %.0f moveto %.0f %.0f moveto %.0f %.0f moveto restore\n", X t->x_low*s->ps_scale,t->y_low*s->ps_scale, X (t->x_low+t->x_frac)*s->ps_scale,t->y_low*s->ps_scale, X (t->x_low+t->x_frac)*s->ps_scale,(t->y_low+t->y_frac)*s->ps_scale, X t->x_low*s->ps_scale,(t->y_low+t->y_frac)*s->ps_scale); X break; X case PLOT: X openpl(); X pl_space(s); X if (s->erase) erase(); X linemod("solid"); X if (s->border) { X pl_move(s,t->x_low,t->y_low); X pl_cont(s,t->x_low+t->x_frac,t->y_low); X pl_cont(s,t->x_low+t->x_frac,t->y_low+t->y_frac); X pl_cont(s,t->x_low,t->y_low+t->y_frac); X pl_cont(s,t->x_low,t->y_low); X } else if (s->invisible_border) { X pl_move(s,t->x_low,t->y_low); X pl_move(s,t->x_low+t->x_frac,t->y_low); X pl_move(s,t->x_low+t->x_frac,t->y_low+t->y_frac); X pl_move(s,t->x_low,t->y_low+t->y_frac); X } X break; X default: X fprintf(stderr,"%s: bad output style %d\n",s->output_style); X exit(1); X } X} Xoutput_epilogue(t,s) XTRANSFORM *t; XSTYLE *s; X{ X /* X * epilogue X */ X switch (s->output_style) { X case GRAPH: X break; X case POST_SCRIPT: X break; X case PLOT: X pl_move(s,1.0,1.0); /* to put the cursor in the top right */ X closepl(); X break; X default: X fprintf(stderr,"%s: bad output style %d\n",s->output_style); X exit(1); X } X} X Xoutput_poly_vec(n_polys,poly_vec,s) Xint n_polys; XPOLYGON **poly_vec; XSTYLE *s; X{ X int i; X /* X * polygons X */ X for (i=0;i<n_polys;i++) X output_poly(poly_vec[i],s); X} X Xoutput_poly_list(poly,s) XPOLYGON *poly; XSTYLE *s; X{ X for (;poly!=NULL;poly=poly->next) X output_poly(poly,s); X} X Xoutput_poly(poly,s) XPOLYGON *poly; XSTYLE *s; X{ X int j; X switch (s->output_style) { X case GRAPH: X for (j=0;j<poly->n_points;j++) X fprintf(out,"%.5f %.5f%c",poly->points[j].view.x,poly->points[j].view.y, X (poly->type==POLY || j<poly->n_points-1? '\n' : ' ')); X if (poly->type==POLY) X fprintf(out,"%.5f %.5f \"%s\n",poly->points[0].view.x,poly->points[0].view.y,(poly->text==NULL ? " " : poly->text)); X else X fprintf(out,"\"%s\n",(poly->text==NULL ? " " : poly->text)); X break; X case PLOT: X if (poly->n_points>0) { X pl_move(s,poly->points[0].view.x,poly->points[0].view.y); X for (j=1;j<poly->n_points;j++) X pl_cont(s,poly->points[j].view.x,poly->points[j].view.y); X if (poly->type==POLY) X pl_cont(s,poly->points[0].view.x,poly->points[0].view.y); X if (poly->text!=NULL) pl_label(s,poly->text); X } X break; X case POST_SCRIPT: X if (poly->type==POLY) { X if (poly->n_points==3) { X fprintf(out,"%.0f %.0f %.0f %.0f %.0f %.0f %s\n", X poly->points[0].view.x * s->ps_scale,poly->points[0].view.y * s->ps_scale, X poly->points[1].view.x * s->ps_scale,poly->points[1].view.y * s->ps_scale, X poly->points[2].view.x * s->ps_scale,poly->points[2].view.y * s->ps_scale, X (s->remove_hidden ? "trfill" : "tr")); X } else if (poly->n_points==4) { X fprintf(out,"%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %s\n", X poly->points[0].view.x * s->ps_scale,poly->points[0].view.y * s->ps_scale, X poly->points[1].view.x * s->ps_scale,poly->points[1].view.y * s->ps_scale, X poly->points[2].view.x * s->ps_scale,poly->points[2].view.y * s->ps_scale, X poly->points[3].view.x * s->ps_scale,poly->points[3].view.y * s->ps_scale, X (s->remove_hidden ? "sqfill" : "sq")); X } else { X fprintf(out,"save newpath "); X for (j=0;j<poly->n_points;j++) X fprintf(out,"%.0f %.0f %s ", X poly->points[j].view.x * s->ps_scale,poly->points[j].view.y * s->ps_scale, X (j==0 ? "moveto" : "lineto")); X if (s->remove_hidden) X fprintf(out,"closepath gsave 0 setgray stroke grestore gsave 1 setgray fill grestore restore\n"); X else X fprintf(out,"closepath gsave 0 setgray stroke grestore restore\n"); X } X } else { /* LINE */ X fprintf(out,"save newpath "); X for (j=0;j<poly->n_points;j++) X fprintf(out,"%.0f %.0f %s ", X poly->points[j].view.x * s->ps_scale,poly->points[j].view.y * s->ps_scale, X (j==0 ? "moveto" : "lineto")); X fprintf(out,"stroke restore\n"); X } X if (poly->text!=0) { X if (print_ps_string(poly->text)) X fprintf(out," %.0f %.0f text\n", X poly->points[poly->n_points>0 ? poly->n_points-1 : 0].view.x * s->ps_scale, X poly->points[poly->n_points>0 ? poly->n_points-1 : 0].view.y * s->ps_scale); X } X break; X default: X fprintf(stderr,"%s: bad output style %d\n",my_name,s->output_style); X exit(1); X } X} X X Xoutput_label_list(label_list,t,s) XPOLYGON *label_list; XTRANSFORM *t; XSTYLE *s; X{ X POLYGON *poly; X real x,y; X for (poly=label_list;poly!=NULL;poly=poly->next) { X if (poly->n_points==0) { X fprintf(stderr,"%s: label poly has no points!\n",my_name); X exit(1); X } X x = s->x_char_size * poly->points[0].world.x; X y = s->y_char_size * poly->points[0].world.y; X if (x > 0) x += t->x_low; else x = t->x_low + t->x_frac + x; X if (y > 0) y += t->y_low; else y = t->y_low + t->y_frac + y; X switch (s->output_style) { X case GRAPH: X fprintf(out,"%.5f %.5f \"%s\n",x,y,(poly->text==NULL ? " " : poly->text)); X break; X case POST_SCRIPT: X if (print_ps_string(poly->text)) X fprintf(out," %.0f %.0f label\n",poly->points[0].world.x,poly->points[0].world.y); X break; X case PLOT: X pl_move(s,x,y); X pl_label(s,poly->text); X break; X default: X fprintf(stderr,"%s: bad output style %d\n",my_name,s->output_style); X exit(1); X } X } X} X Xint print_ps_string(str) Xchar *str; X{ X if (str!=NULL && has_content(str)) { X putchar('('); X for (;*str;str++) { X if (isprint(*str)) { X if (*str=='(' || *str==')' || (*str=='\\' && str[1]==0)) putchar('\\'); X putchar(*str); X } X } X putchar(')'); X return 1; X } X return 0; X} X X/* X * output_orient - a little-bitty labelled axis in the bottom-right-hand corner X */ Xoutput_orient(t,s) XTRANSFORM *t; XSTYLE *s; X{ X POLYGON *poly_list=NULL; X POINT_LIST *point_list,*point_cur; X POINT_LIST *spare_points=NULL; X MIN_MAX m; X TRANSFORM newt; X point_cur = point_list = new_point(&spare_points,-0.05,-0.05,-0.05); X point_cur = point_cur->next = new_point(&spare_points,0.05,-0.05,-0.05); X add_poly(&poly_list,point_list,&spare_points,"X",0); X point_cur = point_list = new_point(&spare_points,0.04,-0.04,-0.05); X point_cur = point_cur->next = new_point(&spare_points,0.05,-0.05,-0.05); X point_cur = point_cur->next = new_point(&spare_points,0.04,-0.06,-0.05); X add_poly(&poly_list,point_list,&spare_points,NULL,0); X point_cur = point_list = new_point(&spare_points,-0.05,-0.05,-0.05); X point_cur = point_cur->next = new_point(&spare_points,-0.05,-0.05,0.05); X add_poly(&poly_list,point_list,&spare_points,"Z",0); X point_cur = point_list = new_point(&spare_points,-0.04,-0.05,0.04); X point_cur = point_cur->next = new_point(&spare_points,-0.05,-0.05,0.05); X point_cur = point_cur->next = new_point(&spare_points,-0.06,-0.05,0.04); X add_poly(&poly_list,point_list,&spare_points,NULL,0); X point_cur = point_list = new_point(&spare_points,-0.05,-0.05,-0.05); X point_cur = point_cur->next = new_point(&spare_points,-0.05,0.05,-0.05); X add_poly(&poly_list,point_list,&spare_points,"Y",0); X point_cur = point_list = new_point(&spare_points,-0.04,0.04,-0.05); X point_cur = point_cur->next = new_point(&spare_points,-0.05,0.05,-0.05); X point_cur = point_cur->next = new_point(&spare_points,-0.06,0.04,-0.05); X add_poly(&poly_list,point_list,&spare_points,NULL,0); X X /* X * set up a transform record for doing the axis X */ X newt.proj_focus = 0; /* no perspective for this */ X newt.proj_plane = 0; X newt.x_low = t->x_low; X newt.x_frac = t->x_frac; X newt.x_view_scale = 1; X newt.x_view_move = 0; X newt.x_scale = t->x_scale/fabs(t->x_scale); X newt.x_move = 0; X newt.x_rot = t->x_rot; X newt.sin_x_rot = t->sin_x_rot; X newt.cos_x_rot = t->cos_x_rot; X newt.y_low = t->y_low; X newt.y_frac = t->y_frac; X newt.y_view_scale = 1; X newt.y_view_move = 0; X newt.y_scale = t->y_scale/fabs(t->y_scale); X newt.y_move = 0; X newt.y_rot = t->y_rot; X newt.sin_y_rot = t->sin_y_rot; X newt.cos_y_rot = t->cos_y_rot; X newt.z_scale = t->z_scale/fabs(t->z_scale); X newt.z_move = 0; X newt.z_rot = t->z_rot; X newt.z_view_scale = 1; X newt.z_view_move = 0; X newt.sin_z_rot = t->sin_z_rot; X newt.cos_z_rot = t->cos_z_rot; X X transform_poly_list(poly_list,&newt,s); X find_min_max_view(poly_list,&m); X newt.x_view_move = t->x_low+t->x_frac - m.max.x -.02; X newt.y_view_move = t->y_low - m.min.y +.02; X transform_poly_list(poly_list,&newt,s); X output_poly_list(poly_list,s); X} X Xoutput_back_axis(poly_list,s) XPOLYGON *poly_list; XSTYLE *s; X{ X MIN_MAX m; X POLYGON *poly; X int front_is_corner; /* the front z point is a corner rather than the end of an axis */ X find_min_max_view(poly_list,&m); X front_is_corner = 0; X for (poly=poly_list;poly!=NULL;poly=poly->next) X if (poly->n_points>1 X && (poly->points[0].view.z==m.max.z X || poly->points[1].view.z==m.max.z)) X front_is_corner++; X front_is_corner = (front_is_corner > 1); X for (poly=poly_list;poly!=NULL;poly=poly->next) X if (!front_is_corner X || poly->n_points<2 X || (poly->points[0].view.z!=m.max.z && poly->points[1].view.z!=m.max.z)) X output_poly(poly,s); X} X X Xoutput_front_axis(poly_list,s) XPOLYGON *poly_list; XSTYLE *s; X{ X MIN_MAX m; X POLYGON *poly; X int front_is_corner; /* the front z point is a corner rather than the end of an axis */ X find_min_max_view(poly_list,&m); X front_is_corner = 0; X for (poly=poly_list;poly!=NULL;poly=poly->next) X if (poly->n_points>1 X && (poly->points[0].view.z==m.max.z || poly->points[1].view.z==m.max.z)) front_is_corner++; X front_is_corner = (front_is_corner > 1); X for (poly=poly_list;poly!=NULL;poly=poly->next) X if (poly->n_points<2 X || (front_is_corner X && (poly->points[0].view.z==m.max.z || poly->points[1].view.z==m.max.z))) X output_poly(poly,s); X} X Xpl_space(s) XSTYLE *s; X{ X int x0,y0,x1,y1; X x0 = y0 = 0; X x1 = y1 = s->plot_scale; X space(x0,y0,x1,y1); X} X Xpl_move(s,x,y) XSTYLE *s; Xreal x,y; X{ X int x0,y0; X x0 = x * s->plot_scale; X y0 = y * s->plot_scale; X move(x0,y0); X} X Xpl_cont(s,x,y) XSTYLE *s; Xreal x,y; X{ X int x0,y0; X x0 = x * s->plot_scale; X y0 = y * s->plot_scale; X cont(x0,y0); X} X Xpl_point(s,x,y) XSTYLE *s; Xreal x,y; X{ X int x0,y0; X x0 = x * s->plot_scale; X y0 = y * s->plot_scale; X point(x0,y0); X} X Xpl_label(s,t) XSTYLE *s; Xchar *t; X{ X if (t!=NULL && *t) label(t); X} X X/* X * return 1 if prefix is an unambigous prefix of the option 'word' X */ X Xprefix(prefix,word) Xchar *prefix,*word; X{ X int matches,len; X char **option; X len = strlen(prefix); X if (strncmp(prefix,word,len)) return 0; X if (strlen(word) == len) return 1; X /* we've got a prefix match, check for ambiguity */ X matches = 0; X option = options_description; X while (*option) { X if (option[0][0]=='-' && !strncmp(prefix,option[0]+1,len)) X matches++; X option++; X } X if (matches==1) return 1; X else return 0; X} X Xprint_options() X{ X char **p = options_description; X while (*p) printf("%s\n",*p++); X} X Xerror(s,p) X{ X char str[200]; X fprintf(stderr,sprintf(str,"%s: %s\n",my_name,s),p); X exit(1); X} END_OF_graph3d.c if test 49102 -ne `wc -c <graph3d.c`; then echo shar: \"graph3d.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 1 \(of 3\). cp /dev/null ark1isdone MISSING="" for I in 1 2 3 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 3 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- ------------------------------------------------------------------------------- Michel Berkelaar | Email: michel@ele.tue.nl (prefered) Eindhoven University of Technology | ..!mcvax!euteal!michel (old) Dept. of Electrical Engineering | Design Automation Section | P.O. Box 513 | Phone: ... - 31 - 40 - 473345 NL-5600 MB Eindhoven | Fax: ... - 31 - 40 - 448375 The Netherlands | -------------------------------------------------------------------------------