# include # include # include # include "ppc_ll.h" # include "ppc_truss.h" # include "ppc_truss_io.h" # include "ppc_truss_to_eps.h" /******************************************************************************/ void arrowdef ( FILE *fp ) /******************************************************************************/ /* Purpose: arrowdef() defines how to draw an arrow. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: FILE *fp: a pointer to the output file. */ { fputs ("% x, y, u, v\n", fp); fputs ("/draw_arrow {\n", fp); fputs ("\t/v exch def\n", fp); fputs ("\t/u exch def\n", fp); fputs ("\t/y exch def\n", fp); fputs ("\t/x exch def\n", fp); fputs ("\t/angle v u atan def\n", fp); fputs ("\t/len u u mul v v mul add sqrt def\n", fp); fputs ("\tgsave\n", fp); fputs ("\tx y translate\n", fp); fputs ("\tlen 100 div dup scale\n", fp); fputs ("\tangle rotate\n", fp); fputs ("\tnewpath\n", fp); fputs ("\t0 0 moveto\n", fp); fputs ("\t70 0 rlineto\n", fp); fputs ("\tstroke\n", fp); fputs ("\tnewpath\n", fp); fputs ("\t70 8 moveto\n", fp); fputs ("\t30 -8 rlineto\n", fp); fputs ("\t-30 -8 rlineto\n", fp); fputs ("\tclosepath\n", fp); fputs ("\tfill\n", fp); fputs ("\tgrestore\n", fp); fputs ("} def\n", fp); fputs ("\n", fp); return; } /******************************************************************************/ void draw_colorscale ( FILE *fp, double height, double smax ) /******************************************************************************/ /* Purpose: draw_colorscale() draws the colorbar in PostScript. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: FILE *fp: a pointer to the output file. double height: ? double smax: ? */ { char buf[32]; int nboxes = 15; double bh = height / nboxes; /* box height */ int i; /* A tickmark for the center (zero) of the color scale */ fputs ( "gsave\n", fp ); fputs ( "1 setlinewidth\n", fp ); fprintf ( fp, "newpath\n" ); fprintf ( fp, "%g %g moveto\n", -0.3*SCALE_WIDTH, height/2 ); fprintf ( fp, "%g %g lineto\n", 1.3*SCALE_WIDTH, height/2 ); fprintf ( fp, "stroke\n" ); fputs ( "grestore\n", fp ); /* Draw the color boxes */ for ( i = 0; i < nboxes; i++ ) { /* 1.0 - (...) to reverse color scale so that blue is on top */ double s = 1.0 - (i+0.5)/nboxes; double r = REDHUE(s); double g = GREENHUE(s); double b = BLUEHUE(s); double y = i*bh; /* bottom of the box */ fprintf ( fp, "newpath\n"); fprintf ( fp, "%g %g moveto\n", 0.0, y); fprintf ( fp, "%g %g rlineto\n", SCALE_WIDTH, 0.0); fprintf ( fp, "%g %g rlineto\n", 0.0, bh); fprintf ( fp, "%g %g rlineto\n", -SCALE_WIDTH, 0.0); fprintf ( fp, "closepath\n"); fprintf ( fp, "%.3f %.3f %.3f setrgbcolor fill\n", r, g, b); } /* Add text. */ fputs ("gsave\n", fp); fputs ("0 setgray\n", fp); fputs ("0 0 translate\n", fp); fprintf (fp, "/Helvetica findfont 8 scalefont setfont\n"); sprintf (buf, "%.2e", -smax); fprintf (fp, "-10 -10 moveto (%s) show\n", buf); sprintf (buf, "%.2e", smax); fprintf (fp, "-10 %g moveto (%s) show\n", height+5, buf); fputs ("90 rotate\n", fp); fprintf (fp, "/Times-Roman findfont 9 scalefont setfont\n"); fprintf (fp, "0 -20 moveto (compression) show\n"); fprintf (fp, "%g -20 moveto (tension) show\n", height -30); fprintf (fp, "%g -23 moveto (0) show\n", height/2 - 2); fputs ("grestore\n", fp); return; } /******************************************************************************/ void fixedsupportdef ( FILE *fp ) /******************************************************************************/ /* Purpose: fixedsupportdef() defines how to draw a fixed support. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: FILE *fp: a pointer to the output file. */ { fputs ("% x, y, rotate\n", fp); fputs ("/draw_fixed_support {\n", fp); fputs ( "\t/angle exch def\n", fp); fputs ( "\t/y exch def\n", fp); fputs ("\t/x exch def\n", fp); fputs ("\t/s 3 sqrt 2 div def\n", fp); fputs ("\t/L 12 def\n", fp); fputs ("\t/R 1.5 def\n", fp); fputs ("\tgsave\n", fp); fputs ("\t1 setlinewidth\n", fp); fputs ("\t0.4 setgray\n", fp); fputs ("\tx y translate\n", fp); fputs ("\tangle rotate\n", fp); fputs ("\tnewpath\n", fp); fputs ("\t0 0 moveto\n", fp); fputs ("\t-0.5 L mul s neg L mul rlineto\n", fp); fputs ("\tL 0 rlineto\n", fp); fputs ("\tclosepath stroke\n", fp); fputs ("\t-0.5 L mul L s mul neg translate\n", fp); fputs ("\tnewpath\n", fp); fputs ("\t0 0 moveto 0 2 R mul neg rlineto\n", fp); fputs ("\tL 0 rlineto 0 2 R mul rlineto\n", fp); fputs ("\tclosepath fill\n", fp); fputs ("\tgrestore\n", fp); fputs ("} def\n", fp); fputs ("\n", fp); return; } /******************************************************************************/ void header ( FILE *fp ) /******************************************************************************/ /* Purpose: header() writes the header for the PostScript file. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: FILE *fp: a pointer to the output file. */ { fputs ("%!PS-Adobe-3.0 EPSF-3.0\n", fp); fputs ("%%Title: (Truss)\n", fp); fputs ("%%Creator: Math 625's truss solver by Rouben Rostamian \n", fp); fputs ("%%BoundingBox: (atend)\n", fp); fputs ("%%DocumentFonts: Times-Roman Times-Bold " "Times-Italic Helvetica\n", fp); fputs ("%%EndComments\n", fp); fputs ("\n", fp); fputs ("% save original state\n", fp); fputs ("/origstate save def\n", fp); fputs ("\n", fp); fputs ("% dictionary\n", fp); fputs ("30 dict begin\n", fp); fputs ("\n", fp); return; } /******************************************************************************/ void hingedef ( FILE *fp ) /******************************************************************************/ /* Purpose: hingedef() defines how to draw a hinged support. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: FILE *fp: a pointer to the output file. */ { fputs ( "% x, y\n", fp); fputs ( "/draw_hinge {\n", fp); fputs ( "\t/y exch def\n", fp); fputs ( "\t/x exch def\n", fp); fputs ( "\tgsave\n", fp); fputs ( "\t1 setlinewidth\n", fp); fputs ( "\t0 setgray\n", fp); fputs ( "\tnewpath x y 2 0 360 arc fill\n", fp); fputs ( "\t1 setgray\n", fp); fputs ( "\tnewpath x y 1 0 360 arc fill\n", fp); fputs ( "\tgrestore\n", fp); fputs ( "} def\n", fp); fputs ( "\n", fp); return; } /******************************************************************************/ float huefunc ( float s ) /******************************************************************************/ /* Purpose: huefunc()... Discussion: Based on Matlab's `jet' colormap. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: float s: Output: float huefunc: */ { if ( s < 0.0 ) { return 0.0; } else if ( s < 16.0 / 64.0 ) { return 4.0 * s; } else if ( s < 33.0 / 64.0 ) { return 1.0; } else if ( s < 49.0 / 64.0 ) { return 1.0 - 4.0 * ( s - 33.0 / 64.0 ); } else { return 0.0; } } /******************************************************************************/ void ppc_truss_to_eps ( struct truss *truss, char *epsfile, int labels ) /******************************************************************************/ /* Purpose: ppc_truss_to_eps() creates an EPS image of a truss structure. Discussion: Receives a pointer to a truss data structure (before or after deformation.) Writes a PostScript file of a drawing of the truss. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: struct truss *truss: Pointer to a truss structure (declared in truss.h). char *epsfile: Name of the output file. int labels: if TR_PLOT_WITH_LABELS, adds node and link labels on the drawing. if TR_PLOT_WITH_NO_LABELS suppresses node and link labels. */ { double bbox_height; double bbox_width; double forcemax; FILE *fp; conscell *p; double scale; double stress_max; double stress_min; double xmax; double xmin; double xwidth; double ymax; double ymin; double ywidth; fp = fopen ( epsfile, "w" ); if ( fp == NULL ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "ppc_truss_to_eps(): Fatal error!\n" ); fprintf ( stderr, " Unable to open file %s for writing\n", epsfile ); return; } /* Calculate min and max stress */ stress_min = ( ( struct link *)truss->links_list->data)->stress; stress_max = stress_min; for ( p = truss->links_list; p != NULL; p = p->next ) { struct link *link = p->data; double s = link->stress; if ( s < stress_min ) { stress_min = s; } else if ( stress_max < s ) { stress_max = s; } } /* Symmetrize, so that center of color scale corresponds to zero. */ stress_max = fmax ( fabs ( stress_min ), fabs ( stress_max ) ); stress_min = - stress_max; /* Calculate range of (x,y) coordiantes and largest applied force. */ xmin = xmax = ( ( struct node *)truss->nodes_list->data)->x; ymin = ymax = ( ( struct node *)truss->nodes_list->data)->y; forcemax = 0.0; for ( p = truss->nodes_list; p != NULL; p = p->next ) { struct node *node = p->data; if ( node->x < xmin ) { xmin = node->x; } else if ( xmax < node->x ) { xmax = node->x; } if ( node->y < ymin ) { ymin = node->y; } else if ( ymax < node->y ) { ymax = node->y; } if ( forcemax < fabs(node->fx) ) { forcemax = fabs(node->fx); } if ( forcemax < fabs(node->fy) ) { forcemax = fabs(node->fy); } } xwidth = xmax - xmin; ywidth = ymax - ymin; scale = TRUSS_SIZE / fmax ( xwidth, ywidth ); bbox_width = xwidth * scale + SCALE_GAP + SCALE_WIDTH + 2 * H_MARGIN; bbox_height = ywidth * scale + 2 * V_MARGIN; /* Header and other initializations. */ header ( fp ); arrowdef ( fp ); hingedef ( fp ); fixedsupportdef ( fp ); rollersupportdef ( fp ); fprintf(fp, "%g %g translate\n", H_MARGIN, V_MARGIN); fprintf(fp, "%d setlinewidth\n", 3); fprintf(fp, "%d setlinecap\n", 1); for ( p = truss->links_list; p != NULL; p = p->next ) { struct link *link = p->data; double s, r, g, b; if ( stress_max == stress_min ) { s = 0.5; } else { s = (link->stress - stress_min) / (stress_max - stress_min); } /* Reverse color scale. */ s = 1.0 - s; r = REDHUE(s); g = GREENHUE(s); b = BLUEHUE(s); fprintf(fp, "%.3f %.3f %.3f setrgbcolor\n", r, g, b); fprintf(fp, "newpath %g %g moveto %g %g lineto stroke\n", (link->np1->x - xmin)*scale, (link->np1->y - ymin)*scale, (link->np2->x - xmin)*scale, (link->np2->y - ymin)*scale); } fputs("0 setgray\n", fp); fprintf(fp, "/Times-Bold findfont 14 scalefont setfont\n"); for ( p = truss->nodes_list; p != NULL; p = p->next ) { struct node *node = p->data; double x = (node->x - xmin)*scale; double y = (node->y - ymin)*scale; if (node->fx != 0 || node->fy != 0) { fprintf(fp, "%g %g %g %g draw_arrow\n", x, y, F_MAX*node->fx/forcemax, F_MAX*node->fy/forcemax); } if (node->xfixed && node->yfixed) { fprintf(fp, "%g %g 0 draw_fixed_support\n", x, y); } else if (node->xfixed) { fprintf(fp, "%g %g 90 draw_roller_support\n", x, y); } else if (node->yfixed) { fprintf(fp, "%g %g 0 draw_roller_support\n", x, y); } fprintf(fp, "%g %g draw_hinge\n", x, y); if ( labels == TR_PLOT_WITH_LABELS ) { fprintf(fp, "%g %g moveto (%d) show\n", x+5, y+5, node->n); } } if ( labels == TR_PLOT_WITH_LABELS ) { fputs ("0.5 setgray\n", fp); fprintf (fp, "/Times-Italic findfont 14 scalefont setfont\n"); for ( p = truss->links_list; p != NULL; p = p->next ) { struct link *link = p->data; double x1 = (link->np1->x - xmin)*scale; double y1 = (link->np1->y - ymin)*scale; double x2 = (link->np2->x - xmin)*scale; double y2 = (link->np2->y - ymin)*scale; double x = 0.4*x1 + 0.6*x2; double y = 0.4*y1 + 0.6*y2; fprintf(fp, "%g %g moveto (%d) show\n", x, y, link->n); } } fprintf (fp, "%g %g translate\n", xwidth*scale + SCALE_GAP, 0.0); draw_colorscale ( fp, ywidth*scale, stress_max ); fputs ("\n", fp); fputs ("showpage\n", fp); fputs ("\n", fp); fputs ("% end dictionary\n", fp); fputs ("end\n", fp); fputs ("\n", fp); fputs ("% restore original state\n", fp); fputs ("origstate restore\n", fp); fputs ("\n", fp); fputs ("%%Trailer\n", fp); fputs ("\n", fp); fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", (int)(0.5+bbox_width), (int)(0.5+bbox_height)); fputs ("%%EOF\n", fp); fclose(fp); return; } /******************************************************************************/ void rollersupportdef ( FILE *fp ) /******************************************************************************/ /* Purpose: rollersupportdef() defines how to draw a roller support. Licensing: This code is distributed under the MIT license. Modified: 14 May 2024 Author: Original C version by Rouben Rostamian; This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 Input: FILE *fp: a pointer to the output file. */ { fputs ("% x, y, rotate\n", fp); fputs ("/draw_roller_support {\n", fp); fputs ("\t/angle exch def\n", fp); fputs ("\t/y exch def\n", fp); fputs ("\t/x exch def\n", fp); fputs ("\t/s 3 sqrt 2 div def\n", fp); fputs ("\t/L 12 def\n", fp); fputs ("\t/R 1.5 def\n", fp); fputs ("\tgsave\n", fp); fputs ("\t1 setlinewidth\n", fp); fputs ("\t0.4 setgray\n", fp); fputs ("\tx y translate\n", fp); fputs ("\tangle rotate\n", fp); fputs ("\tnewpath\n", fp); fputs ("\t0 0 moveto\n", fp); fputs ("\t-0.5 L mul s neg L mul rlineto\n", fp); fputs ("\t0.5 L 0 rlineto\n", fp); fputs ("\tclosepath stroke\n", fp); fputs ("\tL 3 div neg s L mul neg R sub translate\n", fp); fputs ("\tnewpath 0 0 R 0 360 arc stroke\n", fp); fputs ("\tL 3 div 0 translate\n", fp); fputs ("\tnewpath 0 0 R 0 360 arc stroke\n", fp); fputs ("\tL 3 div 0 translate\n", fp); fputs ("\tnewpath 0 0 R 0 360 arc stroke\n", fp); fputs ("\tgrestore\n", fp); fputs ("} def\n", fp); fputs ("\n", fp); return; }