showme.c
上传用户:yflamps
上传日期:2010-04-01
资源大小:155k
文件大小:106k
源码类别:

3D图形编程

开发平台:

C/C++

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /*    ,d88^^o 888                                   o    o                   */
  4. /*    8888    888o^88,  o88^^o Y88b    o    /      d8b  d8b      o88^^8o     */
  5. /*    "Y88b   888  888 d888   b Y88b  d8b  /      d888bdY88b    d888  88b    */
  6. /*     "Y88b, 888  888 8888   8  Y888/Y88b/      / Y88Y Y888b   8888oo888    */
  7. /*    o  8888 888  888 q888   p   Y8/  Y8/      /   YY   Y888b  q888         */
  8. /*    "oo88P" 888  888  "88oo"     Y    Y      /          Y888b  "88oooo"    */
  9. /*                                                                           */
  10. /*  A Display Program for Meshes and More.                                   */
  11. /*  (showme.c)                                                               */
  12. /*                                                                           */
  13. /*  Version 1.6                                                              */
  14. /*  July 28, 2005                                                            */
  15. /*                                                                           */
  16. /*  Copyright 1996, 1998, 2005                                               */
  17. /*  Jonathan Richard Shewchuk                                                */
  18. /*  2360 Woolsey #H                                                          */
  19. /*  Berkeley, California  94705-1927                                         */
  20. /*  jrs@cs.berkeley.edu                                                      */
  21. /*                                                                           */
  22. /*  This program may be freely redistributed under the condition that the    */
  23. /*    copyright notices (including this entire header and the copyright      */
  24. /*    notice printed when the `-h' switch is selected) are not removed, and  */
  25. /*    no compensation is received.  Private, research, and institutional     */
  26. /*    use is free.  You may distribute modified versions of this code UNDER  */
  27. /*    THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE   */
  28. /*    SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE   */
  29. /*    AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR    */
  30. /*    NOTICE IS GIVEN OF THE MODIFICATIONS.  Distribution of this code as    */
  31. /*    part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT  */
  32. /*    WITH THE AUTHOR.  (If you are not directly supplying this code to a    */
  33. /*    customer, and you are instead telling them how they can obtain it for  */
  34. /*    free, then you are not required to make any arrangement with me.)      */
  35. /*                                                                           */
  36. /*  Hypertext instructions for Triangle are available on the Web at          */
  37. /*                                                                           */
  38. /*      http://www.cs.cmu.edu/~quake/showme.html                             */
  39. /*                                                                           */
  40. /*  Show Me was created as part of the Archimedes project in the School of   */
  41. /*    Computer Science at Carnegie Mellon University.  Archimedes is a       */
  42. /*    system for compiling parallel finite element solvers.  For further     */
  43. /*    information, see Anja Feldmann, Omar Ghattas, John R. Gilbert, Gary L. */
  44. /*    Miller, David R. O'Hallaron, Eric J. Schwabe, Jonathan R. Shewchuk,    */
  45. /*    and Shang-Hua Teng.  "Automated Parallel Solution of Unstructured PDE  */
  46. /*    Problems."  To appear in Communications of the ACM, we hope.           */
  47. /*                                                                           */
  48. /*  If you make any improvements to this code, please please please let me   */
  49. /*    know, so that I may obtain the improvements.  Even if you don't change */
  50. /*    the code, I'd still love to hear what it's being used for.             */
  51. /*                                                                           */
  52. /*  Disclaimer:  Neither I nor Carnegie Mellon warrant this code in any way  */
  53. /*    whatsoever.  Use at your own risk.                                     */
  54. /*                                                                           */
  55. /*****************************************************************************/
  56. /* For single precision (which will save some memory and reduce paging),     */
  57. /*   write "#define SINGLE" below.                                           */
  58. /*                                                                           */
  59. /* For double precision (which will allow you to display triangulations of   */
  60. /*   a finer resolution), leave SINGLE undefined.                            */
  61. /* #define SINGLE */
  62. #ifdef SINGLE
  63. #define REAL float
  64. #else
  65. #define REAL double
  66. #endif
  67. /* Maximum number of characters in a file name (including the null).         */
  68. #define FILENAMESIZE 2048
  69. /* Maximum number of characters in a line read from a file (including the    */
  70. /*   null).                                                                  */
  71. #define INPUTLINESIZE 1024
  72. #define STARTWIDTH 414
  73. #define STARTHEIGHT 414
  74. #define MINWIDTH 50
  75. #define MINHEIGHT 50
  76. #define BUTTONHEIGHT 21
  77. #define BUTTONROWS 3
  78. #define PANELHEIGHT (BUTTONHEIGHT * BUTTONROWS)
  79. #define MAXCOLORS 64
  80. #define IMAGE_TYPES 7
  81. #define NOTHING -1
  82. #define NODE 0
  83. #define POLY 1
  84. #define ELE 2
  85. #define EDGE 3
  86. #define PART 4
  87. #define ADJ 5
  88. #define VORO 6
  89. #define STARTEXPLOSION 0.5
  90. #include <stdio.h>
  91. #include <stdlib.h>
  92. #include <string.h>
  93. #include <X11/Xlib.h>
  94. #include <X11/Xutil.h>
  95. #include <X11/Xatom.h>
  96. /* A necessary forward declaration.                                          */
  97. int load_image();
  98. Display *display;
  99. int screen;
  100. Window rootwindow;
  101. Window mainwindow;
  102. Window quitwin;
  103. Window leftwin;
  104. Window rightwin;
  105. Window upwin;
  106. Window downwin;
  107. Window resetwin;
  108. Window pswin;
  109. Window epswin;
  110. Window expwin;
  111. Window exppluswin;
  112. Window expminuswin;
  113. Window widthpluswin;
  114. Window widthminuswin;
  115. Window versionpluswin;
  116. Window versionminuswin;
  117. Window fillwin;
  118. Window nodewin[2];
  119. Window polywin[2];
  120. Window elewin[2];
  121. Window edgewin[2];
  122. Window partwin[2];
  123. Window adjwin[2];
  124. Window voronoiwin[2];
  125. int windowdepth;
  126. XEvent event;
  127. Colormap rootmap;
  128. XFontStruct *font;
  129. int width, height;
  130. int black, white;
  131. int showme_foreground;
  132. GC fontgc;
  133. GC blackfontgc;
  134. GC linegc;
  135. GC trianglegc;
  136. int colors[MAXCOLORS];
  137. XColor rgb[MAXCOLORS];
  138. int color;
  139. int start_image, current_image;
  140. int start_inc, current_inc;
  141. int loweriteration;
  142. int line_width;
  143. int loaded[2][IMAGE_TYPES];
  144. REAL xlo[2][IMAGE_TYPES], ylo[2][IMAGE_TYPES];
  145. REAL xhi[2][IMAGE_TYPES], yhi[2][IMAGE_TYPES];
  146. REAL xscale, yscale;
  147. REAL xoffset, yoffset;
  148. int zoom;
  149. int nodes[2], node_dim[2];
  150. REAL *nodeptr[2];
  151. int polynodes[2], poly_dim[2], polyedges[2], polyholes[2];
  152. REAL *polynodeptr[2], *polyholeptr[2];
  153. int *polyedgeptr[2];
  154. int elems[2], ele_corners[2];
  155. int *eleptr[2];
  156. int edges[2];
  157. int *edgeptr[2];
  158. REAL *normptr[2];
  159. int subdomains[2];
  160. int *partpart[2];
  161. REAL *partcenter[2], *partshift[2];
  162. int adjsubdomains[2];
  163. int *adjptr[2];
  164. int vnodes[2], vnode_dim[2];
  165. REAL *vnodeptr[2];
  166. int vedges[2];
  167. int *vedgeptr[2];
  168. REAL *vnormptr[2];
  169. int firstnumber[2];
  170. int quiet, fillelem, bw_ps, explode;
  171. REAL explosion;
  172. char filename[FILENAMESIZE];
  173. char nodefilename[2][FILENAMESIZE];
  174. char polyfilename[2][FILENAMESIZE];
  175. char elefilename[2][FILENAMESIZE];
  176. char edgefilename[2][FILENAMESIZE];
  177. char partfilename[2][FILENAMESIZE];
  178. char adjfilename[2][FILENAMESIZE];
  179. char vnodefilename[2][FILENAMESIZE];
  180. char vedgefilename[2][FILENAMESIZE];
  181. char *colorname[] = {"aquamarine", "red", "green yellow", "magenta",
  182.                      "yellow", "green", "orange", "blue",
  183.                      "white", "sandy brown", "cyan", "moccasin",
  184.                      "cadet blue", "coral", "cornflower blue", "sky blue",
  185.                      "firebrick", "forest green", "gold", "goldenrod",
  186.                      "gray", "hot pink", "chartreuse", "pale violet red",
  187.                      "indian red", "khaki", "lavender", "light blue",
  188.                      "light gray", "light steel blue", "lime green", "azure",
  189.                      "maroon", "medium aquamarine", "dodger blue", "honeydew",
  190.                      "medium orchid", "medium sea green", "moccasin",
  191.                      "medium slate blue", "medium spring green",
  192.                      "medium turquoise", "medium violet red",
  193.                      "orange red", "chocolate", "light goldenrod",
  194.                      "orchid", "pale green", "pink", "plum",
  195.                      "purple", "salmon", "sea green",
  196.                      "sienna", "slate blue", "spring green",
  197.                      "steel blue", "tan", "thistle", "turquoise",
  198.                      "violet", "violet red", "wheat",
  199.                      "yellow green"};
  200. void syntax()
  201. {
  202.   printf("showme [-bfw_Qh] input_filen");
  203.   printf("    -b  Black and white PostScript (default is color).n");
  204.   printf("    -f  Fill triangles of partitioned mesh with color.n");
  205.   printf("    -w  Set line width to some specified number.n");
  206.   printf("    -Q  Quiet:  No terminal output except errors.n");
  207.   printf("    -h  Help:  Detailed instructions for Show Me.n");
  208.   exit(0);
  209. }
  210. void info()
  211. {
  212.   printf("Show Men");
  213.   printf("A Display Program for Meshes and More.n");
  214.   printf("Version 1.6nn");
  215.   printf(
  216. "Copyright 1996 Jonathan Richard Shewchuk  (bugs/comments to jrs@cs.cmu.edu)n"
  217. );
  218.   printf("School of Computer Science / Carnegie Mellon Universityn");
  219.   printf("5000 Forbes Avenue / Pittsburgh, Pennsylvania  15213-3891n");
  220.   printf(
  221. "Created as part of the Archimedes project (tools for parallel FEM).n");
  222.   printf(
  223. "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.n");
  224.   printf("There is no warranty whatsoever.  Use at your own risk.n");
  225. #ifdef SINGLE
  226.   printf("This executable is compiled for single precision arithmetic.nnn");
  227. #else
  228.   printf("This executable is compiled for double precision arithmetic.nnn");
  229. #endif
  230.   printf(
  231. "Show Me graphically displays the contents of geometric files, especiallyn");
  232.   printf(
  233. "those generated by Triangle, my two-dimensional quality mesh generator andn"
  234. );
  235.   printf(
  236. "Delaunay triangulator.  Show Me can also write images in PostScript form.n");
  237.   printf(
  238. "Show Me is also useful for checking the consistency of the files you createn"
  239. );
  240.   printf(
  241. "as input to Triangle; Show Me does these checks more thoroughly thann");
  242.   printf("Triangle does.  The command syntax is:nn");
  243.   printf("showme [-bfw_Qh] input_filenn");
  244.   printf(
  245. "The underscore indicates that a number should follow the -w switch.n");
  246.   printf(
  247. "input_file may be one of several types of file.  It must have extensionn");
  248.   printf(
  249. ".node, .poly, .ele, .edge, .part, or .adj.  If no extension is provided,n");
  250.   printf(
  251. "Show Me will assume the extension .ele.  A .node file represents a set ofn");
  252.   printf(
  253. "points; a .poly file represents a Planar Straight Line Graph; an .ele filen"
  254. );
  255.   printf(
  256. "(coupled with a .node file) represents the elements of a mesh or then");
  257.   printf(
  258. "triangles of a triangulation; an .edge file (coupled with a .node file)n");
  259.   printf(
  260. "represents a set of edges; a .part file specifies a partition of a mesh;n");
  261.   printf(
  262. "and a .adj file represents the adjacency graph defined by a partition.n");
  263.   printf("n");
  264.   printf("Command Line Switches:n");
  265.   printf("n");
  266.   printf(
  267. "    -b  Makes all PostScript output black and white.  If this switch is notn"
  268. );
  269.   printf(
  270. "        selected, color PostScript is used for partitioned meshes andn");
  271.   printf("        adjacency graphs (.part and .adj files).n");
  272.   printf(
  273. "    -f  On color displays and in color PostScript, displays partitionedn");
  274.   printf(
  275. "        meshes by filling triangles with color, rather than by coloring then"
  276. );
  277.   printf(
  278. "        edges.  This switch will result in a clearer picture if alln");
  279.   printf(
  280. "        triangles are reasonably large, and a less clear picture if smalln");
  281.   printf(
  282. "        triangles are present.  (There is also a button to toggle thisn");
  283.   printf("        behavior.)n");
  284.   printf(
  285. "    -w  Followed by an integer, specifies the line width used in alln");
  286.   printf(
  287. "        images.  (There are also buttons to change the line width.)n");
  288.   printf(
  289. "    -Q  Quiet:  Suppresses all explanation of what Show Me is doing, unlessn"
  290. );
  291.   printf("        an error occurs.n");
  292.   printf("    -h  Help:  Displays these instructions.n");
  293.   printf("n");
  294.   printf("Controls:n");
  295.   printf("n");
  296.   printf(
  297. "  To zoom in on an image, point at the location where you want a closern");
  298.   printf(
  299. "  look, and click the left mouse button.  To zoom out, click the rightn");
  300.   printf(
  301. "  mouse button.  In either case, the point you click on will be centered inn"
  302. );
  303.   printf(
  304. "  the window.  If you want to know the coordinates of a point, click then");
  305.   printf(
  306. "  middle mouse button; the coordinates will be printed on the terminal youn"
  307. );
  308.   printf("  invoked Show Me from.nn");
  309.   printf(
  310. "  If you resize the window, the image will grow or shrink to match.n");
  311.   printf("n");
  312.   printf(
  313. "  There is a panel of control buttons at the bottom of the Show Me window:n"
  314. );
  315.   printf("n");
  316.   printf("  Quit:  Shuts down Show Me.n");
  317.   printf("  <, >, ^, v:  Moves the image in the indicated direction.n");
  318.   printf(
  319. "  Reset: Unzooms and centers the image in the window.  When you switch fromn"
  320. );
  321.   printf(
  322. "    one image to another, the viewing region does not change, so you mayn");
  323.   printf(
  324. "    need to reset the new image to make it fully visible.  This often isn");
  325.   printf(
  326. "    the case when switching between Delaunay triangulations and theirn");
  327.   printf(
  328. "    corresponding Voronoi diagrams, as Voronoi vertices can be far from then"
  329. );
  330.   printf("    initial point set.n");
  331.   printf(
  332. "  Width+, -:  Increases or decreases the width of all lines and points.n");
  333.   printf(
  334. "  Exp, +, -:  These buttons appear only when you are viewing a partitionedn"
  335. );
  336.   printf(
  337. "    mesh (.part file).  `Exp' toggles between an exploded and non-explodedn"
  338. );
  339.   printf(
  340. "    image of the mesh.  The non-exploded image will not show the partitionn"
  341. );
  342.   printf(
  343. "    on a black and white monitor.  `+' and `-' allow you to adjust then");
  344.   printf(
  345. "    spacing between pieces of the mesh to better distinguish them.n");
  346.   printf(
  347. "  Fill:  This button appears only when you are viewing a partitioned meshn");
  348.   printf(
  349. "    (.part file).  It toggles between color-filled triangles and coloredn");
  350.   printf(
  351. "    edges (as the -f switch does).  Filled triangles look better when alln");
  352.   printf(
  353. "    triangles are reasonably large; colored edges look better when theren");
  354.   printf("    are very small triangles present.n");
  355.   printf(
  356. "  PS:  Creates a PostScript file containing the image you are viewing.  Ifn"
  357. );
  358.   printf(
  359. "    the -b switch is selected, all PostScript output will be black andn");
  360.   printf(
  361. "    white; otherwise, .part.ps and .adj.ps files will be color, independentn"
  362. );
  363.   printf(
  364. "    of whether you are using a color monitor.  Normally the output willn");
  365.   printf(
  366. "    preserve the properties of the image you see on the screen, includingn");
  367.   printf(
  368. "    zoom and line width; however, if black and white output is selected (-bn"
  369. );
  370.   printf(
  371. "    switch), partitioned meshes will always be drawn exploded.  The outputn"
  372. );
  373.   printf(
  374. "    file name depends on the image being viewed.  If you want severaln");
  375.   printf(
  376. "    different snapshots (zooming in on different parts) of the same object,n"
  377. );
  378.   printf(
  379. "    you'll have to rename each file after Show Me creates it so that itn");
  380.   printf("    isn't overwritten by the next snapshot.n");
  381.   printf(
  382. "  EPS:  Creates an encapsulated PostScript file, suitable for inclusion inn"
  383. );
  384.   printf(
  385. "    documents.  Otherwise, this button is just like the PS button.  (Then");
  386.   printf(
  387. "    only difference is that .eps files lack a `showpage' command at then");
  388.   printf("    end.)nn");
  389.   printf(
  390. "  There are two nearly-identical rows of buttons that load different imagesn"
  391. );
  392.   printf("  from disk.  Each row contains the following buttons:nn");
  393.   printf("  node:  Loads a .node file.n");
  394.   printf(
  395. "  poly:  Loads a .poly file (and possibly an associated .node file).n");
  396.   printf("  ele:  Loads an .ele file (and associated .node file).n");
  397.   printf("  edge:  Loads an .edge file (and associated .node file).n");
  398.   printf(
  399. "  part:  Loads a .part file (and associated .node and .ele files).n");
  400.   printf(
  401. "  adj:  Loads an .adj file (and associated .node, .ele, and .part files).n");
  402.   printf("  voro:  Loads a .v.node and .v.edge file for a Voronoi diagram.n");
  403.   printf("n");
  404.   printf(
  405. "  Each row represents a different iteration number of the geometry files.n");
  406.   printf(
  407. "  For a full explanation of iteration numbers, read the instructions forn");
  408.   printf(
  409. "  Triangle.  Briefly, iteration numbers are used to allow a user to easilyn"
  410. );
  411.   printf(
  412. "  represent a sequence of related triangulations.  Iteration numbers aren");
  413.   printf(
  414. "  used in the names of geometry files; for instance, mymesh.3.ele is an");
  415.   printf(
  416. "  triangle file with iteration number three, and mymesh.ele has an implicitn"
  417. );
  418.   printf("  iteration number of zero.nn");
  419.   printf(
  420. "  The control buttons at the right end of each row display the twon");
  421.   printf(
  422. "  iterations currently under view.  These buttons can be clicked ton");
  423.   printf(
  424. "  increase or decrease the iteration numbers, and thus conveniently viewn");
  425.   printf("  a sequence of meshes.nn");
  426.   printf(
  427. "  Show Me keeps each file in memory after loading it, but you can forcen");
  428.   printf(
  429. "  Show Me to reread a set of files (for one iteration number) by reclickingn"
  430. );
  431.   printf(
  432. "  the button that corresponds to the current image.  This is convenient ifn"
  433. );
  434.   printf("  you have changed a geometry file.nn");
  435.   printf("File Formats:nn");
  436.   printf(
  437. "  All files may contain comments prefixed by the character '#'.  Points,n");
  438.   printf(
  439. "  segments, holes, triangles, edges, and subdomains must be numberedn");
  440.   printf(
  441. "  consecutively, starting from either 1 or 0.  Whichever you choose, alln");
  442.   printf(
  443. "  input files must be consistent (for any single iteration number); if then"
  444. );
  445.   printf(
  446. "  nodes are numbered from 1, so must be all other objects.  Show Men");
  447.   printf(
  448. "  automatically detects your choice while reading a .node (or .poly) file.n"
  449. );
  450.   printf("  Examples of these file formats are given below.nn");
  451.   printf("  .node files:n");
  452.   printf(
  453. "    First line:  <# of points> <dimension (must be 2)> <# of attributes>n");
  454.   printf(
  455. "                                           <# of boundary markers (0 or 1)>n"
  456. );
  457.   printf(
  458. "    Remaining lines:  <point #> <x> <y> [attributes] [boundary marker]n");
  459.   printf("n");
  460.   printf(
  461. "    The attributes, which are typically floating-point values of physicaln");
  462.   printf(
  463. "    quantities (such as mass or conductivity) associated with the nodes ofn"
  464. );
  465.   printf(
  466. "    a finite element mesh, are ignored by Show Me.  Show Me also ignoresn");
  467.   printf(
  468. "    boundary markers.  See the instructions for Triangle to find out whatn");
  469.   printf("    attributes and boundary markers are.nn");
  470.   printf("  .poly files:n");
  471.   printf(
  472. "    First line:  <# of points> <dimension (must be 2)> <# of attributes>n");
  473.   printf(
  474. "                                           <# of boundary markers (0 or 1)>n"
  475. );
  476.   printf(
  477. "    Following lines:  <point #> <x> <y> [attributes] [boundary marker]n");
  478.   printf("    One line:  <# of segments> <# of boundary markers (0 or 1)>n");
  479.   printf(
  480. "    Following lines:  <segment #> <endpoint> <endpoint> [boundary marker]n");
  481.   printf("    One line:  <# of holes>n");
  482.   printf("    Following lines:  <hole #> <x> <y>n");
  483.   printf("    [Optional additional lines that are ignored]nn");
  484.   printf(
  485. "    A .poly file represents a Planar Straight Line Graph (PSLG), an idean");
  486.   printf(
  487. "    familiar to computational geometers.  By definition, a PSLG is just an");
  488.   printf(
  489. "    list of points and edges.  A .poly file also contains some additionaln");
  490.   printf("    information.nn");
  491.   printf(
  492. "    The first section lists all the points, and is identical to the formatn"
  493. );
  494.   printf(
  495. "    of .node files.  <# of points> may be set to zero to indicate that then"
  496. );
  497.   printf(
  498. "    points are listed in a separate .node file; .poly files produced byn");
  499.   printf(
  500. "    Triangle always have this format.  When Show Me reads such a file, itn");
  501.   printf("    also reads the corresponding .node file.nn");
  502.   printf(
  503. "    The second section lists the segments.  Segments are edges whosen");
  504.   printf(
  505. "    presence in a triangulation produced from the PSLG is enforced.  Eachn");
  506.   printf(
  507. "    segment is specified by listing the indices of its two endpoints.  Thisn"
  508. );
  509.   printf(
  510. "    means that its endpoints must be included in the point list.  Eachn");
  511.   printf(
  512. "    segment, like each point, may have a boundary marker, which is ignoredn"
  513. );
  514.   printf("    by Show Me.nn");
  515.   printf(
  516. "    The third section lists holes and concavities that are desired in anyn");
  517.   printf(
  518. "    triangulation generated from the PSLG.  Holes are specified byn");
  519.   printf("    identifying a point inside each hole.nn");
  520.   printf("  .ele files:n");
  521.   printf(
  522. "    First line:  <# of triangles> <points per triangle> <# of attributes>n");
  523.   printf(
  524. "    Remaining lines:  <triangle #> <point> <point> <point> ... [attributes]n"
  525. );
  526.   printf("n");
  527.   printf(
  528. "    Points are indices into the corresponding .node file.  Show Me ignoresn"
  529. );
  530.   printf(
  531. "    all but the first three points of each triangle; these should be then");
  532.   printf(
  533. "    corners listed in counterclockwise order around the triangle.  Then");
  534.   printf("    attributes are ignored by Show Me.nn");
  535.   printf("  .edge files:n");
  536.   printf("    First line:  <# of edges> <# of boundary markers (0 or 1)>n");
  537.   printf(
  538. "    Following lines:  <edge #> <endpoint> <endpoint> [boundary marker]n");
  539.   printf("n");
  540.   printf(
  541. "    Endpoints are indices into the corresponding .node file.  The boundaryn"
  542. );
  543.   printf("    markers are ignored by Show Me.nn");
  544.   printf(
  545. "    In Voronoi diagrams, one also finds a special kind of edge that is ann");
  546.   printf(
  547. "    infinite ray with only one endpoint.  For these edges, a differentn");
  548.   printf("    format is used:nn");
  549.   printf("        <edge #> <endpoint> -1 <direction x> <direction y>nn");
  550.   printf(
  551. "    The `direction' is a floating-point vector that indicates the directionn"
  552. );
  553.   printf("    of the infinite ray.nn");
  554.   printf("  .part files:n");
  555.   printf("    First line:  <# of triangles> <# of subdomains>n");
  556.   printf("    Remaining lines:  <triangle #> <subdomain #>nn");
  557.   printf(
  558. "    The set of triangles is partitioned by a .part file; each triangle isn");
  559.   printf("    mapped to a subdomain.nn");
  560.   printf("  .adj files:n");
  561.   printf("    First line:  <# of subdomains>n");
  562.   printf("    Remaining lines:  <adjacency matrix entry>nn");
  563.   printf(
  564. "    An .adj file represents adjacencies between subdomains (presumablyn");
  565.   printf("    computed by a partitioner).  The first line is followed byn");
  566.   printf(
  567. "    (subdomains X subdomains) lines, each containing one entry of then");
  568.   printf(
  569. "    adjacency matrix.  A nonzero entry indicates that two subdomains aren");
  570.   printf("    adjacent (share a point).nn");
  571.   printf("Example:nn");
  572.   printf(
  573. "  Here is a sample file `box.poly' describing a square with a square hole:n"
  574. );
  575.   printf("n");
  576.   printf(
  577. "    # A box with eight points in 2D, no attributes, no boundary marker.n");
  578.   printf("    8 2 0 0n");
  579.   printf("    # Outer box has these vertices:n");
  580.   printf("     1   0 0n");
  581.   printf("     2   0 3n");
  582.   printf("     3   3 0n");
  583.   printf("     4   3 3n");
  584.   printf("    # Inner square has these vertices:n");
  585.   printf("     5   1 1n");
  586.   printf("     6   1 2n");
  587.   printf("     7   2 1n");
  588.   printf("     8   2 2n");
  589.   printf("    # Five segments without boundary markers.n");
  590.   printf("    5 0n");
  591.   printf("     1   1 2          # Left side of outer box.n");
  592.   printf("     2   5 7          # Segments 2 through 5 enclose the hole.n");
  593.   printf("     3   7 8n");
  594.   printf("     4   8 6n");
  595.   printf("     5   6 5n");
  596.   printf("    # One hole in the middle of the inner square.n");
  597.   printf("    1n");
  598.   printf("     1   1.5 1.5nn");
  599.   printf(
  600. "  After this PSLG is triangulated by Triangle, the resulting triangulationn"
  601. );
  602.   printf(
  603. "  consists of a .node and .ele file.  Here is the former, `box.1.node',n");
  604.   printf("  which duplicates the points of the PSLG:nn");
  605.   printf("    8  2  0  0n");
  606.   printf("       1    0  0n");
  607.   printf("       2    0  3n");
  608.   printf("       3    3  0n");
  609.   printf("       4    3  3n");
  610.   printf("       5    1  1n");
  611.   printf("       6    1  2n");
  612.   printf("       7    2  1n");
  613.   printf("       8    2  2n");
  614.   printf("    # Generated by triangle -pcBev boxn");
  615.   printf("n");
  616.   printf("  Here is the triangulation file, `box.1.ele'.n");
  617.   printf("n");
  618.   printf("    8  3  0n");
  619.   printf("       1       1     5     6n");
  620.   printf("       2       5     1     3n");
  621.   printf("       3       2     6     8n");
  622.   printf("       4       6     2     1n");
  623.   printf("       5       7     3     4n");
  624.   printf("       6       3     7     5n");
  625.   printf("       7       8     4     2n");
  626.   printf("       8       4     8     7n");
  627.   printf("    # Generated by triangle -pcBev boxnn");
  628.   printf("  Here is the edge file for the triangulation, `box.1.edge'.nn");
  629.   printf("    16  0n");
  630.   printf("       1   1  5n");
  631.   printf("       2   5  6n");
  632.   printf("       3   6  1n");
  633.   printf("       4   1  3n");
  634.   printf("       5   3  5n");
  635.   printf("       6   2  6n");
  636.   printf("       7   6  8n");
  637.   printf("       8   8  2n");
  638.   printf("       9   2  1n");
  639.   printf("      10   7  3n");
  640.   printf("      11   3  4n");
  641.   printf("      12   4  7n");
  642.   printf("      13   7  5n");
  643.   printf("      14   8  4n");
  644.   printf("      15   4  2n");
  645.   printf("      16   8  7n");
  646.   printf("    # Generated by triangle -pcBev boxn");
  647.   printf("n");
  648.   printf(
  649. "  Here's a file `box.1.part' that partitions the mesh into four subdomains.n"
  650. );
  651.   printf("n");
  652.   printf("    8  4n");
  653.   printf("       1    3n");
  654.   printf("       2    3n");
  655.   printf("       3    4n");
  656.   printf("       4    4n");
  657.   printf("       5    1n");
  658.   printf("       6    1n");
  659.   printf("       7    2n");
  660.   printf("       8    2n");
  661.   printf("    # Generated by slice -s4 box.1nn");
  662.   printf(
  663. "  Here's a file `box.1.adj' that represents the resulting adjacencies.n");
  664.   printf("n");
  665.   printf("    4n");
  666.   printf("      9n");
  667.   printf("      2n");
  668.   printf("      2n");
  669.   printf("      0n");
  670.   printf("      2n");
  671.   printf("      9n");
  672.   printf("      0n");
  673.   printf("      2n");
  674.   printf("      2n");
  675.   printf("      0n");
  676.   printf("      9n");
  677.   printf("      2n");
  678.   printf("      0n");
  679.   printf("      2n");
  680.   printf("      2n");
  681.   printf("      9n");
  682.   printf("n");
  683.   printf("Display Speed:n");
  684.   printf("n");
  685.   printf(
  686. "  It is worthwhile to note that .edge files typically plot and print twicen"
  687. );
  688.   printf(
  689. "  as quickly as .ele files, because .ele files cause each internal edge ton"
  690. );
  691.   printf(
  692. "  be drawn twice.  For the same reason, PostScript files created from edgen"
  693. );
  694.   printf("  sets are smaller than those created from triangulations.nn");
  695.   printf("Show Me on the Web:nn");
  696.   printf(
  697. "  To see an illustrated, updated version of these instructions, check outn");
  698.   printf("n");
  699.   printf("    http://www.cs.cmu.edu/~quake/showme.htmln");
  700.   printf("n");
  701.   printf("A Brief Plea:n");
  702.   printf("n");
  703.   printf(
  704. "  If you use Show Me (or Triangle), and especially if you use it ton");
  705.   printf(
  706. "  accomplish real work, I would like very much to hear from you.  A shortn");
  707.   printf(
  708. "  letter or email (to jrs@cs.cmu.edu) describing how you use Show Me (andn");
  709.   printf(
  710. "  its sister programs) will mean a lot to me.  The more people I known");
  711.   printf(
  712. "  are using my programs, the more easily I can justify spending time onn");
  713.   printf(
  714. "  improvements, which in turn will benefit you.  Also, I can put youn");
  715.   printf(
  716. "  on a list to receive email whenever new versions are available.n");
  717.   printf("n");
  718.   printf(
  719. "  If you use a PostScript file generated by Show Me in a publication,n");
  720.   printf("  please include an acknowledgment as well.nn");
  721.   exit(0);
  722. }
  723. void set_filenames(filename, lowermeshnumber)
  724. char *filename;
  725. int lowermeshnumber;
  726. {
  727.   char numberstring[100];
  728.   int i;
  729.   for (i = 0; i < 2; i++) {
  730.     strcpy(nodefilename[i], filename);
  731.     strcpy(polyfilename[i], filename);
  732.     strcpy(elefilename[i], filename);
  733.     strcpy(edgefilename[i], filename);
  734.     strcpy(partfilename[i], filename);
  735.     strcpy(adjfilename[i], filename);
  736.     strcpy(vnodefilename[i], filename);
  737.     strcpy(vedgefilename[i], filename);
  738.     if (lowermeshnumber + i > 0) {
  739.       sprintf(numberstring, ".%d", lowermeshnumber + i);
  740.       strcat(nodefilename[i], numberstring);
  741.       strcat(polyfilename[i], numberstring);
  742.       strcat(elefilename[i], numberstring);
  743.       strcat(edgefilename[i], numberstring);
  744.       strcat(partfilename[i], numberstring);
  745.       strcat(adjfilename[i], numberstring);
  746.       strcat(vnodefilename[i], numberstring);
  747.       strcat(vedgefilename[i], numberstring);
  748.     }
  749.     strcat(nodefilename[i], ".node");
  750.     strcat(polyfilename[i], ".poly");
  751.     strcat(elefilename[i], ".ele");
  752.     strcat(edgefilename[i], ".edge");
  753.     strcat(partfilename[i], ".part");
  754.     strcat(adjfilename[i], ".adj");
  755.     strcat(vnodefilename[i], ".v.node");
  756.     strcat(vedgefilename[i], ".v.edge");
  757.   }
  758. }
  759. void parsecommandline(argc, argv)
  760. int argc;
  761. char **argv;
  762. {
  763.   int increment;
  764.   int meshnumber;
  765.   int i, j;
  766.   quiet = 0;
  767.   fillelem = 0;
  768.   line_width = 1;
  769.   bw_ps = 0;
  770.   start_image = ELE;
  771.   filename[0] = '';
  772.   for (i = 1; i < argc; i++) {
  773.     if (argv[i][0] == '-') {
  774.       for (j = 1; argv[i][j] != ''; j++) {
  775.         if (argv[i][j] == 'f') {
  776.           fillelem = 1;
  777. }
  778.         if (argv[i][j] == 'w') {
  779.           if ((argv[i][j + 1] >= '1') && (argv[i][j + 1] <= '9')) {
  780.             line_width = 0;
  781.             while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
  782.               j++;
  783.               line_width = line_width * 10 + (int) (argv[i][j] - '0');
  784.             }
  785.             if (line_width > 100) {
  786.               printf("Error:  Line width cannot exceed 100.n");
  787.               line_width = 1;
  788.     }
  789.   }
  790. }
  791.         if (argv[i][j] == 'b') {
  792.           bw_ps = 1;
  793. }
  794.         if (argv[i][j] == 'Q') {
  795.           quiet = 1;
  796. }
  797.         if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
  798.             (argv[i][j] == '?')) {
  799.           info();
  800. }
  801.       }
  802.     } else {
  803.       strcpy(filename, argv[i]);
  804.     }
  805.   }
  806.   if (filename[0] == '') {
  807.     syntax();
  808.   }
  809.   if (!strcmp(&filename[strlen(filename) - 5], ".node")) {
  810.     filename[strlen(filename) - 5] = '';
  811.     start_image = NODE;
  812.   }
  813.   if (!strcmp(&filename[strlen(filename) - 5], ".poly")) {
  814.     filename[strlen(filename) - 5] = '';
  815.     start_image = POLY;
  816.   }
  817.   if (!strcmp(&filename[strlen(filename) - 4], ".ele")) {
  818.     filename[strlen(filename) - 4] = '';
  819.     start_image = ELE;
  820.   }
  821.   if (!strcmp(&filename[strlen(filename) - 5], ".edge")) {
  822.     filename[strlen(filename) - 5] = '';
  823.     start_image = EDGE;
  824.   }
  825.   if (!strcmp(&filename[strlen(filename) - 5], ".part")) {
  826.     filename[strlen(filename) - 5] = '';
  827.     start_image = PART;
  828.   }
  829.   if (!strcmp(&filename[strlen(filename) - 4], ".adj")) {
  830.     filename[strlen(filename) - 4] = '';
  831.     start_image = ADJ;
  832.   }
  833.   increment = 0;
  834.   j = 1;
  835.   while (filename[j] != '') {
  836.     if ((filename[j] == '.') && (filename[j + 1] != '')) {
  837.       increment = j + 1;
  838.     }
  839.     j++;
  840.   }
  841.   meshnumber = 0;
  842.   if (increment > 0) {
  843.     j = increment;
  844.     do {
  845.       if ((filename[j] >= '0') && (filename[j] <= '9')) {
  846.         meshnumber = meshnumber * 10 + (int) (filename[j] - '0');
  847.       } else {
  848.         increment = 0;
  849.       }
  850.       j++;
  851.     } while (filename[j] != '');
  852.   }
  853.   if (increment > 0) {
  854.     filename[increment - 1] = '';
  855.   }
  856.   if (meshnumber == 0) {
  857.     start_inc = 0;
  858.     loweriteration = 0;
  859.   } else {
  860.     start_inc = 1;
  861.     loweriteration = meshnumber - 1;
  862.   }
  863.   set_filenames(filename, loweriteration);
  864. }
  865. void free_inc(inc)
  866. int inc;
  867. {
  868.   if (loaded[inc][NODE]) {
  869.     free(nodeptr[inc]);
  870.   }
  871.   if (loaded[inc][POLY]) {
  872.     if (polynodes[inc] > 0) {
  873.       free(polynodeptr[inc]);
  874.     }
  875.     free(polyedgeptr[inc]);
  876.     free(polyholeptr[inc]);
  877.   }
  878.   if (loaded[inc][ELE]) {
  879.     free(eleptr[inc]);
  880.   }
  881.   if (loaded[inc][PART]) {
  882.     free(partpart[inc]);
  883.     free(partcenter[inc]);
  884.     free(partshift[inc]);
  885.   }
  886.   if (loaded[inc][EDGE]) {
  887.     free(edgeptr[inc]);
  888.     free(normptr[inc]);
  889.   }
  890.   if (loaded[inc][ADJ]) {
  891.     free(adjptr[inc]);
  892.   }
  893.   if (loaded[inc][VORO]) {
  894.     free(vnodeptr[inc]);
  895.     free(vedgeptr[inc]);
  896.     free(vnormptr[inc]);
  897.   }
  898. }
  899. void move_inc(inc)
  900. int inc;
  901. {
  902.   int i;
  903.   free_inc(1 - inc);
  904.   for (i = 0; i < IMAGE_TYPES; i++) {
  905.     loaded[1 - inc][i] = loaded[inc][i];
  906.     loaded[inc][i] = 0;
  907.     xlo[1 - inc][i] = xlo[inc][i];
  908.     ylo[1 - inc][i] = ylo[inc][i];
  909.     xhi[1 - inc][i] = xhi[inc][i];
  910.     yhi[1 - inc][i] = yhi[inc][i];
  911.   }
  912.   nodes[1 - inc] = nodes[inc];
  913.   node_dim[1 - inc] = node_dim[inc];
  914.   nodeptr[1 - inc] = nodeptr[inc];
  915.   polynodes[1 - inc] = polynodes[inc];
  916.   poly_dim[1 - inc] = poly_dim[inc];
  917.   polyedges[1 - inc] = polyedges[inc];
  918.   polyholes[1 - inc] = polyholes[inc];
  919.   polynodeptr[1 - inc] = polynodeptr[inc];
  920.   polyedgeptr[1 - inc] = polyedgeptr[inc];
  921.   polyholeptr[1 - inc] = polyholeptr[inc];
  922.   elems[1 - inc] = elems[inc];
  923.   ele_corners[1 - inc] = ele_corners[inc];
  924.   eleptr[1 - inc] = eleptr[inc];
  925.   edges[1 - inc] = edges[inc];
  926.   edgeptr[1 - inc] = edgeptr[inc];
  927.   normptr[1 - inc] = normptr[inc];
  928.   subdomains[1 - inc] = subdomains[inc];
  929.   partpart[1 - inc] = partpart[inc];
  930.   partcenter[1 - inc] = partcenter[inc];
  931.   partshift[1 - inc] = partshift[inc];
  932.   adjsubdomains[1 - inc] = adjsubdomains[inc];
  933.   adjptr[1 - inc] = adjptr[inc];
  934.   vnodes[1 - inc] = vnodes[inc];
  935.   vnode_dim[1 - inc] = vnode_dim[inc];
  936.   vnodeptr[1 - inc] = vnodeptr[inc];
  937.   vedges[1 - inc] = vedges[inc];
  938.   vedgeptr[1 - inc] = vedgeptr[inc];
  939.   vnormptr[1 - inc] = vnormptr[inc];
  940.   firstnumber[1 - inc] = firstnumber[inc];
  941.   firstnumber[inc] = -1;
  942. }
  943. void unload_inc(inc)
  944. int inc;
  945. {
  946.   int i;
  947.   current_image = NOTHING;
  948.   for (i = 0; i < IMAGE_TYPES; i++) {
  949.     loaded[inc][i] = 0;
  950.     firstnumber[inc] = -1;
  951.   }
  952. }
  953. void showme_init()
  954. {
  955.   current_image = NOTHING;
  956.   current_inc = 0;
  957.   explosion = STARTEXPLOSION;
  958.   unload_inc(0);
  959.   unload_inc(1);
  960. }
  961. char *readline(string, infile, infilename)
  962. char *string;
  963. FILE *infile;
  964. char *infilename;
  965. {
  966.   char *result;
  967.   do {
  968.     result = fgets(string, INPUTLINESIZE, infile);
  969.     if (result == (char *) NULL) {
  970.       printf("  Error:  Unexpected end of file in %s.n",
  971.              infilename);
  972.       exit(1);
  973.     }
  974.     while ((*result != '') && (*result != '#')
  975.            && (*result != '.') && (*result != '+') && (*result != '-')
  976.            && ((*result < '0') || (*result > '9'))) {
  977.       result++;
  978.     }
  979.   } while ((*result == '#') || (*result == ''));
  980.   return result;
  981. }
  982. char *findfield(string)
  983. char *string;
  984. {
  985.   char *result;
  986.   result = string;
  987.   while ((*result != '') && (*result != '#')
  988.          && (*result != ' ') && (*result != 't')) {
  989.     result++;
  990.   }
  991.   while ((*result != '') && (*result != '#')
  992.          && (*result != '.') && (*result != '+') && (*result != '-')
  993.          && ((*result < '0') || (*result > '9'))) {
  994.     result++;
  995.   }
  996.   if (*result == '#') {
  997.     *result = '';
  998.   }
  999.   return result;
  1000. }
  1001. int load_node(fname, firstnumber, nodes, dim, ptr, xmin, ymin, xmax, ymax)
  1002. char *fname;
  1003. int *firstnumber;
  1004. int *nodes;
  1005. int *dim;
  1006. REAL **ptr;
  1007. REAL *xmin;
  1008. REAL *ymin;
  1009. REAL *xmax;
  1010. REAL *ymax;
  1011. {
  1012.   FILE *infile;
  1013.   char inputline[INPUTLINESIZE];
  1014.   char *stringptr;
  1015.   int extras;
  1016.   int nodemarks;
  1017.   int index;
  1018.   int nodenumber;
  1019.   int i, j;
  1020.   int smallerr;
  1021.   REAL x, y;
  1022.   *xmin = *ymin = 0.0;
  1023.   *xmax = *ymax = 1.0;
  1024.   if (!quiet) {
  1025.     printf("Opening %s.n", fname);
  1026.   }
  1027.   infile = fopen(fname, "r");
  1028.   if (infile == (FILE *) NULL) {
  1029.     printf("  Error:  Cannot access file %s.n", fname);
  1030.     return 1;
  1031.   }
  1032.   stringptr = readline(inputline, infile, fname);
  1033.   *nodes = (int) strtol (stringptr, &stringptr, 0);
  1034.   if (*nodes < 3) {
  1035.     printf("  Error:  %s contains %d points.n", fname, *nodes);
  1036.     return 1;
  1037.   }
  1038.   stringptr = findfield(stringptr);
  1039.   if (*stringptr == '') {
  1040.     *dim = 2;
  1041.   } else {
  1042.     *dim = (int) strtol (stringptr, &stringptr, 0);
  1043.   }
  1044.   if (*dim < 1) {
  1045.     printf("  Error:  %s has dimensionality %d.n", fname, *dim);
  1046.     return 1;
  1047.   }
  1048.   if (*dim != 2) {
  1049.     printf("  I only understand two-dimensional meshes.n");
  1050.     return 1;
  1051.   }
  1052.   stringptr = findfield(stringptr);
  1053.   if (*stringptr == '') {
  1054.     extras = 0;
  1055.   } else {
  1056.     extras = (int) strtol (stringptr, &stringptr, 0);
  1057.   }
  1058.   if (extras < 0) {
  1059.     printf("  Error:  %s has negative value for number of attributes.n",
  1060.            fname);
  1061.     return 1;
  1062.   }
  1063.   stringptr = findfield(stringptr);
  1064.   if (*stringptr == '') {
  1065.     nodemarks = 0;
  1066.   } else {
  1067.     nodemarks = (int) strtol (stringptr, &stringptr, 0);
  1068.   }
  1069.   if (nodemarks < 0) {
  1070.     printf("  Warning:  %s has negative value for number of point markers.n",
  1071.            fname);
  1072.   }
  1073.   if (nodemarks > 1) {
  1074.     printf(
  1075.    "  Warning:  %s has value greater than one for number of point markers.n",
  1076.            fname);
  1077.   }
  1078.   *ptr = (REAL *) malloc((*nodes + 1) * *dim * sizeof(REAL));
  1079.   if (*ptr == (REAL *) NULL) {
  1080.     printf("  Out of memory.n");
  1081.     return 1;
  1082.   }
  1083.   index = *dim;
  1084.   smallerr = 1;
  1085.   for (i = 0; i < *nodes; i++) {
  1086.     stringptr = readline(inputline, infile, fname);
  1087.     nodenumber = (int) strtol (stringptr, &stringptr, 0);
  1088.     if ((i == 0) && (*firstnumber == -1)) {
  1089.       if (nodenumber == 0) {
  1090.         *firstnumber = 0;
  1091.       } else {
  1092.         *firstnumber = 1;
  1093.       }
  1094.     }
  1095.     if ((nodenumber != *firstnumber + i) && (smallerr)) {
  1096.       printf("  Warning:  Points in %s are not numbered correctlyn", fname);
  1097.       printf("            (starting with point %d).n", *firstnumber + i);
  1098.       smallerr = 0;
  1099.     }
  1100.     for (j = 0; j < *dim; j++) {
  1101.       stringptr = findfield(stringptr);
  1102.       if (*stringptr == '') {
  1103.         printf("Error:  Point %d is missing a coordinate in %s.n",
  1104.                *firstnumber + i, fname);
  1105.         free(*ptr);
  1106.         return 1;
  1107.       }
  1108.       (*ptr)[index++] = (REAL) strtod(stringptr, &stringptr);
  1109.     }
  1110.   }
  1111.   fclose(infile);
  1112.   index = *dim;
  1113.   *xmin = *xmax = (*ptr)[index];
  1114.   *ymin = *ymax = (*ptr)[index + 1];
  1115.   for (i = 2; i <= *nodes; i++) {
  1116.     index += *dim;
  1117.     x = (*ptr)[index];
  1118.     y = (*ptr)[index + 1];
  1119.     if (x < *xmin) {
  1120.       *xmin = x;
  1121.     }
  1122.     if (y < *ymin) {
  1123.       *ymin = y;
  1124.     }
  1125.     if (x > *xmax) {
  1126.       *xmax = x;
  1127.     }
  1128.     if (y > *ymax) {
  1129.       *ymax = y;
  1130.     }
  1131.   }
  1132.   if (*xmin == *xmax) {
  1133.     *xmin -= 0.5;
  1134.     *xmax += 0.5;
  1135.   }
  1136.   if (*ymin == *ymax) {
  1137.     *ymin -= 0.5;
  1138.     *ymax += 0.5;
  1139.   }
  1140.   return 0;
  1141. }
  1142. int load_poly(inc, fname, firstnumber, pnodes, dim, edges, holes, nodeptr,
  1143.               edgeptr, holeptr, xmin, ymin, xmax, ymax)
  1144. int inc;
  1145. char *fname;
  1146. int *firstnumber;
  1147. int *pnodes;
  1148. int *dim;
  1149. int *edges;
  1150. int *holes;
  1151. REAL **nodeptr;
  1152. int **edgeptr;
  1153. REAL **holeptr;
  1154. REAL *xmin;
  1155. REAL *ymin;
  1156. REAL *xmax;
  1157. REAL *ymax;
  1158. {
  1159.   FILE *infile;
  1160.   char inputline[INPUTLINESIZE];
  1161.   char *stringptr;
  1162.   int extras;
  1163.   int nodemarks;
  1164.   int segmentmarks;
  1165.   int index;
  1166.   int nodenumber, edgenumber, holenumber;
  1167.   int maxnode;
  1168.   int i, j;
  1169.   int smallerr;
  1170.   REAL x, y;
  1171.   if (!quiet) {
  1172.     printf("Opening %s.n", fname);
  1173.   }
  1174.   infile = fopen(fname, "r");
  1175.   if (infile == (FILE *) NULL) {
  1176.     printf("  Error:  Cannot access file %s.n", fname);
  1177.     return 1;
  1178.   }
  1179.   stringptr = readline(inputline, infile, fname);
  1180.   *pnodes = (int) strtol (stringptr, &stringptr, 0);
  1181.   if (*pnodes == 0) {
  1182.     if (!loaded[inc][NODE]) {
  1183.       if (load_image(inc, NODE)) {
  1184.         return 1;
  1185.       }
  1186.     }
  1187.     maxnode = nodes[inc];
  1188.     *xmin = xlo[inc][NODE];
  1189.     *ymin = ylo[inc][NODE];
  1190.     *xmax = xhi[inc][NODE];
  1191.     *ymax = yhi[inc][NODE];
  1192.   } else {
  1193.     if (*pnodes < 1) {
  1194.       printf("  Error:  %s contains %d points.n", fname, *pnodes);
  1195.       return 1;
  1196.     }
  1197.     maxnode = *pnodes;
  1198.   }
  1199.   stringptr = findfield(stringptr);
  1200.   if (*stringptr == '') {
  1201.     *dim = 2;
  1202.   } else {
  1203.     *dim = (int) strtol (stringptr, &stringptr, 0);
  1204.   }
  1205.   if (*dim < 1) {
  1206.     printf("  Error:  %s has dimensionality %d.n", fname, *dim);
  1207.     return 1;
  1208.   }
  1209.   if (*dim != 2) {
  1210.     printf("  I only understand two-dimensional .poly files.n");
  1211.     return 1;
  1212.   }
  1213.   stringptr = findfield(stringptr);
  1214.   if (*stringptr == '') {
  1215.     extras = 0;
  1216.   } else {
  1217.     extras = (int) strtol (stringptr, &stringptr, 0);
  1218.   }
  1219.   if (extras < 0) {
  1220.     printf("  Error:  %s has negative value for number of attributes.n",
  1221.            fname);
  1222.     return 1;
  1223.   }
  1224.   stringptr = findfield(stringptr);
  1225.   if (*stringptr == '') {
  1226.     nodemarks = 0;
  1227.   } else {
  1228.     nodemarks = (int) strtol (stringptr, &stringptr, 0);
  1229.   }
  1230.   if (nodemarks < 0) {
  1231.     printf("  Warning:  %s has negative value for number of point markers.n",
  1232.            fname);
  1233.   }
  1234.   if (nodemarks > 1) {
  1235.     printf(
  1236.    "  Warning:  %s has value greater than one for number of point markers.n",
  1237.            fname);
  1238.   }
  1239.   if (*pnodes > 0) {
  1240.     *nodeptr = (REAL *) malloc((*pnodes + 1) * *dim * sizeof(REAL));
  1241.     if (*nodeptr == (REAL *) NULL) {
  1242.       printf("  Out of memory.n");
  1243.       return 1;
  1244.     }
  1245.     index = *dim;
  1246.     smallerr = 1;
  1247.     for (i = 0; i < *pnodes; i++) {
  1248.       stringptr = readline(inputline, infile, fname);
  1249.       nodenumber = (int) strtol (stringptr, &stringptr, 0);
  1250.       if ((i == 0) && (*firstnumber == -1)) {
  1251.         if (nodenumber == 0) {
  1252.           *firstnumber = 0;
  1253.         } else {
  1254.           *firstnumber = 1;
  1255.         }
  1256.       }
  1257.       if ((nodenumber != *firstnumber + i) && (smallerr)) {
  1258.         printf("  Warning:  Points in %s are not numbered correctly.n",
  1259.                fname);
  1260.         printf("            (starting with point %d).n", *firstnumber + i);
  1261.         smallerr = 0;
  1262.       }
  1263.       for (j = 0; j < *dim; j++) {
  1264.         stringptr = findfield(stringptr);
  1265.         if (*stringptr == '') {
  1266.           printf("Error:  Point %d is missing a coordinate in %s.n",
  1267.                  *firstnumber + i, fname);
  1268.           free(*nodeptr);
  1269.           return 1;
  1270.         }
  1271.         (*nodeptr)[index++] = (REAL) strtod(stringptr, &stringptr);
  1272.       }
  1273.     }
  1274.   }
  1275.   stringptr = readline(inputline, infile, fname);
  1276.   *edges = (int) strtol (stringptr, &stringptr, 0);
  1277.   if (*edges < 0) {
  1278.     printf("  Error:  %s contains %d segments.n", fname, *edges);
  1279.     free(*nodeptr);
  1280.     return 1;
  1281.   }
  1282.   stringptr = findfield(stringptr);
  1283.   if (*stringptr == '') {
  1284.     segmentmarks = 0;
  1285.   } else {
  1286.     segmentmarks = (int) strtol (stringptr, &stringptr, 0);
  1287.   }
  1288.   if (segmentmarks < 0) {
  1289.     printf("  Error:  %s has negative value for number of segment markers.n",
  1290.            fname);
  1291.     free(*nodeptr);
  1292.     return 1;
  1293.   }
  1294.   if (segmentmarks > 1) {
  1295.     printf(
  1296.    "  Error:  %s has value greater than one for number of segment markers.n",
  1297.            fname);
  1298.     free(*nodeptr);
  1299.     return 1;
  1300.   }
  1301.   *edgeptr = (int *) malloc(((*edges + 1) << 1) * sizeof(int));
  1302.   if (*edgeptr == (int *) NULL) {
  1303.     printf("  Out of memory.n");
  1304.     free(*nodeptr);
  1305.     return 1;
  1306.   }
  1307.   index = 2;
  1308.   smallerr = 1;
  1309.   for (i = *firstnumber; i < *firstnumber + *edges; i++) {
  1310.     stringptr = readline(inputline, infile, fname);
  1311.     edgenumber = (int) strtol (stringptr, &stringptr, 0);
  1312.     if ((edgenumber != i) && (smallerr)) {
  1313.       printf("  Warning:  Segments in %s are not numbered correctly.n",
  1314.              fname);
  1315.       printf("            (starting with segment %d).n", i);
  1316.       smallerr = 0;
  1317.     }
  1318.     stringptr = findfield(stringptr);
  1319.     if (*stringptr == '') {
  1320.       printf("Error:  Segment %d is missing its endpoints in %s.n", i, fname);
  1321.       free(*nodeptr);
  1322.       free(*edgeptr);
  1323.       return 1;
  1324.     }
  1325.     (*edgeptr)[index] = (int) strtol (stringptr, &stringptr, 0) + 1 -
  1326.                         *firstnumber;
  1327.     if (((*edgeptr)[index] < 1) || ((*edgeptr)[index] > maxnode)) {
  1328.       printf("Error:  Segment %d has invalid endpoint in %s.n", i, fname);
  1329.       return 1;
  1330.     }
  1331.     stringptr = findfield(stringptr);
  1332.     if (*stringptr == '') {
  1333.       printf("Error:  Segment %d is missing an endpoint in %s.n", i, fname);
  1334.       free(*nodeptr);
  1335.       free(*edgeptr);
  1336.       return 1;
  1337.     }
  1338.     (*edgeptr)[index + 1] = (int) strtol (stringptr, &stringptr, 0) + 1 -
  1339.                             *firstnumber;
  1340.     if (((*edgeptr)[index + 1] < 1) || ((*edgeptr)[index + 1] > maxnode)) {
  1341.       printf("Error:  Segment %d has invalid endpoint in %s.n", i, fname);
  1342.       return 1;
  1343.     }
  1344.     index += 2;
  1345.   }
  1346.   stringptr = readline(inputline, infile, fname);
  1347.   *holes = (int) strtol (stringptr, &stringptr, 0);
  1348.   if (*holes < 0) {
  1349.     printf("  Error:  %s contains %d holes.n", fname, *holes);
  1350.     free(*nodeptr);
  1351.     free(*edgeptr);
  1352.     return 1;
  1353.   }
  1354.   *holeptr = (REAL *) malloc((*holes + 1) * *dim * sizeof(REAL));
  1355.   if (*holeptr == (REAL *) NULL) {
  1356.     printf("  Out of memory.n");
  1357.     free(*nodeptr);
  1358.     free(*edgeptr);
  1359.     return 1;
  1360.   }
  1361.   index = *dim;
  1362.   smallerr = 1;
  1363.   for (i = *firstnumber; i < *firstnumber + *holes; i++) {
  1364.     stringptr = readline(inputline, infile, fname);
  1365.     holenumber = (int) strtol (stringptr, &stringptr, 0);
  1366.     if ((holenumber != i) && (smallerr)) {
  1367.       printf("  Warning:  Holes in %s are not numbered correctly.n", fname);
  1368.       printf("            (starting with hole %d).n", i);
  1369.       smallerr = 0;
  1370.     }
  1371.     for (j = 0; j < *dim; j++) {
  1372.       stringptr = findfield(stringptr);
  1373.       if (*stringptr == '') {
  1374.         printf("Error:  Hole %d is missing a coordinate in %s.n", i,
  1375.                fname);
  1376.         free(*nodeptr);
  1377.         free(*edgeptr);
  1378.         free(*holeptr);
  1379.         return 1;
  1380.       }
  1381.       (*holeptr)[index++] = (REAL) strtod(stringptr, &stringptr);
  1382.     }
  1383.   }
  1384.   fclose(infile);
  1385.   if (*pnodes > 0) {
  1386.     index = *dim;
  1387.     *xmin = *xmax = (*nodeptr)[index];
  1388.     *ymin = *ymax = (*nodeptr)[index + 1];
  1389.     for (i = 2; i <= *pnodes; i++) {
  1390.       index += *dim;
  1391.       x = (*nodeptr)[index];
  1392.       y = (*nodeptr)[index + 1];
  1393.       if (x < *xmin) {
  1394.         *xmin = x;
  1395.       }
  1396.       if (y < *ymin) {
  1397.         *ymin = y;
  1398.       }
  1399.       if (x > *xmax) {
  1400.         *xmax = x;
  1401.       }
  1402.       if (y > *ymax) {
  1403.         *ymax = y;
  1404.       }
  1405.     }
  1406.   }
  1407.   index = *dim;
  1408.   for (i = 1; i <= *holes; i++) {
  1409.     x = (*holeptr)[index];
  1410.     y = (*holeptr)[index + 1];
  1411.     if (x < *xmin) {
  1412.       *xmin = x;
  1413.     }
  1414.     if (y < *ymin) {
  1415.       *ymin = y;
  1416.     }
  1417.     if (x > *xmax) {
  1418.       *xmax = x;
  1419.     }
  1420.     if (y > *ymax) {
  1421.       *ymax = y;
  1422.     }
  1423.     index += *dim;
  1424.   }
  1425.   return 0;
  1426. }
  1427. int load_ele(fname, firstnumber, nodes, elems, corners, ptr)
  1428. char *fname;
  1429. int firstnumber;
  1430. int nodes;
  1431. int *elems;
  1432. int *corners;
  1433. int **ptr;
  1434. {
  1435.   FILE *infile;
  1436.   char inputline[INPUTLINESIZE];
  1437.   char *stringptr;
  1438.   int extras;
  1439.   int index;
  1440.   int elemnumber;
  1441.   int i, j;
  1442.   int smallerr;
  1443.   if (!quiet) {
  1444.     printf("Opening %s.n", fname);
  1445.   }
  1446.   infile = fopen(fname, "r");
  1447.   if (infile == (FILE *) NULL) {
  1448.     printf("  Error:  Cannot access file %s.n", fname);
  1449.     return 1;
  1450.   }
  1451.   stringptr = readline(inputline, infile, fname);
  1452.   *elems = (int) strtol (stringptr, &stringptr, 0);
  1453.   if (*elems < 1) {
  1454.     printf("  Error:  %s contains %d triangles.n", fname, *elems);
  1455.     return 1;
  1456.   }
  1457.   stringptr = findfield(stringptr);
  1458.   if (*stringptr == '') {
  1459.     *corners = 3;
  1460.   } else {
  1461.     *corners = (int) strtol (stringptr, &stringptr, 0);
  1462.   }
  1463.   if (*corners < 3) {
  1464.     printf("  Error:  Triangles in %s have only %d corners.n", fname,
  1465.            *corners);
  1466.     return 1;
  1467.   }
  1468.   stringptr = findfield(stringptr);
  1469.   if (*stringptr == '') {
  1470.     extras = 0;
  1471.   } else {
  1472.     extras = (int) strtol (stringptr, &stringptr, 0);
  1473.   }
  1474.   if (extras < 0) {
  1475.     printf("  Error:  %s has negative value for extra fields.n", fname);
  1476.     return 1;
  1477.   }
  1478.   *ptr = (int *) malloc((*elems + 1) * 3 * sizeof(int));
  1479.   if (*ptr == (int *) NULL) {
  1480.     printf("  Out of memory.n");
  1481.     return 1;
  1482.   }
  1483.   index = 3;
  1484.   smallerr = 1;
  1485.   for (i = firstnumber; i < firstnumber + *elems; i++) {
  1486.     stringptr = readline(inputline, infile, fname);
  1487.     elemnumber = (int) strtol (stringptr, &stringptr, 0);
  1488.     if ((elemnumber != i) && (smallerr)) {
  1489.       printf("  Warning:  Triangles in %s are not numbered correctly.n",
  1490.              fname);
  1491.       printf("            (starting with triangle %d).n", i);
  1492.       smallerr = 0;
  1493.     }
  1494.     for (j = 0; j < 3; j++) {
  1495.       stringptr = findfield(stringptr);
  1496.       if (*stringptr == '') {
  1497.         printf("Error:  Triangle %d is missing a corner in %s.n", i, fname);
  1498.         free(*ptr);
  1499.         return 1;
  1500.       }
  1501.       (*ptr)[index] = (int) strtol (stringptr, &stringptr, 0) + 1 -
  1502.                       firstnumber;
  1503.       if (((*ptr)[index] < 1) || ((*ptr)[index] > nodes)) {
  1504.         printf("Error:  Triangle %d has invalid corner in %s.n", i, fname);
  1505.         return 1;
  1506.       }
  1507.       index++;
  1508.     }
  1509.   }
  1510.   fclose(infile);
  1511.   return 0;
  1512. }
  1513. int load_edge(fname, firstnumber, nodes, edges, edgeptr, normptr)
  1514. char *fname;
  1515. int firstnumber;
  1516. int nodes;
  1517. int *edges;
  1518. int **edgeptr;
  1519. REAL **normptr;
  1520. {
  1521.   FILE *infile;
  1522.   char inputline[INPUTLINESIZE];
  1523.   char *stringptr;
  1524.   int index;
  1525.   int edgenumber;
  1526.   int edgemarks;
  1527.   int i;
  1528.   int smallerr;
  1529.   if (!quiet) {
  1530.     printf("Opening %s.n", fname);
  1531.   }
  1532.   infile = fopen(fname, "r");
  1533.     if (infile == (FILE *) NULL) {
  1534.       printf("  Error:  Cannot access file %s.n", fname);
  1535.       return 1;
  1536.     }
  1537.   stringptr = readline(inputline, infile, fname);
  1538.   *edges = (int) strtol (stringptr, &stringptr, 0);
  1539.   if (*edges < 1) {
  1540.     printf("  Error:  %s contains %d edges.n", fname, *edges);
  1541.     return 1;
  1542.   }
  1543.   stringptr = findfield(stringptr);
  1544.   if (*stringptr == '') {
  1545.     edgemarks = 0;
  1546.   } else {
  1547.     edgemarks = (int) strtol (stringptr, &stringptr, 0);
  1548.   }
  1549.   if (edgemarks < 0) {
  1550.     printf("  Error:  %s has negative value for number of edge markers.n",
  1551.            fname);
  1552.     return 1;
  1553.   }
  1554.   if (edgemarks > 1) {
  1555.     printf(
  1556.    "  Error:  %s has value greater than one for number of edge markers.n",
  1557.            fname);
  1558.     return 1;
  1559.   }
  1560.   *edgeptr = (int *) malloc(((*edges + 1) << 1) * sizeof(int));
  1561.   if (*edgeptr == (int *) NULL) {
  1562.     printf("  Out of memory.n");
  1563.     return 1;
  1564.   }
  1565.   *normptr = (REAL *) malloc(((*edges + 1) << 1) * sizeof(REAL));
  1566.   if (*normptr == (REAL *) NULL) {
  1567.     printf("  Out of memory.n");
  1568.     free(*edgeptr);
  1569.     return 1;
  1570.   }
  1571.   index = 2;
  1572.   smallerr = 1;
  1573.   for (i = firstnumber; i < firstnumber + *edges; i++) {
  1574.     stringptr = readline(inputline, infile, fname);
  1575.     edgenumber = (int) strtol (stringptr, &stringptr, 0);
  1576.     if ((edgenumber != i) && (smallerr)) {
  1577.       printf("  Warning:  Edges in %s are not numbered correctly.n", fname);
  1578.       printf("            (starting with edge %d).n", i);
  1579.       smallerr = 0;
  1580.     }
  1581.     stringptr = findfield(stringptr);
  1582.     if (*stringptr == '') {
  1583.       printf("Error:  Edge %d is missing its endpoints in %s.n", i, fname);
  1584.       free(*edgeptr);
  1585.       free(*normptr);
  1586.       return 1;
  1587.     }
  1588.     (*edgeptr)[index] = (int) strtol (stringptr, &stringptr, 0) + 1 -
  1589.                         firstnumber;
  1590.     if (((*edgeptr)[index] < 1) || ((*edgeptr)[index] > nodes)) {
  1591.       printf("Error:  Edge %d has invalid endpoint in %s.n", i, fname);
  1592.       return 1;
  1593.     }
  1594.     stringptr = findfield(stringptr);
  1595.     if (*stringptr == '') {
  1596.       printf("Error:  Edge %d is missing an endpoint in %s.n", i, fname);
  1597.       free(*edgeptr);
  1598.       free(*normptr);
  1599.       return 1;
  1600.     }
  1601.     (*edgeptr)[index + 1] = (int) strtol (stringptr, &stringptr, 0);
  1602.     if ((*edgeptr)[index + 1] == -1) {
  1603.       stringptr = findfield(stringptr);
  1604.       if (*stringptr == '') {
  1605.         printf("Error:  Edge %d is missing its direction in %s.n", i, fname);
  1606.         free(*edgeptr);
  1607.         free(*normptr);
  1608.         return 1;
  1609.       }
  1610.       (*normptr)[index] = (REAL) strtod(stringptr, &stringptr);
  1611.       stringptr = findfield(stringptr);
  1612.       if (*stringptr == '') {
  1613.         printf("Error:  Edge %d is missing a direction coordinate in %s.n",
  1614.                i, fname);
  1615.         free(*edgeptr);
  1616.         free(*normptr);
  1617.         return 1;
  1618.       }
  1619.       (*normptr)[index + 1] = (REAL) strtod(stringptr, &stringptr);
  1620.     } else {
  1621.       (*edgeptr)[index + 1] += 1 - firstnumber;
  1622.       if (((*edgeptr)[index + 1] < 1) || ((*edgeptr)[index + 1] > nodes)) {
  1623.         printf("Error:  Edge %d has invalid endpoint in %s.n", i, fname);
  1624.         return 1;
  1625.       }
  1626.     }
  1627.     index += 2;
  1628.   }
  1629.   fclose(infile);
  1630.   return 0;
  1631. }
  1632. int load_part(fname, dim, firstnumber, elems, nodeptr, eleptr, parts,
  1633.               partition, partcenter, partshift)
  1634. char *fname;
  1635. int dim;
  1636. int firstnumber;
  1637. int elems;
  1638. REAL *nodeptr;
  1639. int *eleptr;
  1640. int *parts;
  1641. int **partition;
  1642. REAL **partcenter;
  1643. REAL **partshift;
  1644. {
  1645.   FILE *infile;
  1646.   char inputline[INPUTLINESIZE];
  1647.   char *stringptr;
  1648.   int partelems;
  1649.   int index;
  1650.   int elemnumber;
  1651.   int i, j;
  1652.   int smallerr;
  1653.   int *partsize;
  1654.   if (!quiet) {
  1655.     printf("Opening %s.n", fname);
  1656.   }
  1657.   infile = fopen(fname, "r");
  1658.   if (infile == (FILE *) NULL) {
  1659.     printf("  Error:  Cannot access file %s.n", fname);
  1660.     return 1;
  1661.   }
  1662.   stringptr = readline(inputline, infile, fname);
  1663.   partelems = (int) strtol (stringptr, &stringptr, 0);
  1664.   if (partelems != elems) {
  1665.     printf(
  1666.       "  Error:  .ele and .part files do not agree on number of triangles.n");
  1667.     return 1;
  1668.   }
  1669.   stringptr = findfield(stringptr);
  1670.   if (*stringptr == '') {
  1671.     *parts = 1;
  1672.   } else {
  1673.     *parts = (int) strtol (stringptr, &stringptr, 0);
  1674.   }
  1675.   if (*parts < 1) {
  1676.     printf("  Error:  %s specifies %d subdomains.n", fname, *parts);
  1677.     return 1;
  1678.   }
  1679.   *partition = (int *) malloc((elems + 1) * sizeof(int));
  1680.   if (*partition == (int *) NULL) {
  1681.     printf("  Out of memory.n");
  1682.     return 1;
  1683.   }
  1684.   smallerr = 1;
  1685.   for (i = firstnumber; i < firstnumber + partelems; i++) {
  1686.     stringptr = readline(inputline, infile, fname);
  1687.     elemnumber = (int) strtol (stringptr, &stringptr, 0);
  1688.     if ((elemnumber != i) && (smallerr)) {
  1689.       printf("  Warning:  Triangles in %s are not numbered correctly.n",
  1690.              fname);
  1691.       printf("            (starting with triangle %d).n", i);
  1692.       smallerr = 0;
  1693.     }
  1694.     stringptr = findfield(stringptr);
  1695.     if (*stringptr == '') {
  1696.       printf("Error:  Triangle %d has no subdomain in %s.n", i, fname);
  1697.       free(*partition);
  1698.       return 1;
  1699.     }
  1700.     j = i + 1 - firstnumber;
  1701.     (*partition)[j] = (int) strtol (stringptr, &stringptr, 0) - firstnumber;
  1702.     if (((*partition)[j] >= *parts) || ((*partition)[j] < 0)) {
  1703.       printf("  Error:  Triangle %d of %s has an invalid subdomain.n",
  1704.              i, fname);
  1705.       free(*partition);
  1706.       return 1;
  1707.     }
  1708.   }
  1709.   fclose(infile);
  1710.   *partcenter = (REAL *) malloc(((*parts + 1) << 1) * sizeof(REAL));
  1711.   if (*partcenter == (REAL *) NULL) {
  1712.     printf("Error:  Out of memory.n");
  1713.     free(*partition);
  1714.     return 1;
  1715.   }
  1716.   *partshift = (REAL *) malloc((*parts << 1) * sizeof(REAL));
  1717.   if (*partshift == (REAL *) NULL) {
  1718.     printf("Error:  Out of memory.n");
  1719.     free(*partition);
  1720.     free(*partcenter);
  1721.     return 1;
  1722.   }
  1723.   partsize = (int *) malloc((*parts + 1) * sizeof(int));
  1724.   if (partsize == (int *) NULL) {
  1725.     printf("Error:  Out of memory.n");
  1726.     free(*partition);
  1727.     free(*partcenter);
  1728.     free(*partshift);
  1729.     return 1;
  1730.   }
  1731.   for (i = 0; i <= *parts; i++) {
  1732.     partsize[i] = 0;
  1733.     (*partcenter)[i << 1] = 0.0;
  1734.     (*partcenter)[(i << 1) + 1] = 0.0;
  1735.   }
  1736.   index = 3;
  1737.   for (i = 1; i <= elems; i++) {
  1738.     partsize[(*partition)[i]] += 3;
  1739.     for (j = 0; j < 3; j++) {
  1740.       (*partcenter)[(*partition)[i] << 1] +=
  1741.                 nodeptr[eleptr[index] * dim];
  1742.       (*partcenter)[((*partition)[i] << 1) + 1] +=
  1743.                 nodeptr[eleptr[index++] * dim + 1];
  1744.     }
  1745.   }
  1746.   for (i = 0; i < *parts; i++) {
  1747.     (*partcenter)[i << 1] /= (REAL) partsize[i];
  1748.     (*partcenter)[(i << 1) + 1] /= (REAL) partsize[i];
  1749.     (*partcenter)[*parts << 1] += (*partcenter)[i << 1];
  1750.     (*partcenter)[(*parts << 1) + 1] += (*partcenter)[(i << 1) + 1];
  1751.   }
  1752.   (*partcenter)[*parts << 1] /= (REAL) *parts;
  1753.   (*partcenter)[(*parts << 1) + 1] /= (REAL) *parts;
  1754.   free(partsize);
  1755.   return 0;
  1756. }
  1757. int load_adj(fname, subdomains, ptr)
  1758. char *fname;
  1759. int *subdomains;
  1760. int **ptr;
  1761. {
  1762.   FILE *infile;
  1763.   char inputline[INPUTLINESIZE];
  1764.   char *stringptr;
  1765.   int i, j;
  1766.   if (!quiet) {
  1767.     printf("Opening %s.n", fname);
  1768.   }
  1769.   infile = fopen(fname, "r");
  1770.   if (infile == (FILE *) NULL) {
  1771.     printf("  Error:  Cannot access file %s.n", fname);
  1772.     return 1;
  1773.   }
  1774.   stringptr = readline(inputline, infile, fname);
  1775.   *subdomains = (int) strtol (stringptr, &stringptr, 0);
  1776.   if (*subdomains < 1) {
  1777.     printf("  Error:  %s contains %d subdomains.n", fname, *subdomains);
  1778.     return 1;
  1779.   }
  1780.   *ptr = (int *) malloc(*subdomains * *subdomains * sizeof(int));
  1781.   if (*ptr == (int *) NULL) {
  1782.     printf("  Out of memory.n");
  1783.     return 1;
  1784.   }
  1785.   for (i = 0; i < *subdomains; i++) {
  1786.     for (j = 0; j < *subdomains; j++) {
  1787.       stringptr = readline(inputline, infile, fname);
  1788.       (*ptr)[i * *subdomains + j] = (int) strtol (stringptr, &stringptr, 0);
  1789.     }
  1790.   }
  1791.   return 0;
  1792. }
  1793. void findpartshift(parts, explosion, partcenter, partshift)
  1794. int parts;
  1795. REAL explosion;
  1796. REAL *partcenter;
  1797. REAL *partshift;
  1798. {
  1799.   int i;
  1800.   for (i = 0; i < parts; i++) {
  1801.     partshift[i << 1] = explosion *
  1802.           (partcenter[i << 1] - partcenter[parts << 1]);
  1803.     partshift[(i << 1) + 1] = explosion *
  1804.           (partcenter[(i << 1) + 1] - partcenter[(parts << 1) + 1]);
  1805.   }
  1806. }
  1807. int load_image(inc, image)
  1808. int inc;
  1809. int image;
  1810. {
  1811.   int error;
  1812.   switch (image) {
  1813.     case NODE:
  1814.       error = load_node(nodefilename[inc], &firstnumber[inc], &nodes[inc],
  1815.                         &node_dim[inc], &nodeptr[inc], &xlo[inc][NODE],
  1816.                         &ylo[inc][NODE], &xhi[inc][NODE], &yhi[inc][NODE]);
  1817.       break;
  1818.     case POLY:
  1819.       error = load_poly(inc, polyfilename[inc], &firstnumber[inc],
  1820.                         &polynodes[inc], &poly_dim[inc], &polyedges[inc],
  1821.                         &polyholes[inc], &polynodeptr[inc], &polyedgeptr[inc],
  1822.                         &polyholeptr[inc],
  1823.                         &xlo[inc][POLY], &ylo[inc][POLY],
  1824.                         &xhi[inc][POLY], &yhi[inc][POLY]);
  1825.       break;
  1826.     case ELE:
  1827.       error = load_ele(elefilename[inc], firstnumber[inc], nodes[inc],
  1828.                        &elems[inc], &ele_corners[inc], &eleptr[inc]);
  1829.       xlo[inc][ELE] = xlo[inc][NODE];
  1830.       ylo[inc][ELE] = ylo[inc][NODE];
  1831.       xhi[inc][ELE] = xhi[inc][NODE];
  1832.       yhi[inc][ELE] = yhi[inc][NODE];
  1833.       break;
  1834.     case EDGE:
  1835.       error = load_edge(edgefilename[inc], firstnumber[inc], nodes[inc],
  1836.                         &edges[inc], &edgeptr[inc], &normptr[inc]);
  1837.       xlo[inc][EDGE] = xlo[inc][NODE];
  1838.       ylo[inc][EDGE] = ylo[inc][NODE];
  1839.       xhi[inc][EDGE] = xhi[inc][NODE];
  1840.       yhi[inc][EDGE] = yhi[inc][NODE];
  1841.       break;
  1842.     case PART:
  1843.       error = load_part(partfilename[inc], node_dim[inc], firstnumber[inc],
  1844.                         elems[inc], nodeptr[inc], eleptr[inc],
  1845.                         &subdomains[inc], &partpart[inc], &partcenter[inc],
  1846.                         &partshift[inc]);
  1847.       if (!error) {
  1848.         findpartshift(subdomains[inc], explosion, partcenter[inc],
  1849.                       partshift[inc]);
  1850.       }
  1851.       xlo[inc][PART] = xlo[inc][NODE];
  1852.       ylo[inc][PART] = ylo[inc][NODE];
  1853.       xhi[inc][PART] = xhi[inc][NODE];
  1854.       yhi[inc][PART] = yhi[inc][NODE];
  1855.       break;
  1856.     case ADJ:
  1857.       error = load_adj(adjfilename[inc], &adjsubdomains[inc], &adjptr[inc]);
  1858.       xlo[inc][ADJ] = xlo[inc][NODE];
  1859.       ylo[inc][ADJ] = ylo[inc][NODE];
  1860.       xhi[inc][ADJ] = xhi[inc][NODE];
  1861.       yhi[inc][ADJ] = yhi[inc][NODE];
  1862.       break;
  1863.     case VORO:
  1864.       error = load_node(vnodefilename[inc], &firstnumber[inc], &vnodes[inc],
  1865.                         &vnode_dim[inc], &vnodeptr[inc], &xlo[inc][VORO],
  1866.                         &ylo[inc][VORO], &xhi[inc][VORO], &yhi[inc][VORO]);
  1867.       if (!error) {
  1868.         error = load_edge(vedgefilename[inc], firstnumber[inc], vnodes[inc],
  1869.                           &vedges[inc], &vedgeptr[inc], &vnormptr[inc]);
  1870.       }
  1871.       break;
  1872.     default:
  1873.       error = 1;
  1874.   }
  1875.   if (!error) {
  1876.     loaded[inc][image] = 1;
  1877.   }
  1878.   return error;
  1879. }
  1880. void choose_image(inc, image)
  1881. int inc;
  1882. int image;
  1883. {
  1884.   if (!loaded[inc][image]) {
  1885.     if ((image == ELE) || (image == EDGE) || (image == PART)
  1886.         || (image == ADJ)) {
  1887.       if (!loaded[inc][NODE]) {
  1888.         if (load_image(inc, NODE)) {
  1889.           return;
  1890.         }
  1891.       }
  1892.     }
  1893.     if ((image == PART) || (image == ADJ)) {
  1894.       if (!loaded[inc][ELE]) {
  1895.         if (load_image(inc, ELE)) {
  1896.           return;
  1897.         }
  1898.       }
  1899.     }
  1900.     if (image == ADJ) {
  1901.       if (!loaded[inc][PART]) {
  1902.         if (load_image(inc, PART)) {
  1903.           return;
  1904.         }
  1905.       }
  1906.     }
  1907.     if (load_image(inc, image)) {
  1908.       return;
  1909.     }
  1910.   }
  1911.   current_inc = inc;
  1912.   current_image = image;
  1913. }
  1914. Window make_button(name, x, y, width)
  1915. char *name;
  1916. int x;
  1917. int y;
  1918. int width;
  1919. {
  1920.   XSetWindowAttributes attr;
  1921.   XSizeHints hints;
  1922.   Window button;
  1923.   attr.background_pixel = black;
  1924.   attr.border_pixel = white;
  1925.   attr.backing_store = NotUseful;
  1926.   attr.event_mask = ExposureMask | ButtonReleaseMask | ButtonPressMask;
  1927.   attr.bit_gravity = SouthWestGravity;
  1928.   attr.win_gravity = SouthWestGravity;
  1929.   attr.save_under = False;
  1930.   button = XCreateWindow(display, mainwindow, x, y, width, BUTTONHEIGHT - 4,
  1931.                          2, 0, InputOutput, CopyFromParent,
  1932.                          CWBackPixel | CWBorderPixel | CWEventMask |
  1933.                          CWBitGravity | CWWinGravity | CWBackingStore |
  1934.                          CWSaveUnder, &attr);
  1935.   hints.width = width;
  1936.   hints.height = BUTTONHEIGHT - 4;
  1937.   hints.min_width = 0;
  1938.   hints.min_height = BUTTONHEIGHT - 4;
  1939.   hints.max_width = width;
  1940.   hints.max_height = BUTTONHEIGHT - 4;
  1941.   hints.width_inc = 1;
  1942.   hints.height_inc = 1;
  1943.   hints.flags = PMinSize | PMaxSize | PSize | PResizeInc;
  1944.   XSetStandardProperties(display, button, name, "showme", None, (char **) NULL,
  1945.                          0, &hints);
  1946.   return button;
  1947. }
  1948. void make_buttons(y)
  1949. int y;
  1950. {
  1951.   int i;
  1952.   for (i = 1; i >= 0; i--) {
  1953.     nodewin[i] = make_button("node", 0, y + (1 - i) * BUTTONHEIGHT, 42);
  1954.     XMapWindow(display, nodewin[i]);
  1955.     polywin[i] = make_button("poly", 44, y + (1 - i) * BUTTONHEIGHT, 42);
  1956.     XMapWindow(display, polywin[i]);
  1957.     elewin[i] = make_button("ele", 88, y + (1 - i) * BUTTONHEIGHT, 33);
  1958.     XMapWindow(display, elewin[i]);
  1959.     edgewin[i] = make_button("edge", 123, y + (1 - i) * BUTTONHEIGHT, 42);
  1960.     XMapWindow(display, edgewin[i]);
  1961.     partwin[i] = make_button("part", 167, y + (1 - i) * BUTTONHEIGHT, 42);
  1962.     XMapWindow(display, partwin[i]);
  1963.     adjwin[i] = make_button("adj", 211, y + (1 - i) * BUTTONHEIGHT, 33);
  1964.     XMapWindow(display, adjwin[i]);
  1965.     voronoiwin[i] = make_button("voro", 246, y + (1 - i) * BUTTONHEIGHT, 42);
  1966.     XMapWindow(display, voronoiwin[i]);
  1967.   }
  1968.   versionpluswin = make_button("    +", 290, y, 52);
  1969.   XMapWindow(display, versionpluswin);
  1970.   versionminuswin = make_button("    -", 290, y + BUTTONHEIGHT, 52);
  1971.   XMapWindow(display, versionminuswin);
  1972.   quitwin = make_button("Quit", 0, y + 2 * BUTTONHEIGHT, 42);
  1973.   XMapWindow(display, quitwin);
  1974.   leftwin = make_button("<", 44, y + 2 * BUTTONHEIGHT, 14);
  1975.   XMapWindow(display, leftwin);
  1976.   rightwin = make_button(">", 60, y + 2 * BUTTONHEIGHT, 14);
  1977.   XMapWindow(display, rightwin);
  1978.   upwin = make_button("^", 76, y + 2 * BUTTONHEIGHT, 14);
  1979.   XMapWindow(display, upwin);
  1980.   downwin = make_button("v", 92, y + 2 * BUTTONHEIGHT, 14);
  1981.   XMapWindow(display, downwin);
  1982.   resetwin = make_button("Reset", 108, y + 2 * BUTTONHEIGHT, 52);
  1983.   XMapWindow(display, resetwin);
  1984.   widthpluswin = make_button("Width+", 162, y + 2 * BUTTONHEIGHT, 61);
  1985.   XMapWindow(display, widthpluswin);
  1986.   widthminuswin = make_button("-", 225, y + 2 * BUTTONHEIGHT, 14);
  1987.   XMapWindow(display, widthminuswin);
  1988.   expwin = make_button("Exp", 241, y + 2 * BUTTONHEIGHT, 33);
  1989.   XMapWindow(display, expwin);
  1990.   exppluswin = make_button("+", 276, y + 2 * BUTTONHEIGHT, 14);
  1991.   XMapWindow(display, exppluswin);
  1992.   expminuswin = make_button("-", 292, y + 2 * BUTTONHEIGHT, 14);
  1993.   XMapWindow(display, expminuswin);
  1994.   fillwin = make_button("Fill", 308, y + 2 * BUTTONHEIGHT, 41);
  1995.   XMapWindow(display, fillwin);
  1996.   pswin = make_button("PS", 351, y + 2 * BUTTONHEIGHT, 24);
  1997.   XMapWindow(display, pswin);
  1998.   epswin = make_button("EPS", 377, y + 2 * BUTTONHEIGHT, 33);
  1999.   XMapWindow(display, epswin);
  2000. }
  2001. void fill_button(button)
  2002. Window button;
  2003. {
  2004.   int x, y;
  2005.   unsigned int w, h, d, b;
  2006.   Window rootw;
  2007.   XGetGeometry(display, button, &rootw, &x, &y, &w, &h, &d, &b);
  2008.   XFillRectangle(display, button, fontgc, 0, 0, w, h);
  2009. }
  2010. void draw_buttons()
  2011. {
  2012.   char numberstring[32];
  2013.   char buttonstring[6];
  2014.   int i;
  2015.   for (i = 1; i >= 0; i--) {
  2016.     if ((current_image == NODE) && (current_inc == i)) {
  2017.       fill_button(nodewin[i]);
  2018.       XDrawString(display, nodewin[i], blackfontgc, 2, 13, "node", 4);
  2019.     } else {
  2020.       XClearWindow(display, nodewin[i]);
  2021.       XDrawString(display, nodewin[i], fontgc, 2, 13, "node", 4);
  2022.     }
  2023.     if ((current_image == POLY) && (current_inc == i)) {
  2024.       fill_button(polywin[i]);
  2025.       XDrawString(display, polywin[i], blackfontgc, 2, 13, "poly", 4);
  2026.     } else {
  2027.       XClearWindow(display, polywin[i]);
  2028.       XDrawString(display, polywin[i], fontgc, 2, 13, "poly", 4);
  2029.     }
  2030.     if ((current_image == ELE) && (current_inc == i)) {
  2031.       fill_button(elewin[i]);
  2032.       XDrawString(display, elewin[i], blackfontgc, 2, 13, "ele", 3);
  2033.     } else {
  2034.       XClearWindow(display, elewin[i]);
  2035.       XDrawString(display, elewin[i], fontgc, 2, 13, "ele", 3);
  2036.     }
  2037.     if ((current_image == EDGE) && (current_inc == i)) {
  2038.       fill_button(edgewin[i]);
  2039.       XDrawString(display, edgewin[i], blackfontgc, 2, 13, "edge", 4);
  2040.     } else {
  2041.       XClearWindow(display, edgewin[i]);
  2042.       XDrawString(display, edgewin[i], fontgc, 2, 13, "edge", 4);
  2043.     }
  2044.     if ((current_image == PART) && (current_inc == i)) {
  2045.       fill_button(partwin[i]);
  2046.       XDrawString(display, partwin[i], blackfontgc, 2, 13, "part", 4);
  2047.     } else {
  2048.       XClearWindow(display, partwin[i]);
  2049.       XDrawString(display, partwin[i], fontgc, 2, 13, "part", 4);
  2050.     }
  2051.     if ((current_image == ADJ) && (current_inc == i)) {
  2052.       fill_button(adjwin[i]);
  2053.       XDrawString(display, adjwin[i], blackfontgc, 2, 13, "adj", 3);
  2054.     } else {
  2055.       XClearWindow(display, adjwin[i]);
  2056.       XDrawString(display, adjwin[i], fontgc, 2, 13, "adj", 3);
  2057.     }
  2058.     if ((current_image == VORO) && (current_inc == i)) {
  2059.       fill_button(voronoiwin[i]);
  2060.       XDrawString(display, voronoiwin[i], blackfontgc, 2, 13, "voro", 4);
  2061.     } else {
  2062.       XClearWindow(display, voronoiwin[i]);
  2063.       XDrawString(display, voronoiwin[i], fontgc, 2, 13, "voro", 4);
  2064.     }
  2065.   }
  2066.   XClearWindow(display, versionpluswin);
  2067.   sprintf(numberstring, "%d", loweriteration + 1);
  2068.   sprintf(buttonstring, "%-4.4s+", numberstring);
  2069.   XDrawString(display, versionpluswin, fontgc, 2, 13, buttonstring, 5);
  2070.   XClearWindow(display, versionminuswin);
  2071.   sprintf(numberstring, "%d", loweriteration);
  2072.   if (loweriteration == 0) {
  2073.     sprintf(buttonstring, "%-4.4s", numberstring);
  2074.   } else {
  2075.     sprintf(buttonstring, "%-4.4s-", numberstring);
  2076.   }
  2077.   XDrawString(display, versionminuswin, fontgc, 2, 13, buttonstring, 5);
  2078.   XClearWindow(display, quitwin);
  2079.   XDrawString(display, quitwin, fontgc, 2, 13, "Quit", 4);
  2080.   XClearWindow(display, leftwin);
  2081.   XDrawString(display, leftwin, fontgc, 2, 13, "<", 1);
  2082.   XClearWindow(display, rightwin);
  2083.   XDrawString(display, rightwin, fontgc, 2, 13, ">", 1);
  2084.   XClearWindow(display, upwin);
  2085.   XDrawString(display, upwin, fontgc, 2, 13, "^", 1);
  2086.   XClearWindow(display, downwin);
  2087.   XDrawString(display, downwin, fontgc, 2, 13, "v", 1);
  2088.   XClearWindow(display, resetwin);
  2089.   XDrawString(display, resetwin, fontgc, 2, 13, "Reset", 6);
  2090.   XClearWindow(display, widthpluswin);
  2091.   if (line_width < 100) {
  2092.     XDrawString(display, widthpluswin, fontgc, 2, 13, "Width+", 6);
  2093.   } else {
  2094.     XDrawString(display, widthpluswin, fontgc, 2, 13, "Width ", 6);
  2095.   }
  2096.   XClearWindow(display, widthminuswin);
  2097.   if (line_width > 1) {
  2098.     XDrawString(display, widthminuswin, fontgc, 2, 13, "-", 1);
  2099.   }
  2100.   XClearWindow(display, expwin);
  2101.   XClearWindow(display, exppluswin);
  2102.   XClearWindow(display, expminuswin);
  2103.   XClearWindow(display, fillwin);
  2104.   if (current_image == PART) {
  2105.     if (explode) {
  2106.       fill_button(expwin);
  2107.       XDrawString(display, expwin, blackfontgc, 2, 13, "Exp", 3);
  2108.     } else {
  2109.       XDrawString(display, expwin, fontgc, 2, 13, "Exp", 3);
  2110.     }
  2111.     XDrawString(display, exppluswin, fontgc, 2, 13, "+", 1);
  2112.     XDrawString(display, expminuswin, fontgc, 2, 13, "-", 1);
  2113.     if (fillelem) {
  2114.       fill_button(fillwin);
  2115.       XDrawString(display, fillwin, blackfontgc, 2, 13, "Fill", 4);
  2116.     } else {
  2117.       XDrawString(display, fillwin, fontgc, 2, 13, "Fill", 4);
  2118.     }
  2119.   }
  2120.   XClearWindow(display, pswin);
  2121.   XDrawString(display, pswin, fontgc, 2, 13, "PS", 2);
  2122.   XClearWindow(display, epswin);
  2123.   XDrawString(display, epswin, fontgc, 2, 13, "EPS", 3);
  2124. }
  2125. void showme_window(argc, argv)
  2126. int argc;
  2127. char **argv;
  2128. {
  2129.   XSetWindowAttributes attr;
  2130.   XSizeHints hints;
  2131.   XGCValues fontvalues, linevalues;
  2132.   XColor alloc_color, exact_color;
  2133.   int i;
  2134.   display = XOpenDisplay((char *) NULL);
  2135.   if (!display) {
  2136.     printf("Error:  Cannot open display.n");
  2137.     exit(1);
  2138.   }
  2139.   screen = DefaultScreen(display);
  2140.   rootwindow = DefaultRootWindow(display);
  2141.   black = BlackPixel(display, screen);
  2142.   white = WhitePixel(display, screen);
  2143.   windowdepth = DefaultDepth(display, screen);
  2144.   rootmap = DefaultColormap(display, screen);
  2145.   width = STARTWIDTH;
  2146.   height = STARTHEIGHT;
  2147.   attr.background_pixel = black;
  2148.   attr.border_pixel = white;
  2149.   attr.backing_store = NotUseful;
  2150.   attr.event_mask = ExposureMask | ButtonReleaseMask | ButtonPressMask |
  2151.                     StructureNotifyMask;
  2152.   attr.bit_gravity = NorthWestGravity;
  2153.   attr.win_gravity = NorthWestGravity;
  2154.   attr.save_under = False;
  2155.   mainwindow = XCreateWindow(display, rootwindow, 0, 0, width,
  2156.                              height + PANELHEIGHT, 3, 0,
  2157.                              InputOutput, CopyFromParent,
  2158.                              CWBackPixel | CWBorderPixel | CWEventMask |
  2159.                              CWBitGravity | CWWinGravity | CWBackingStore |
  2160.                              CWSaveUnder, &attr);
  2161.   hints.width = width;
  2162.   hints.height = height + PANELHEIGHT;
  2163.   hints.min_width = MINWIDTH;
  2164.   hints.min_height = MINHEIGHT + PANELHEIGHT;
  2165.   hints.width_inc = 1;
  2166.   hints.height_inc = 1;
  2167.   hints.flags = PMinSize | PSize | PResizeInc;
  2168.   XSetStandardProperties(display, mainwindow, "Show Me", "showme", None,
  2169.                          argv, argc, &hints);
  2170.   XChangeProperty(display, mainwindow, XA_WM_CLASS, XA_STRING, 8,
  2171.                   PropModeReplace, "showmeArchimedes", 18);
  2172.   XClearWindow(display, mainwindow);
  2173.   XMapWindow(display, mainwindow);
  2174.   if ((windowdepth > 1) &&
  2175.       XAllocNamedColor(display, rootmap, "yellow", &alloc_color,
  2176.                        &exact_color)) {
  2177.     color = 1;
  2178.     explode = bw_ps;
  2179.     fontvalues.foreground = alloc_color.pixel;
  2180.     linevalues.foreground = alloc_color.pixel;
  2181.     showme_foreground = alloc_color.pixel;
  2182.     for (i = 0; i < 64; i++) {
  2183.       if (XAllocNamedColor(display, rootmap, colorname[i], &alloc_color,
  2184.                            &rgb[i])) {
  2185.         colors[i] = alloc_color.pixel;
  2186.       } else {
  2187.         colors[i] = white;
  2188.         rgb[i].red = alloc_color.red;
  2189.         rgb[i].green = alloc_color.green;
  2190.         rgb[i].blue = alloc_color.blue;
  2191.         if (!quiet) {
  2192.           printf("Warning:  I could not allocate %s.n", colorname[i]);
  2193.         }
  2194.       }
  2195.     }
  2196.   } else {
  2197.     color = 0;
  2198.     fillelem = 0;
  2199.     explode = 1;
  2200.     fontvalues.foreground = white;
  2201.     linevalues.foreground = white;
  2202.     showme_foreground = white;
  2203.   }
  2204.   font = XLoadQueryFont(display, "9x15");
  2205.   fontvalues.background = black;
  2206.   fontvalues.font = font->fid;
  2207.   fontvalues.fill_style = FillSolid;
  2208.   fontvalues.line_width = 2;
  2209.   fontgc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
  2210.                       GCFont | GCLineWidth | GCFillStyle, &fontvalues);
  2211.   fontvalues.foreground = black;
  2212.   blackfontgc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
  2213.                          GCFont | GCLineWidth | GCFillStyle, &fontvalues);
  2214.   linevalues.background = black;
  2215.   linevalues.line_width = line_width;
  2216.   linevalues.cap_style = CapRound;
  2217.   linevalues.join_style = JoinRound;
  2218.   linevalues.fill_style = FillSolid;
  2219.   linegc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
  2220.                      GCLineWidth | GCCapStyle | GCJoinStyle | GCFillStyle,
  2221.                      &linevalues);
  2222.   trianglegc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
  2223.                          GCLineWidth | GCCapStyle | GCJoinStyle | GCFillStyle,
  2224.                          &linevalues);
  2225.   make_buttons(height);
  2226.   XFlush(display);
  2227. }
  2228. void draw_node(nodes, dim, ptr, xscale, yscale, xoffset, yoffset)
  2229. int nodes;
  2230. int dim;
  2231. REAL *ptr;
  2232. REAL xscale;
  2233. REAL yscale;
  2234. REAL xoffset;
  2235. REAL yoffset;
  2236. {
  2237.   int i;
  2238.   int index;
  2239.   index = dim;
  2240.   for (i = 1; i <= nodes; i++) {
  2241.     XFillRectangle(display, mainwindow, linegc,
  2242.                    (int) (ptr[index] * xscale + xoffset) - (line_width >> 1),
  2243.                    (int) (ptr[index + 1] * yscale + yoffset) -
  2244.                          (line_width >> 1), line_width, line_width);
  2245.     index += dim;
  2246.   }
  2247. }
  2248. void draw_poly(nodes, dim, edges, holes, nodeptr, edgeptr, holeptr,
  2249.                xscale, yscale, xoffset, yoffset)
  2250. int nodes;
  2251. int dim;
  2252. int edges;
  2253. int holes;
  2254. REAL *nodeptr;
  2255. int *edgeptr;
  2256. REAL *holeptr;
  2257. REAL xscale;
  2258. REAL yscale;
  2259. REAL xoffset;
  2260. REAL yoffset;
  2261. {
  2262.   int i;
  2263.   int index;
  2264.   REAL *point1, *point2;
  2265.   int x1, y1, x2, y2;
  2266.   index = dim;
  2267.   for (i = 1; i <= nodes; i++) {
  2268.     XFillRectangle(display, mainwindow, linegc,
  2269.                    (int) (nodeptr[index] * xscale + xoffset) -
  2270.                          (line_width >> 1),
  2271.                    (int) (nodeptr[index + 1] * yscale + yoffset) -
  2272.                          (line_width >> 1), line_width, line_width);
  2273.     index += dim;
  2274.   }
  2275.   index = 2;
  2276.   for (i = 1; i <= edges; i++) {
  2277.     point1 = &nodeptr[edgeptr[index++] * dim];
  2278.     point2 = &nodeptr[edgeptr[index++] * dim];
  2279.     XDrawLine(display, mainwindow, linegc,
  2280.               (int) (point1[0] * xscale + xoffset),
  2281.               (int) (point1[1] * yscale + yoffset),
  2282.               (int) (point2[0] * xscale + xoffset),
  2283.               (int) (point2[1] * yscale + yoffset));
  2284.   }
  2285.   index = dim;
  2286.   if (color) {
  2287.     XSetForeground(display, linegc, colors[0]);
  2288.   }
  2289.   for (i = 1; i <= holes; i++) {
  2290.     x1 = (int) (holeptr[index] * xscale + xoffset) - 3;
  2291.     y1 = (int) (holeptr[index + 1] * yscale + yoffset) - 3;
  2292.     x2 = x1 + 6;
  2293.     y2 = y1 + 6;
  2294.     XDrawLine(display, mainwindow, linegc, x1, y1, x2, y2);
  2295.     XDrawLine(display, mainwindow, linegc, x1, y2, x2, y1);
  2296.     index += dim;
  2297.   }
  2298.   XSetForeground(display, linegc, showme_foreground);
  2299. }
  2300. void draw_ele(inc, elems, corners, ptr, partition, shift,
  2301.               xscale, yscale, xoffset, yoffset)
  2302. int inc;
  2303. int elems;
  2304. int corners;
  2305. int *ptr;
  2306. int *partition;
  2307. REAL *shift;
  2308. REAL xscale;
  2309. REAL yscale;
  2310. REAL xoffset;
  2311. REAL yoffset;
  2312. {
  2313.   int i, j;
  2314.   int index;
  2315.   REAL shiftx, shifty;
  2316.   REAL *prevpoint, *nowpoint;
  2317.   XPoint *vertices;
  2318.   if (color && fillelem && (partition != (int *) NULL)) {
  2319.     vertices = (XPoint *) malloc(3 * sizeof(XPoint));
  2320.     if (vertices == (XPoint *) NULL) {
  2321.       printf("Error:  Out of memory.n");
  2322.       exit(1);
  2323.     }
  2324.   }
  2325.   index = 3;
  2326.   for (i = 1; i <= elems; i++) {
  2327.     if ((partition != (int *) NULL) && explode) {
  2328.       shiftx = shift[partition[i] << 1];
  2329.       shifty = shift[(partition[i] << 1) + 1];
  2330.     }
  2331.     if (color && (partition != (int *) NULL)) {
  2332.       if (fillelem) {
  2333.         XSetForeground(display, trianglegc, colors[partition[i] & 63]);
  2334.       } else {
  2335.         XSetForeground(display, linegc, colors[partition[i] & 63]);
  2336.       }
  2337.     }
  2338.     if (color && fillelem && (partition != (int *) NULL)) {
  2339.       if ((partition != (int *) NULL) && explode) {
  2340.         for (j = 0; j < 3; j++) {
  2341.           nowpoint = &nodeptr[inc][ptr[index + j] * node_dim[inc]];
  2342.           vertices[j].x = (nowpoint[0] + shiftx) * xscale + xoffset;
  2343.           vertices[j].y = (nowpoint[1] + shifty) * yscale + yoffset;
  2344.         }
  2345.       } else {
  2346.         for (j = 0; j < 3; j++) {
  2347.           nowpoint = &nodeptr[inc][ptr[index + j] * node_dim[inc]];
  2348.           vertices[j].x = nowpoint[0] * xscale + xoffset;
  2349.           vertices[j].y = nowpoint[1] * yscale + yoffset;
  2350.         }
  2351.       }
  2352.       XFillPolygon(display, mainwindow, trianglegc, vertices, 3,
  2353.                    Convex, CoordModeOrigin);
  2354.     }
  2355.     prevpoint = &nodeptr[inc][ptr[index + 2] * node_dim[inc]];
  2356.     if ((partition != (int *) NULL) && explode) {
  2357.       for (j = 0; j < 3; j++) {
  2358.         nowpoint = &nodeptr[inc][ptr[index++] * node_dim[inc]];
  2359.         XDrawLine(display, mainwindow, linegc,
  2360.                   (int) ((prevpoint[0] + shiftx) * xscale + xoffset),
  2361.                   (int) ((prevpoint[1] + shifty) * yscale + yoffset),
  2362.                   (int) ((nowpoint[0] + shiftx) * xscale + xoffset),
  2363.                   (int) ((nowpoint[1] + shifty) * yscale + yoffset));
  2364.         prevpoint = nowpoint;
  2365.       }
  2366.     } else {
  2367.       for (j = 0; j < 3; j++) {
  2368.         nowpoint = &nodeptr[inc][ptr[index++] * node_dim[inc]];
  2369.         XDrawLine(display, mainwindow, linegc,
  2370.                   (int) (prevpoint[0] * xscale + xoffset),
  2371.                   (int) (prevpoint[1] * yscale + yoffset),
  2372.                   (int) (nowpoint[0] * xscale + xoffset),
  2373.                   (int) (nowpoint[1] * yscale + yoffset));
  2374.         prevpoint = nowpoint;
  2375.       }
  2376.     }
  2377.   }
  2378.   if (color && fillelem && (partition != (int *) NULL)) {
  2379.     free(vertices);
  2380.   }
  2381.   XSetForeground(display, linegc, showme_foreground);
  2382. }
  2383. void draw_edge(nodes, dim, edges, nodeptr, edgeptr, normptr,
  2384.                xscale, yscale, xoffset, yoffset)
  2385. int nodes;
  2386. int dim;
  2387. int edges;
  2388. REAL *nodeptr;
  2389. int *edgeptr;
  2390. REAL *normptr;
  2391. REAL xscale;
  2392. REAL yscale;
  2393. REAL xoffset;
  2394. REAL yoffset;
  2395. {
  2396.   int i;
  2397.   int index;
  2398.   REAL *point1, *point2;
  2399.   REAL normx, normy;
  2400.   REAL normmult, normmultx, normmulty;
  2401.   REAL windowxmin, windowymin, windowxmax, windowymax;
  2402.   index = 2;
  2403.   for (i = 1; i <= edges; i++) {
  2404.     point1 = &nodeptr[edgeptr[index++] * dim];
  2405.     if (edgeptr[index] == -1) {
  2406.       normx = normptr[index - 1];
  2407.       normy = normptr[index++];
  2408.       normmultx = 0.0;
  2409.       if (normx > 0) {
  2410.         windowxmax = (width - 1 - xoffset) / xscale;
  2411.         normmultx = (windowxmax - point1[0]) / normx;
  2412.       } else if (normx < 0) {
  2413.         windowxmin = -xoffset / xscale;
  2414.         normmultx = (windowxmin - point1[0]) / normx;
  2415.       }
  2416.       normmulty = 0.0;
  2417.       if (normy > 0) {
  2418.         windowymax = -yoffset / yscale;
  2419.         normmulty = (windowymax - point1[1]) / normy;
  2420.       } else if (normy < 0) {
  2421.         windowymin = (height - 1 - yoffset) / yscale;
  2422.         normmulty = (windowymin - point1[1]) / normy;
  2423.       }
  2424.       if (normmultx == 0.0) {
  2425.         normmult = normmulty;
  2426.       } else if (normmulty == 0.0) {
  2427.         normmult = normmultx;
  2428.       } else if (normmultx < normmulty) {
  2429.         normmult = normmultx;
  2430.       } else {
  2431.         normmult = normmulty;
  2432.       }
  2433.       if (normmult > 0.0) {
  2434.         XDrawLine(display, mainwindow, linegc,
  2435.                   (int) (point1[0] * xscale + xoffset),
  2436.                   (int) (point1[1] * yscale + yoffset),
  2437.                   (int) ((point1[0] + normmult * normx) * xscale + xoffset),
  2438.                   (int) ((point1[1] + normmult * normy) * yscale + yoffset));
  2439.       }
  2440.     } else {
  2441.       point2 = &nodeptr[edgeptr[index++] * dim];
  2442.       XDrawLine(display, mainwindow, linegc,
  2443.                 (int) (point1[0] * xscale + xoffset),
  2444.                 (int) (point1[1] * yscale + yoffset),
  2445.                 (int) (point2[0] * xscale + xoffset),
  2446.                 (int) (point2[1] * yscale + yoffset));
  2447.     }
  2448.   }
  2449. }
  2450. void draw_adj(dim, subdomains, ptr, center, xscale, yscale,
  2451.               xoffset, yoffset)
  2452. int dim;
  2453. int subdomains;
  2454. int *ptr;
  2455. REAL *center;
  2456. REAL xscale;
  2457. REAL yscale;
  2458. REAL xoffset;
  2459. REAL yoffset;
  2460. {
  2461.   int i, j;
  2462.   REAL *point1, *point2;
  2463.   for (i = 0; i < subdomains; i++) {
  2464.     for (j = i + 1; j < subdomains; j++) {
  2465.       if (ptr[i * subdomains + j]) {
  2466.         point1 = &center[i * dim];
  2467.         point2 = &center[j * dim];
  2468.         XDrawLine(display, mainwindow, linegc,
  2469.                   (int) (point1[0] * xscale + xoffset),
  2470.                   (int) (point1[1] * yscale + yoffset),
  2471.                   (int) (point2[0] * xscale + xoffset),
  2472.                   (int) (point2[1] * yscale + yoffset));
  2473.       }
  2474.     }
  2475.   }
  2476.   for (i = 0; i < subdomains; i++) {
  2477.     point1 = &center[i * dim];
  2478.     if (color) {
  2479.       XSetForeground(display, linegc, colors[i & 63]);
  2480.     }
  2481.     XFillArc(display, mainwindow, linegc,
  2482.              (int) (point1[0] * xscale + xoffset) - 5 - (line_width >> 1),
  2483.              (int) (point1[1] * yscale + yoffset) - 5 - (line_width >> 1),
  2484.              line_width + 10, line_width + 10, 0, 23040);
  2485.   }
  2486.   XSetForeground(display, linegc, showme_foreground);
  2487. }
  2488. void draw(inc, image, xmin, ymin, xmax, ymax)
  2489. int inc;
  2490. int image;
  2491. REAL xmin;
  2492. REAL ymin;
  2493. REAL xmax;
  2494. REAL ymax;
  2495. {
  2496.   draw_buttons();
  2497.   XClearWindow(display, mainwindow);
  2498.   if (image == NOTHING) {
  2499.     return;
  2500.   }
  2501.   if (!loaded[inc][image]) {
  2502.     return;
  2503.   }
  2504.   if ((image == PART) && explode) {
  2505.     xmin += (xmin - partcenter[inc][subdomains[inc] << 1]) * explosion;
  2506.     xmax += (xmax - partcenter[inc][subdomains[inc] << 1]) * explosion;
  2507.     ymin += (ymin - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
  2508.     ymax += (ymax - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
  2509.   }
  2510.   xscale = (REAL) (width - line_width - 4) / (xmax - xmin);
  2511.   yscale = (REAL) (height - line_width - 4) / (ymax - ymin);
  2512.   if (xscale > yscale) {
  2513.     xscale = yscale;
  2514.   } else {
  2515.     yscale = xscale;
  2516.   }
  2517.   xoffset = 0.5 * ((REAL) width - xscale * (xmax - xmin)) -
  2518.             xscale * xmin;
  2519.   yoffset = (REAL) height - 0.5 * ((REAL) height - yscale * (ymax - ymin)) +
  2520.             yscale * ymin;
  2521.   yscale = - yscale;
  2522.   switch(image) {
  2523.     case NODE:
  2524.       draw_node(nodes[inc], node_dim[inc], nodeptr[inc],
  2525.                 xscale, yscale, xoffset, yoffset);
  2526.       break;
  2527.     case POLY:
  2528.       if (polynodes[inc] > 0) {
  2529.         draw_poly(polynodes[inc], poly_dim[inc], polyedges[inc],
  2530.                   polyholes[inc], polynodeptr[inc], polyedgeptr[inc],
  2531.                   polyholeptr[inc],
  2532.                   xscale, yscale, xoffset, yoffset);
  2533.       } else {
  2534.         draw_poly(nodes[inc], node_dim[inc], polyedges[inc],
  2535.                   polyholes[inc], nodeptr[inc], polyedgeptr[inc],
  2536.                   polyholeptr[inc],
  2537.                   xscale, yscale, xoffset, yoffset);
  2538.       }
  2539.       break;
  2540.     case ELE:
  2541.       draw_ele(inc, elems[inc], ele_corners[inc], eleptr[inc],
  2542.                (int *) NULL, (REAL *) NULL,
  2543.                xscale, yscale, xoffset, yoffset);
  2544.       break;
  2545.     case EDGE:
  2546.       draw_edge(nodes[inc], node_dim[inc], edges[inc],
  2547.                 nodeptr[inc], edgeptr[inc], normptr[inc],
  2548.                 xscale, yscale, xoffset, yoffset);
  2549.       break;
  2550.     case PART:
  2551.       draw_ele(inc, elems[inc], ele_corners[inc], eleptr[inc],
  2552.                partpart[inc], partshift[inc],
  2553.                xscale, yscale, xoffset, yoffset);
  2554.       break;
  2555.     case ADJ:
  2556.       draw_adj(node_dim[inc], adjsubdomains[inc], adjptr[inc], partcenter[inc],
  2557.                xscale, yscale, xoffset, yoffset);
  2558.       break;
  2559.     case VORO:
  2560.       if (loaded[inc][NODE]) {
  2561.         draw_node(nodes[inc], node_dim[inc], nodeptr[inc],
  2562.                   xscale, yscale, xoffset, yoffset);
  2563.       }
  2564.       draw_edge(vnodes[inc], vnode_dim[inc], vedges[inc],
  2565.                 vnodeptr[inc], vedgeptr[inc], vnormptr[inc],
  2566.                 xscale, yscale, xoffset, yoffset);
  2567.       break;
  2568.     default:
  2569.       break;
  2570.   }
  2571. }
  2572. void addps(instring, outstring, eps)
  2573. char *instring;
  2574. char *outstring;
  2575. int eps;
  2576. {
  2577.   strcpy(outstring, instring);
  2578.   if (eps) {
  2579.     strcat(outstring, ".eps");
  2580.   } else {
  2581.     strcat(outstring, ".ps");
  2582.   }
  2583. }
  2584. int print_head(fname, file, llcornerx, llcornery, eps)
  2585. char *fname;
  2586. FILE **file;
  2587. int llcornerx;
  2588. int llcornery;
  2589. int eps;
  2590. {
  2591.   if (!quiet) {
  2592.     printf("Writing %sn", fname);
  2593.   }
  2594.   *file = fopen(fname, "w");
  2595.   if (*file == (FILE *) NULL) {
  2596.     printf("  Error:  Could not open %sn", fname);
  2597.     return 1;
  2598.   }
  2599.   if (eps) {
  2600.     fprintf(*file, "%%!PS-Adobe-2.0 EPSF-2.0n");
  2601.   } else {
  2602.     fprintf(*file, "%%!PS-Adobe-2.0n");
  2603.   }
  2604.   fprintf(*file, "%%%%BoundingBox: %d %d %d %dn", llcornerx, llcornery,
  2605.           612 - llcornerx, 792 - llcornery);
  2606.   fprintf(*file, "%%%%Creator: Show Men");
  2607.   fprintf(*file, "%%%%EndCommentsnn");
  2608.   fprintf(*file, "/m {moveto} bind defn");
  2609.   fprintf(*file, "/l {lineto} bind defn");
  2610.   fprintf(*file, "/s {setrgbcolor} bind defn");
  2611.   fprintf(*file, "/g {gsave fill grestore} bind defn");
  2612.   fprintf(*file, "/k {stroke} bind defnn");
  2613.   fprintf(*file, "1 setlinecapn");
  2614.   fprintf(*file, "1 setlinejoinn");
  2615.   fprintf(*file, "%d setlinewidthn", line_width);
  2616.   fprintf(*file, "%d %d mn", llcornerx, llcornery);
  2617.   fprintf(*file, "%d %d ln", 612 - llcornerx, llcornery);
  2618.   fprintf(*file, "%d %d ln", 612 - llcornerx, 792 - llcornery);
  2619.   fprintf(*file, "%d %d ln", llcornerx, 792 - llcornery);
  2620.   fprintf(*file, "closepathnclipnnewpathn");
  2621.   return 0;
  2622. }
  2623. void print_node(nodefile, nodes, dim, ptr, xscale, yscale,
  2624.                 xoffset, yoffset)
  2625. FILE *nodefile;
  2626. int nodes;
  2627. int dim;
  2628. REAL *ptr;
  2629. REAL xscale;
  2630. REAL yscale;
  2631. REAL xoffset;
  2632. REAL yoffset;
  2633. {
  2634.   int i;
  2635.   int index;
  2636.   index = dim;
  2637.   for (i = 1; i <= nodes; i++) {
  2638.     fprintf(nodefile, "%d %d %d 0 360 arcnfilln",
  2639.             (int) (ptr[index] * xscale + xoffset),
  2640.             (int) (ptr[index + 1] * yscale + yoffset),
  2641.             1 + (line_width >> 1));
  2642.     index += dim;
  2643.   }
  2644. }
  2645. void print_poly(polyfile, nodes, dim, edges, holes, nodeptr, edgeptr, holeptr,
  2646.                 xscale, yscale, xoffset, yoffset)
  2647. FILE *polyfile;
  2648. int nodes;
  2649. int dim;
  2650. int edges;
  2651. int holes;
  2652. REAL *nodeptr;
  2653. int *edgeptr;
  2654. REAL *holeptr;
  2655. REAL xscale;
  2656. REAL yscale;
  2657. REAL xoffset;
  2658. REAL yoffset;
  2659. {
  2660.   int i;
  2661.   int index;
  2662.   REAL *point1, *point2;
  2663.   index = dim;
  2664.   for (i = 1; i <= nodes; i++) {
  2665.     fprintf(polyfile, "%d %d %d 0 360 arcnfilln",
  2666.             (int) (nodeptr[index] * xscale + xoffset),
  2667.             (int) (nodeptr[index + 1] * yscale + yoffset),
  2668.             1 + (line_width >> 1));
  2669.     index += dim;
  2670.   }
  2671.   index = 2;
  2672.   for (i = 1; i <= edges; i++) {
  2673.     point1 = &nodeptr[edgeptr[index++] * dim];
  2674.     point2 = &nodeptr[edgeptr[index++] * dim];
  2675.     fprintf(polyfile, "%d %d mn",
  2676.             (int) (point1[0] * xscale + xoffset),
  2677.             (int) (point1[1] * yscale + yoffset));
  2678.     fprintf(polyfile, "%d %d lnkn",
  2679.             (int) (point2[0] * xscale + xoffset),
  2680.             (int) (point2[1] * yscale + yoffset));
  2681.   }
  2682. }
  2683. void print_ele(elefile, nodes, dim, elems, corners, nodeptr, eleptr,
  2684.                partition, shift,
  2685.                xscale, yscale, xoffset, yoffset, llcornerx, llcornery)
  2686. FILE *elefile;
  2687. int nodes;
  2688. int dim;
  2689. int elems;
  2690. int corners;
  2691. REAL *nodeptr;
  2692. int *eleptr;
  2693. int *partition;
  2694. REAL *shift;
  2695. REAL xscale;
  2696. REAL yscale;
  2697. REAL xoffset;
  2698. REAL yoffset;
  2699. int llcornerx;
  2700. int llcornery;
  2701. {
  2702.   int i, j;
  2703.   int index, colorindex;
  2704.   REAL shiftx, shifty;
  2705.   REAL *nowpoint;
  2706.   index = 3;
  2707.   if ((partition != (int *) NULL) && !bw_ps) {
  2708.     fprintf(elefile, "0 0 0 sn");
  2709.     fprintf(elefile, "%d %d mn", llcornerx, llcornery);
  2710.     fprintf(elefile, "%d %d ln", 612 - llcornerx, llcornery);
  2711.     fprintf(elefile, "%d %d ln", 612 - llcornerx, 792 - llcornery);
  2712.     fprintf(elefile, "%d %d ln", llcornerx, 792 - llcornery);
  2713.     fprintf(elefile, "filln");
  2714.   }
  2715.   for (i = 1; i <= elems; i++) {
  2716.     if ((partition != (int *) NULL) && !bw_ps) {
  2717.       colorindex = partition[i] & 63;
  2718.       fprintf(elefile, "%6.3f %6.3f %6.3f sn",
  2719.               (REAL) rgb[colorindex].red / 65535.0,
  2720.               (REAL) rgb[colorindex].green / 65535.0,
  2721.               (REAL) rgb[colorindex].blue / 65535.0);
  2722.     }
  2723.     nowpoint = &nodeptr[eleptr[index + 2] * dim];
  2724.     if ((partition != (int *) NULL) && (explode || bw_ps)) {
  2725.       shiftx = shift[partition[i] << 1];
  2726.       shifty = shift[(partition[i] << 1) + 1];
  2727.       fprintf(elefile, "%d %d mn",
  2728.               (int) ((nowpoint[0] + shiftx) * xscale + xoffset),
  2729.               (int) ((nowpoint[1] + shifty) * yscale + yoffset));
  2730.       for (j = 0; j < 3; j++) {
  2731.         nowpoint = &nodeptr[eleptr[index++] * dim];
  2732.         fprintf(elefile, "%d %d ln",
  2733.                 (int) ((nowpoint[0] + shiftx) * xscale + xoffset),
  2734.                 (int) ((nowpoint[1] + shifty) * yscale + yoffset));
  2735.       }
  2736.     } else {
  2737.       fprintf(elefile, "%d %d mn",
  2738.               (int) (nowpoint[0] * xscale + xoffset),
  2739.               (int) (nowpoint[1] * yscale + yoffset));
  2740.       for (j = 0; j < 3; j++) {
  2741.         nowpoint = &nodeptr[eleptr[index++] * dim];
  2742.         fprintf(elefile, "%d %d ln",
  2743.                 (int) (nowpoint[0] * xscale + xoffset),
  2744.                 (int) (nowpoint[1] * yscale + yoffset));
  2745.       }
  2746.     }
  2747.     if (fillelem && (partition != (int *) NULL) && !bw_ps) {
  2748.       fprintf(elefile, "gn1 1 0 sn");
  2749.     }
  2750.     fprintf(elefile, "kn");
  2751.   }
  2752. }
  2753. void print_edge(edgefile, nodes, dim, edges, nodeptr, edgeptr, normptr,
  2754.                 xscale, yscale, xoffset, yoffset, llcornerx, llcornery)
  2755. FILE *edgefile;
  2756. int nodes;
  2757. int dim;
  2758. int edges;
  2759. REAL *nodeptr;
  2760. int *edgeptr;
  2761. REAL *normptr;
  2762. REAL xscale;
  2763. REAL yscale;
  2764. REAL xoffset;
  2765. REAL yoffset;
  2766. int llcornerx;
  2767. int llcornery;
  2768. {
  2769.   int i;
  2770.   int index;
  2771.   REAL *point1, *point2;
  2772.   REAL normx, normy;
  2773.   REAL normmult, normmultx, normmulty;
  2774.   REAL windowxmin, windowymin, windowxmax, windowymax;
  2775.   index = 2;
  2776.   for (i = 1; i <= edges; i++) {
  2777.     point1 = &nodeptr[edgeptr[index++] * dim];
  2778.     if (edgeptr[index] == -1) {
  2779.       normx = normptr[index - 1];
  2780.       normy = normptr[index++];
  2781.       normmultx = 0.0;
  2782.       if (normx > 0) {
  2783.         windowxmax = ((REAL) (612 - llcornerx) - xoffset) / xscale;
  2784.         normmultx = (windowxmax - point1[0]) / normx;
  2785.       } else if (normx < 0) {
  2786.         windowxmin = ((REAL) llcornerx - xoffset) / xscale;
  2787.         normmultx = (windowxmin - point1[0]) / normx;
  2788.       }
  2789.       normmulty = 0.0;
  2790.       if (normy > 0) {
  2791.         windowymax = ((REAL) (792 - llcornery) - yoffset) / yscale;
  2792.         normmulty = (windowymax - point1[1]) / normy;
  2793.       } else if (normy < 0) {
  2794.         windowymin = ((REAL) llcornery - yoffset) / yscale;
  2795.         normmulty = (windowymin - point1[1]) / normy;
  2796.       }
  2797.       if (normmultx == 0.0) {
  2798.         normmult = normmulty;
  2799.       } else if (normmulty == 0.0) {
  2800.         normmult = normmultx;
  2801.       } else if (normmultx < normmulty) {
  2802.         normmult = normmultx;
  2803.       } else {
  2804.         normmult = normmulty;
  2805.       }
  2806.       if (normmult > 0.0) {
  2807.         fprintf(edgefile, "%d %d mn",
  2808.                 (int) (point1[0] * xscale + xoffset),
  2809.                 (int) (point1[1] * yscale + yoffset));
  2810.         fprintf(edgefile, "%d %d lnkn",
  2811.                 (int) ((point1[0] + normmult * normx) * xscale + xoffset),
  2812.                 (int) ((point1[1] + normmult * normy) * yscale + yoffset));
  2813.       }
  2814.     } else {
  2815.       point2 = &nodeptr[edgeptr[index++] * dim];
  2816.       fprintf(edgefile, "%d %d mn",
  2817.               (int) (point1[0] * xscale + xoffset),
  2818.               (int) (point1[1] * yscale + yoffset));
  2819.       fprintf(edgefile, "%d %d lnkn",
  2820.               (int) (point2[0] * xscale + xoffset),
  2821.               (int) (point2[1] * yscale + yoffset));
  2822.     }
  2823.   }
  2824. }
  2825. void print_adj(adjfile, dim, subdomains, ptr, center, xscale, yscale,
  2826.                xoffset, yoffset, llcornerx, llcornery)
  2827. FILE *adjfile;
  2828. int dim;
  2829. int subdomains;
  2830. int *ptr;
  2831. REAL *center;
  2832. REAL xscale;
  2833. REAL yscale;
  2834. REAL xoffset;
  2835. REAL yoffset;
  2836. int llcornerx;
  2837. int llcornery;
  2838. {
  2839.   int i, j;
  2840.   REAL *point1, *point2;
  2841.   int colorindex;
  2842.   if (!bw_ps) {
  2843.     fprintf(adjfile, "0 0 0 sn");
  2844.     fprintf(adjfile, "%d %d mn", llcornerx, llcornery);
  2845.     fprintf(adjfile, "%d %d ln", 612 - llcornerx, llcornery);
  2846.     fprintf(adjfile, "%d %d ln", 612 - llcornerx, 792 - llcornery);
  2847.     fprintf(adjfile, "%d %d ln", llcornerx, 792 - llcornery);
  2848.     fprintf(adjfile, "filln");
  2849.     fprintf(adjfile, "1 1 0 sn");
  2850.   }
  2851.   for (i = 0; i < subdomains; i++) {
  2852.     for (j = i + 1; j < subdomains; j++) {
  2853.       if (ptr[i * subdomains + j]) {
  2854.         point1 = &center[i * dim];
  2855.         point2 = &center[j * dim];
  2856.         fprintf(adjfile, "%d %d mn",
  2857.                 (int) (point1[0] * xscale + xoffset),
  2858.                 (int) (point1[1] * yscale + yoffset));
  2859.         fprintf(adjfile, "%d %d lnkn",
  2860.                 (int) (point2[0] * xscale + xoffset),
  2861.                 (int) (point2[1] * yscale + yoffset));
  2862.       }
  2863.     }
  2864.   }
  2865.   for (i = 0; i < subdomains; i++) {
  2866.     point1 = &center[i * dim];
  2867.     if (!bw_ps) {
  2868.       colorindex = i & 63;
  2869.       fprintf(adjfile, "%6.3f %6.3f %6.3f sn",
  2870.               (REAL) rgb[colorindex].red / 65535.0,
  2871.               (REAL) rgb[colorindex].green / 65535.0,
  2872.               (REAL) rgb[colorindex].blue / 65535.0);
  2873.       fprintf(adjfile, "%d %d %d 0 360 arcnfilln",
  2874.               (int) (point1[0] * xscale + xoffset),
  2875.               (int) (point1[1] * yscale + yoffset),
  2876.               5 + (line_width >> 1));
  2877.     } else {
  2878.       fprintf(adjfile, "%d %d %d 0 360 arcnfilln",
  2879.               (int) (point1[0] * xscale + xoffset),
  2880.               (int) (point1[1] * yscale + yoffset),
  2881.               3 + (line_width >> 1));
  2882.     }
  2883.   }
  2884. }
  2885. void print(inc, image, xmin, ymin, xmax, ymax, eps)
  2886. int inc;
  2887. int image;
  2888. REAL xmin;
  2889. REAL ymin;
  2890. REAL xmax;
  2891. REAL ymax;
  2892. int eps;
  2893. {
  2894.   REAL xxscale, yyscale, xxoffset, yyoffset;
  2895.   char psfilename[FILENAMESIZE];
  2896.   int llcornerx, llcornery;
  2897.   FILE *psfile;
  2898.   if (image == NOTHING) {
  2899.     return;
  2900.   }
  2901.   if (!loaded[inc][image]) {
  2902.     return;
  2903.   }
  2904.   if ((image == PART) && (explode || bw_ps)) {
  2905.     xmin += (xmin - partcenter[inc][subdomains[inc] << 1]) * explosion;
  2906.     xmax += (xmax - partcenter[inc][subdomains[inc] << 1]) * explosion;
  2907.     ymin += (ymin - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
  2908.     ymax += (ymax - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
  2909.   }
  2910.   xxscale = (460.0 - (REAL) line_width) / (xmax - xmin);
  2911.   yyscale = (640.0 - (REAL) line_width) / (ymax - ymin);
  2912.   if (xxscale > yyscale) {
  2913.     xxscale = yyscale;
  2914.     llcornerx = (604 - (int) (yyscale * (xmax - xmin)) - line_width) >> 1;
  2915.     llcornery = 72;
  2916.   } else {
  2917.     yyscale = xxscale;
  2918.     llcornerx = 72;
  2919.     llcornery = (784 - (int) (xxscale * (ymax - ymin)) - line_width) >> 1;
  2920.   }
  2921.   xxoffset = 0.5 * (612.0 - xxscale * (xmax - xmin)) - xxscale * xmin +
  2922.              (line_width >> 1);
  2923.   yyoffset = 0.5 * (792.0 - yyscale * (ymax - ymin)) - yyscale * ymin +
  2924.              (line_width >> 1);
  2925.   switch(image) {
  2926.     case NODE:
  2927.       addps(nodefilename[inc], psfilename, eps);
  2928.       break;
  2929.     case POLY:
  2930.       addps(polyfilename[inc], psfilename, eps);
  2931.       break;
  2932.     case ELE:
  2933.       addps(elefilename[inc], psfilename, eps);
  2934.       break;
  2935.     case EDGE:
  2936.       addps(edgefilename[inc], psfilename, eps);
  2937.       break;
  2938.     case PART:
  2939.       addps(partfilename[inc], psfilename, eps);
  2940.       break;
  2941.     case ADJ:
  2942.       addps(adjfilename[inc], psfilename, eps);
  2943.       break;
  2944.     case VORO:
  2945.       addps(vedgefilename[inc], psfilename, eps);
  2946.       break;
  2947.     default:
  2948.       break;
  2949.   }
  2950.   if (print_head(psfilename, &psfile, llcornerx, llcornery, eps)) {
  2951.     return;
  2952.   }
  2953.   switch(image) {
  2954.     case NODE:
  2955.       print_node(psfile, nodes[inc], node_dim[inc], nodeptr[inc],
  2956.                  xxscale, yyscale, xxoffset, yyoffset);
  2957.       break;
  2958.     case POLY:
  2959.       if (polynodes[inc] > 0) {
  2960.         print_poly(psfile, polynodes[inc], poly_dim[inc], polyedges[inc],
  2961.                    polyholes[inc], polynodeptr[inc], polyedgeptr[inc],
  2962.                    polyholeptr[inc], xxscale, yyscale, xxoffset, yyoffset);
  2963.       } else {
  2964.         print_poly(psfile, nodes[inc], node_dim[inc], polyedges[inc],
  2965.                    polyholes[inc], nodeptr[inc], polyedgeptr[inc],
  2966.                    polyholeptr[inc], xxscale, yyscale, xxoffset, yyoffset);
  2967.       }
  2968.       break;
  2969.     case ELE:
  2970.       print_ele(psfile, nodes[inc], node_dim[inc], elems[inc],
  2971.                 ele_corners[inc], nodeptr[inc], eleptr[inc],
  2972.                 (int *) NULL, (REAL *) NULL,
  2973.                 xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
  2974.       break;
  2975.     case EDGE:
  2976.       print_edge(psfile, nodes[inc], node_dim[inc], edges[inc],
  2977.                  nodeptr[inc], edgeptr[inc], normptr[inc],
  2978.                  xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
  2979.       break;
  2980.     case PART:
  2981.       print_ele(psfile, nodes[inc], node_dim[inc], elems[inc],
  2982.                 ele_corners[inc], nodeptr[inc], eleptr[inc],
  2983.                 partpart[inc], partshift[inc],
  2984.                 xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
  2985.       break;
  2986.     case ADJ:
  2987.       print_adj(psfile, node_dim[inc], adjsubdomains[inc], adjptr[inc],
  2988.                 partcenter[inc],
  2989.                 xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
  2990.       break;
  2991.     case VORO:
  2992.       print_edge(psfile, vnodes[inc], vnode_dim[inc], vedges[inc],
  2993.                  vnodeptr[inc], vedgeptr[inc], vnormptr[inc],
  2994.                  xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
  2995.       break;
  2996.     default:
  2997.       break;
  2998.   }
  2999.   if (!eps) {
  3000.     fprintf(psfile, "showpagen");
  3001.   }
  3002.   fclose(psfile);
  3003. }
  3004. int main(argc, argv)
  3005. int argc;
  3006. char **argv;
  3007. {
  3008.   REAL xmin, ymin, xmax, ymax;
  3009.   REAL xptr, yptr, xspan, yspan;
  3010.   int past_image;
  3011.   int new_image;
  3012.   int new_inc;
  3013.   parsecommandline(argc, argv);
  3014.   showme_init();
  3015.   choose_image(start_inc, start_image);
  3016.   showme_window(argc, argv);
  3017.   if (current_image != NOTHING) {
  3018.     xmin = xlo[current_inc][current_image];
  3019.     ymin = ylo[current_inc][current_image];
  3020.     xmax = xhi[current_inc][current_image];
  3021.     ymax = yhi[current_inc][current_image];
  3022.     zoom = 0;
  3023.   }
  3024.   XMaskEvent(display, ExposureMask, &event);
  3025.   while (1) {
  3026.     switch (event.type) {
  3027.       case ButtonRelease:
  3028.         if (event.xany.window == quitwin) {
  3029.           XDestroyWindow(display, mainwindow);
  3030.           XCloseDisplay(display);
  3031.           return 0;
  3032.         } else if (event.xany.window == leftwin) {
  3033.           xspan = 0.25 * (xmax - xmin);
  3034.           xmin += xspan;
  3035.           xmax += xspan;
  3036.           draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3037.         } else if (event.xany.window == rightwin) {
  3038.           xspan = 0.25 * (xmax - xmin);
  3039.           xmin -= xspan;
  3040.           xmax -= xspan;
  3041.           draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3042.         } else if (event.xany.window == upwin) {
  3043.           yspan = 0.25 * (ymax - ymin);
  3044.           ymin -= yspan;
  3045.           ymax -= yspan;
  3046.           draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3047.         } else if (event.xany.window == downwin) {
  3048.           yspan = 0.25 * (ymax - ymin);
  3049.           ymin += yspan;
  3050.           ymax += yspan;
  3051.           draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3052.         } else if (event.xany.window == resetwin) {
  3053.           xmin = xlo[current_inc][current_image];
  3054.           ymin = ylo[current_inc][current_image];
  3055.           xmax = xhi[current_inc][current_image];
  3056.           ymax = yhi[current_inc][current_image];
  3057.           zoom = 0;
  3058.           draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3059.         } else if (event.xany.window == widthpluswin) {
  3060.           if (line_width < 100) {
  3061.             line_width++;
  3062.             XSetLineAttributes(display, linegc, line_width, LineSolid,
  3063.                                CapRound, JoinRound);
  3064.             XSetLineAttributes(display, trianglegc, line_width, LineSolid,
  3065.                                CapRound, JoinRound);
  3066.             draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3067.           }
  3068.         } else if (event.xany.window == widthminuswin) {
  3069.           if (line_width > 1) {
  3070.             line_width--;
  3071.             XSetLineAttributes(display, linegc, line_width, LineSolid,
  3072.                                CapRound, JoinRound);
  3073.             XSetLineAttributes(display, trianglegc, line_width, LineSolid,
  3074.                                CapRound, JoinRound);
  3075.             draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3076.           }
  3077.         } else if (event.xany.window == expwin) {
  3078.           if ((current_image == PART) && loaded[current_inc][PART]) {
  3079.             explode = !explode;
  3080.             draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3081.           }
  3082.         } else if (event.xany.window == exppluswin) {
  3083.           if ((current_image == PART) && loaded[PART] && explode) {
  3084.             explosion += 0.125;
  3085.             findpartshift(subdomains[current_inc], explosion,
  3086.                           partcenter[current_inc], partshift[current_inc]);
  3087.             draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3088.           }
  3089.         } else if (event.xany.window == expminuswin) {
  3090.           if ((current_image == PART) && loaded[PART] && explode &&
  3091.               (explosion >= 0.125)) {
  3092.             explosion -= 0.125;
  3093.             findpartshift(subdomains[current_inc], explosion,
  3094.                           partcenter[current_inc], partshift[current_inc]);
  3095.             draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3096.           }
  3097.         } else if (event.xany.window == fillwin) {
  3098.           if ((current_image == PART) && loaded[PART]) {
  3099.             fillelem = !fillelem;
  3100.             draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3101.           }
  3102.         } else if (event.xany.window == pswin) {
  3103.           fill_button(pswin);
  3104.           XFlush(display);
  3105.           print(current_inc, current_image, xmin, ymin, xmax, ymax, 0);
  3106.           XClearWindow(display, pswin);
  3107.           XDrawString(display, pswin, fontgc, 2, 13, "PS", 2);
  3108.         } else if (event.xany.window == epswin) {
  3109.           fill_button(epswin);
  3110.           XFlush(display);
  3111.           print(current_inc, current_image, xmin, ymin, xmax, ymax, 1);
  3112.           XClearWindow(display, epswin);
  3113.           XDrawString(display, epswin, fontgc, 2, 13, "EPS", 3);
  3114.         } else if (event.xany.window == versionpluswin) {
  3115.           move_inc(1);
  3116.           loweriteration++;
  3117.           set_filenames(filename, loweriteration);
  3118.           if (current_inc == 1) {
  3119.             current_inc = 0;
  3120.           } else {
  3121.             current_image = NOTHING;
  3122.             XClearWindow(display, mainwindow);
  3123.           }
  3124.           draw_buttons();
  3125.         } else if (event.xany.window == versionminuswin) {
  3126.           if (loweriteration > 0) {
  3127.             move_inc(0);
  3128.             loweriteration--;
  3129.             set_filenames(filename, loweriteration);
  3130.             if (current_inc == 0) {
  3131.               current_inc = 1;
  3132.             } else {
  3133.               current_image = NOTHING;
  3134.               XClearWindow(display, mainwindow);
  3135.             }
  3136.             draw_buttons();
  3137.           }
  3138.         } else if ((event.xany.window == nodewin[0]) ||
  3139.                    (event.xany.window == polywin[0]) ||
  3140.                    (event.xany.window == elewin[0]) ||
  3141.                    (event.xany.window == edgewin[0]) ||
  3142.                    (event.xany.window == partwin[0]) ||
  3143.                    (event.xany.window == adjwin[0]) ||
  3144.                    (event.xany.window == voronoiwin[0]) ||
  3145.                    (event.xany.window == nodewin[1]) ||
  3146.                    (event.xany.window == polywin[1]) ||
  3147.                    (event.xany.window == elewin[1]) ||
  3148.                    (event.xany.window == edgewin[1]) ||
  3149.                    (event.xany.window == partwin[1]) ||
  3150.                    (event.xany.window == adjwin[1]) ||
  3151.                    (event.xany.window == voronoiwin[1])) {
  3152.           if (event.xany.window == nodewin[0]) {
  3153.             new_inc = 0;
  3154.             new_image = NODE;
  3155.           }
  3156.           if (event.xany.window == polywin[0]) {
  3157.             new_inc = 0;
  3158.             new_image = POLY;
  3159.           }
  3160.           if (event.xany.window == elewin[0]) {
  3161.             new_inc = 0;
  3162.             new_image = ELE;
  3163.           }
  3164.           if (event.xany.window == edgewin[0]) {
  3165.             new_inc = 0;
  3166.             new_image = EDGE;
  3167.           }
  3168.           if (event.xany.window == partwin[0]) {
  3169.             new_inc = 0;
  3170.             new_image = PART;
  3171.           }
  3172.           if (event.xany.window == adjwin[0]) {
  3173.             new_inc = 0;
  3174.             new_image = ADJ;
  3175.           }
  3176.           if (event.xany.window == voronoiwin[0]) {
  3177.             new_inc = 0;
  3178.             new_image = VORO;
  3179.           }
  3180.           if (event.xany.window == nodewin[1]) {
  3181.             new_inc = 1;
  3182.             new_image = NODE;
  3183.           }
  3184.           if (event.xany.window == polywin[1]) {
  3185.             new_inc = 1;
  3186.             new_image = POLY;
  3187.           }
  3188.           if (event.xany.window == elewin[1]) {
  3189.             new_inc = 1;
  3190.             new_image = ELE;
  3191.           }
  3192.           if (event.xany.window == edgewin[1]) {
  3193.             new_inc = 1;
  3194.             new_image = EDGE;
  3195.           }
  3196.           if (event.xany.window == partwin[1]) {
  3197.             new_inc = 1;
  3198.             new_image = PART;
  3199.           }
  3200.           if (event.xany.window == adjwin[1]) {
  3201.             new_inc = 1;
  3202.             new_image = ADJ;
  3203.           }
  3204.           if (event.xany.window == voronoiwin[1]) {
  3205.             new_inc = 1;
  3206.             new_image = VORO;
  3207.           }
  3208.           past_image = current_image;
  3209.           if ((current_inc == new_inc) && (current_image == new_image)) {
  3210.             free_inc(new_inc);
  3211.             unload_inc(new_inc);
  3212.           }
  3213.           choose_image(new_inc, new_image);
  3214.           if ((past_image == NOTHING) && (current_image != NOTHING)) {
  3215.             xmin = xlo[current_inc][current_image];
  3216.             ymin = ylo[current_inc][current_image];
  3217.             xmax = xhi[current_inc][current_image];
  3218.             ymax = yhi[current_inc][current_image];
  3219.             zoom = 0;
  3220.           }
  3221.           draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3222.         } else {
  3223.           xptr = ((REAL) event.xbutton.x - xoffset) / xscale;
  3224.           yptr = ((REAL) event.xbutton.y - yoffset) / yscale;
  3225.           if ((current_image == PART) && loaded[PART] && explode) {
  3226.             xptr = (xptr + partcenter[current_inc]
  3227.                                      [subdomains[current_inc] << 1]
  3228.                     * explosion) / (1.0 + explosion);
  3229.             yptr = (yptr + partcenter[current_inc]
  3230.                                      [(subdomains[current_inc] << 1) + 1]
  3231.                     * explosion) / (1.0 + explosion);
  3232.           }
  3233.           if ((event.xbutton.button == Button1)
  3234.               || (event.xbutton.button == Button3)) {
  3235.             if (event.xbutton.button == Button1) {
  3236.               xspan = 0.25 * (xmax - xmin);
  3237.               yspan = 0.25 * (ymax - ymin);
  3238.               zoom++;
  3239.             } else {
  3240.               xspan = xmax - xmin;
  3241.               yspan = ymax - ymin;
  3242.               zoom--;
  3243.             }
  3244.             xmin = xptr - xspan;
  3245.             ymin = yptr - yspan;
  3246.             xmax = xptr + xspan;
  3247.             ymax = yptr + yspan;
  3248.             draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3249.           } else if (event.xbutton.button == Button2) {
  3250.             printf("x = %.4g, y = %.4gn", xptr, yptr);
  3251.           }
  3252.         }
  3253.         break;
  3254.       case DestroyNotify:
  3255.         XDestroyWindow(display, mainwindow);
  3256.         XCloseDisplay(display);
  3257.         return 0;
  3258.       case ConfigureNotify:
  3259.         if ((width != event.xconfigure.width) ||
  3260.             (height != event.xconfigure.height - PANELHEIGHT)) {
  3261.           width = event.xconfigure.width;
  3262.           height = event.xconfigure.height - PANELHEIGHT;
  3263.           draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3264.           while (XCheckMaskEvent(display, ExposureMask, &event));
  3265.         }
  3266.         break;
  3267.       case Expose:
  3268.         draw(current_inc, current_image, xmin, ymin, xmax, ymax);
  3269.         while (XCheckMaskEvent(display, ExposureMask, &event));
  3270.         break;
  3271.       default:
  3272.         break;
  3273.     }
  3274.     XNextEvent(display, &event);
  3275.   }
  3276. }