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