Skip to content
Snippets Groups Projects
Commit 6cda65ed authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

Added Triangle to the repository (in previson of a future insertion as a third...

Added Triangle to the repository (in previson of a future insertion as a third alternative for 2D mesh generation)
parent 9187e29f
Branches
Tags
No related merge requests found
29 2 1 0
1 0.200000 -0.776400 -0.57
2 0.220000 -0.773200 -0.55
3 0.245600 -0.756400 -0.51
4 0.277600 -0.702000 -0.53
5 0.488800 -0.207600 0.28
6 0.504800 -0.207600 0.30
7 0.740800 -0.739600 0
8 0.756000 -0.761200 -0.01
9 0.774400 -0.772400 0
10 0.800000 -0.776400 0.02
11 0.800000 -0.792400 0.01
12 0.579200 -0.792400 -0.21
13 0.579200 -0.776400 -0.2
14 0.621600 -0.771600 -0.15
15 0.633600 -0.762800 -0.13
16 0.639200 -0.744400 -0.1
17 0.620800 -0.684400 -0.06
18 0.587200 -0.604400 -0.01
19 0.360800 -0.604400 -0.24
20 0.319200 -0.706800 -0.39
21 0.312000 -0.739600 -0.43
22 0.318400 -0.761200 -0.44
23 0.334400 -0.771600 -0.44
24 0.371200 -0.776400 -0.41
25 0.371200 -0.792400 -0.42
26 0.374400 -0.570000 -0.2
27 0.574400 -0.570000 0
28 0.473600 -0.330800 0.14
29 0.200000 -0.792400 -0.59
29 0
1 29 1
2 1 2
3 2 3
4 3 4
5 4 5
6 5 6
7 6 7
8 7 8
9 8 9
10 9 10
11 10 11
12 11 12
13 12 13
14 13 14
15 14 15
16 15 16
17 16 17
18 17 18
19 18 19
20 19 20
21 20 21
22 21 22
23 22 23
24 23 24
25 24 25
26 25 29
27 26 27
28 27 28
29 28 26
1
1 0.47 -0.5
Triangle
A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.
Version 1.3
Show Me
A Display Program for Meshes and More.
Version 1.3
Copyright 1996 Jonathan Richard Shewchuk
School of Computer Science
Carnegie Mellon University
5000 Forbes Avenue
Pittsburgh, Pennsylvania 15213-3891
Please send bugs and comments to jrs@cs.cmu.edu
Created as part of the Archimedes project (tools for parallel FEM).
Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.
There is no warranty whatsoever. Use at your own risk.
Triangle generates exact Delaunay triangulations, constrained Delaunay
triangulations, and quality conforming Delaunay triangulations. The
latter can be generated with no small angles, and are thus suitable for
finite element analysis. Show Me graphically displays the contents of
the geometric files used by Triangle. Show Me can also write images in
PostScript form.
Information on the algorithms used by Triangle, including complete
references, can be found in the comments at the beginning of the triangle.c
source file. Another listing of these references, with PostScript copies
of some of the papers, is available from the Web page
http://www.cs.cmu.edu/~quake/triangle.research.html
------------------------------------------------------------------------------
These programs may be freely redistributed under the condition that the
copyright notices (including the copy of this notice in the code comments
and the copyright notice printed when the `-h' switch is selected) are
not removed, and no compensation is received. Private, research, and
institutional use is free. You may distribute modified versions of this
code UNDER THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT
IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH
SOURCE AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND
CLEAR NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as
part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT
WITH THE AUTHOR. (If you are not directly supplying this code to a
customer, and you are instead telling them how they can obtain it for
free, then you are not required to make any arrangement with me.)
------------------------------------------------------------------------------
The files included in this distribution are:
README The file you're reading now.
triangle.c Complete C source code for Triangle.
showme.c Complete C source code for Show Me.
triangle.h Include file for calling Triangle from another program.
tricall.c Sample program that calls Triangle.
makefile Makefile for compiling Triangle and Show Me.
A.poly A sample data file.
Triangle and Show Me are each a single portable C file. The easiest way to
compile them is to edit and use the included makefile. Before compiling,
read the makefile, which describes your options, and edit it accordingly.
You should specify:
The source and binary directories.
The C compiler and level of optimization.
Do you want single precision or double? Do you want to leave out some of
Triangle's features to reduce the size of the executable file?
The "correct" directories for include files (especially X include files),
if necessary.
Once you've done this, type "make" to compile the programs. Alternatively,
the files are usually easy to compile without a makefile:
cc -O -o triangle triangle.c -lm
cc -O -o showme showme.c -lX11
On some systems, the C compiler won't be able to find the X include files
or libraries, and you'll need to specify an include path or library path:
cc -O -I/usr/local/include -o showme showme.c -L/usr/local/lib -lX11
However, on other systems (like my workstation), the latter incantation
will cause the wrong files to be read, and the Show Me mouse buttons won't
work properly in the main window. Hence, try the "-I" and "-L" switches
ONLY if the compiler fails without it. (If you're using the makefile, you
may edit it to add this switch.)
Some processors, possibly including Intel x86 family and Motorola 68xxx
family chips, are IEEE conformant but have extended length internal
floating-point registers that may defeat Triangle's exact arithmetic
routines by failing to cause enough roundoff error! Typically, there is
a way to set these internal registers so that they are rounded off to
IEEE single or double precision format. If you have such a processor,
you should check your C compiler or system manuals to find out how to
configure these internal registers to the precision you are using.
Otherwise, the exact arithmetic routines won't be exact at all.
Unfortunately, I don't have access to any such systems, and can't give
advice on how to configure them. These problems don't occur on any
workstations I am aware of. However, Triangle's exact arithmetic hasn't
a hope of working on machines like the Cray C90 or Y-MP, which are not
IEEE conformant and have inaccurate rounding.
Triangle and Show Me both produce their own documentation. Complete
instructions are printed by invoking each program with the `-h' switch:
triangle -h
showme -h
The instructions are long; you'll probably want to pipe the output to
`more' or `lpr' or redirect it to a file. Both programs give a short list
of command line options if they are invoked without arguments (that is,
just type `triangle' or `showme'). Alternatively, you may want to read
the instructions on the World Wide Web. The appropriate URLs are:
http://www.cs.cmu.edu/~quake/triangle.html
http://www.cs.cmu.edu/~quake/showme.html
Try out Triangle on the enclosed sample file, A.poly:
triangle -p A
showme A.poly &
Triangle will read the Planar Straight Line Graph defined by A.poly, and
write its constrained Delaunay triangulation to A.1.node and A.1.ele.
Show Me will display the figure defined by A.poly. There are two buttons
marked "ele" in the Show Me window; click on the top one. This will cause
Show Me to load and display the triangulation.
For contrast, try running
triangle -pq A
Now, click on the same "ele" button. A new triangulation will be loaded;
this one having no angles smaller than 20 degrees.
To see a Voronoi diagram, try this:
cp A.poly A.node
triangle -v A
Click the "ele" button again. You will see the Delaunay triangulation of
the points in A.poly, without the segments. Now click the top "voro" button.
You will see the Voronoi diagram corresponding to that Delaunay triangulation.
Click the "Reset" button to see the full extent of the diagram.
------------------------------------------------------------------------------
If you wish to call Triangle from another program, instructions for doing
so are contained in the file `triangle.h' (but read Triangle's regular
instructions first!). Also look at `tricall.c', which provides an example.
Type "make trilibrary" to create triangle.o, a callable object file.
Alternatively, the object file is usually easy to compile without a
makefile:
cc -DTRILIBRARY -O -c triangle.c
------------------------------------------------------------------------------
If you use Triangle, and especially if you use it to accomplish real
work, I would like very much to hear from you. A short letter or email
(to jrs@cs.cmu.edu) describing how you use Triangle will mean a lot to
me. The more people I know are using this program, the more easily I can
justify spending time on improvements and on the three-dimensional
successor to Triangle, which in turn will benefit you. Also, I can put
you on a list to receive email whenever a new version of Triangle is
available.
If you use a mesh generated by Triangle or plotted by Show Me in a
publication, please include an acknowledgment as well.
Jonathan Richard Shewchuk
July 20, 1996
# makefile for Triangle and Show Me
#
# Type "make" to compile Triangle and Show Me.
#
# After compiling, type "triangle -h" and "showme -h" to read instructions
# for using each of these programs.
#
# Type "make trilibrary" to compile Triangle as an object file (triangle.o).
#
# Type "make distclean" to delete all executable files.
# SRC is the directory in which the C source files are, and BIN is the
# directory where you want to put the executable programs. By default,
# both are the current directory.
SRC = ./
BIN = ./
# CC should be set to the name of your favorite C compiler.
CC = cc
# CSWITCHES is a list of all switches passed to the C compiler. I strongly
# recommend using the best level of optimization. I also strongly
# recommend timing each level of optimization to see which is the
# best. For instance, on my DEC Alpha using DEC's optimizing compiler,
# the -O2 switch generates a notably faster version of Triangle than the
# -O3 switch. Go figure.
#
# By default, Triangle and Show Me use double precision floating point
# numbers. If you prefer single precision, use the -DSINGLE switch.
# Double precision uses more memory, but improves the resolution of
# the meshes you can generate with Triangle. It also reduces the
# likelihood of a floating exception due to overflow. Also, it is
# much faster than single precision on 64-bit architectures like the
# DEC Alpha. I recommend double precision unless you want to generate
# a mesh for which you do not have enough memory to use double precision.
#
# If yours is not a Unix system, use the -DNO_TIMER switch to eliminate the
# Unix-specific timer code.
#
# If you are modifying Triangle, I recommend using the -DSELF_CHECK switch
# while you are debugging. Defining the SELF_CHECK symbol causes
# Triangle to include self-checking code. Triangle will execute more
# slowly, however, so be sure to remove this switch before compiling a
# production version.
#
# If the size of the Triangle binary is important to you, you may wish to
# generate a reduced version of Triangle. The -DREDUCED switch gets rid
# of all features that are primarily of research interest. Specifically,
# defining the REDUCED symbol eliminates the -i, -F, -s, and -C switches.
# The -DCDT_ONLY switch gets rid of all meshing algorithms above and beyond
# constrained Delaunay triangulation. Specifically, defining the CDT_ONLY
# symbol eliminates the -r, -q, -a, -S, and -s switches. The REDUCED and
# CDT_ONLY symbols may be particularly attractive when Triangle is called
# by another program that does not need all of Triangle's features; in
# this case, these switches should appear as part of "TRILIBDEFS" below.
#
# On some systems, you may need to include -I/usr/local/include and/or
# -L/usr/local/lib in the compiler options to ensure that the X include
# files and libraries that Show Me needs are found. If you get errors
# like "Can't find include file X11/Xlib.h", you need the former switch.
# Try compiling without them first; add them if that fails.
#
# An example CSWITCHES line is:
#
# CSWITCHES = -O -DNO_TIMER -I/usr/local/include -L/usr/local/lib
CSWITCHES = -O
# TRILIBDEFS is a list of definitions used to compile an object code version
# of Triangle (triangle.o) to be called by another program. The file
# "triangle.h" contains detailed information on how to call triangle.o.
#
# The -DTRILIBRARY should always be used when compiling Triangle into an
# object file.
#
# An example TRILIBDEFS line is:
#
# TRILIBDEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
TRILIBDEFS = -DTRILIBRARY
# RM should be set to the name of your favorite rm (file deletion program).
RM = /bin/rm
# The action starts here.
all: $(BIN)triangle $(BIN)showme
trilibrary: $(BIN)triangle.o $(BIN)tricall
$(BIN)triangle: $(SRC)triangle.c
$(CC) $(CSWITCHES) -o $(BIN)triangle $(SRC)triangle.c -lm
$(BIN)tricall: $(BIN)tricall.c $(BIN)triangle.o
$(CC) $(CSWITCHES) -o $(BIN)tricall $(SRC)tricall.c \
$(BIN)triangle.o -lm
$(BIN)triangle.o: $(SRC)triangle.c $(SRC)triangle.h
$(CC) $(CSWITCHES) $(TRILIBDEFS) -c -o $(BIN)triangle.o \
$(SRC)triangle.c
$(BIN)showme: $(SRC)showme.c
$(CC) $(CSWITCHES) -o $(BIN)showme $(SRC)showme.c -lX11
distclean:
$(RM) $(BIN)triangle $(BIN)triangle.o $(BIN)showme
/*****************************************************************************/
/* */
/* ,d88^^o 888 o o */
/* 8888 888o^88, o88^^o Y88b o / d8b d8b o88^^8o */
/* "Y88b 888 888 d888 b Y88b d8b / d888bdY88b d888 88b */
/* "Y88b, 888 888 8888 8 Y888/Y88b/ / Y88Y Y888b 8888oo888 */
/* o 8888 888 888 q888 p Y8/ Y8/ / YY Y888b q888 */
/* "oo88P" 888 888 "88oo" Y Y / Y888b "88oooo" */
/* */
/* A Display Program for Meshes and More. */
/* (showme.c) */
/* */
/* Version 1.3 */
/* July 20, 1996 */
/* */
/* Copyright 1996 */
/* Jonathan Richard Shewchuk */
/* School of Computer Science */
/* Carnegie Mellon University */
/* 5000 Forbes Avenue */
/* Pittsburgh, Pennsylvania 15213-3891 */
/* jrs@cs.cmu.edu */
/* */
/* This program may be freely redistributed under the condition that the */
/* copyright notices (including this entire header and the copyright */
/* notice printed when the `-h' switch is selected) are not removed, and */
/* no compensation is received. Private, research, and institutional */
/* use is free. You may distribute modified versions of this code UNDER */
/* THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE */
/* SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE */
/* AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR */
/* NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as */
/* part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT */
/* WITH THE AUTHOR. (If you are not directly supplying this code to a */
/* customer, and you are instead telling them how they can obtain it for */
/* free, then you are not required to make any arrangement with me.) */
/* */
/* Hypertext instructions for Triangle are available on the Web at */
/* */
/* http://www.cs.cmu.edu/~quake/showme.html */
/* */
/* Show Me was created as part of the Archimedes project in the School of */
/* Computer Science at Carnegie Mellon University. Archimedes is a */
/* system for compiling parallel finite element solvers. For further */
/* information, see Anja Feldmann, Omar Ghattas, John R. Gilbert, Gary L. */
/* Miller, David R. O'Hallaron, Eric J. Schwabe, Jonathan R. Shewchuk, */
/* and Shang-Hua Teng. "Automated Parallel Solution of Unstructured PDE */
/* Problems." To appear in Communications of the ACM, we hope. */
/* */
/* If you make any improvements to this code, please please please let me */
/* know, so that I may obtain the improvements. Even if you don't change */
/* the code, I'd still love to hear what it's being used for. */
/* */
/* Disclaimer: Neither I nor Carnegie Mellon warrant this code in any way */
/* whatsoever. Use at your own risk. */
/* */
/*****************************************************************************/
/* For single precision (which will save some memory and reduce paging), */
/* write "#define SINGLE" below. */
/* */
/* For double precision (which will allow you to display triangulations of */
/* a finer resolution), leave SINGLE undefined. */
/* #define SINGLE */
#ifdef SINGLE
#define REAL float
#else
#define REAL double
#endif
/* Maximum number of characters in a file name (including the null). */
#define FILENAMESIZE 1024
/* Maximum number of characters in a line read from a file (including the */
/* null). */
#define INPUTLINESIZE 512
#define STARTWIDTH 414
#define STARTHEIGHT 414
#define MINWIDTH 50
#define MINHEIGHT 50
#define BUTTONHEIGHT 21
#define BUTTONROWS 3
#define PANELHEIGHT (BUTTONHEIGHT * BUTTONROWS)
#define MAXCOLORS 64
#define IMAGE_TYPES 7
#define NOTHING -1
#define NODE 0
#define POLY 1
#define ELE 2
#define EDGE 3
#define PART 4
#define ADJ 5
#define VORO 6
#define STARTEXPLOSION 0.5
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
/* The following obscenity seems to be necessary to ensure that this program */
/* will port to Dec Alphas running OSF/1, because their stdio.h file commits */
/* the unpardonable sin of including stdlib.h. Hence, malloc(), free(), and */
/* exit() may or may not already be defined at this point. I declare these */
/* functions explicitly because some non-ANSI C compilers lack stdlib.h. */
#ifndef _STDLIB_H_
extern char *malloc();
extern void free();
extern void exit();
extern double strtod();
extern long strtol();
#endif
/* A necessary forward declaration. */
int load_image();
Display *display;
int screen;
Window rootwindow;
Window mainwindow;
Window quitwin;
Window leftwin;
Window rightwin;
Window upwin;
Window downwin;
Window resetwin;
Window pswin;
Window epswin;
Window expwin;
Window exppluswin;
Window expminuswin;
Window widthpluswin;
Window widthminuswin;
Window versionpluswin;
Window versionminuswin;
Window fillwin;
Window nodewin[2];
Window polywin[2];
Window elewin[2];
Window edgewin[2];
Window partwin[2];
Window adjwin[2];
Window voronoiwin[2];
int windowdepth;
XEvent event;
Colormap rootmap;
XFontStruct *font;
int width, height;
int black, white;
int showme_foreground;
GC fontgc;
GC blackfontgc;
GC linegc;
GC trianglegc;
int colors[MAXCOLORS];
XColor rgb[MAXCOLORS];
int color;
int start_image, current_image;
int start_inc, current_inc;
int loweriteration;
int line_width;
int loaded[2][IMAGE_TYPES];
REAL xlo[2][IMAGE_TYPES], ylo[2][IMAGE_TYPES];
REAL xhi[2][IMAGE_TYPES], yhi[2][IMAGE_TYPES];
REAL xscale, yscale;
REAL xoffset, yoffset;
int zoom;
int nodes[2], node_dim[2];
REAL *nodeptr[2];
int polynodes[2], poly_dim[2], polyedges[2], polyholes[2];
REAL *polynodeptr[2], *polyholeptr[2];
int *polyedgeptr[2];
int elems[2], ele_corners[2];
int *eleptr[2];
int edges[2];
int *edgeptr[2];
REAL *normptr[2];
int subdomains[2];
int *partpart[2];
REAL *partcenter[2], *partshift[2];
int adjsubdomains[2];
int *adjptr[2];
int vnodes[2], vnode_dim[2];
REAL *vnodeptr[2];
int vedges[2];
int *vedgeptr[2];
REAL *vnormptr[2];
int firstnumber[2];
int quiet, fillelem, bw_ps, explode;
REAL explosion;
char filename[FILENAMESIZE];
char nodefilename[2][FILENAMESIZE];
char polyfilename[2][FILENAMESIZE];
char elefilename[2][FILENAMESIZE];
char edgefilename[2][FILENAMESIZE];
char partfilename[2][FILENAMESIZE];
char adjfilename[2][FILENAMESIZE];
char vnodefilename[2][FILENAMESIZE];
char vedgefilename[2][FILENAMESIZE];
char *colorname[] = {"aquamarine", "red", "green yellow", "magenta",
"yellow", "green", "orange", "blue",
"white", "sandy brown", "cyan", "moccasin",
"cadet blue", "coral", "cornflower blue", "sky blue",
"firebrick", "forest green", "gold", "goldenrod",
"gray", "hot pink", "chartreuse", "pale violet red",
"indian red", "khaki", "lavender", "light blue",
"light gray", "light steel blue", "lime green", "azure",
"maroon", "medium aquamarine", "dodger blue", "honeydew",
"medium orchid", "medium sea green", "moccasin",
"medium slate blue", "medium spring green",
"medium turquoise", "medium violet red",
"orange red", "chocolate", "light goldenrod",
"orchid", "pale green", "pink", "plum",
"purple", "salmon", "sea green",
"sienna", "slate blue", "spring green",
"steel blue", "tan", "thistle", "turquoise",
"violet", "violet red", "wheat",
"yellow green"};
void syntax()
{
printf("showme [-bfw_Qh] input_file\n");
printf(" -b Black and white PostScript (default is color).\n");
printf(" -f Fill triangles of partitioned mesh with color.\n");
printf(" -w Set line width to some specified number.\n");
printf(" -Q Quiet: No terminal output except errors.\n");
printf(" -h Help: Detailed instructions for Show Me.\n");
exit(0);
}
void info()
{
printf("Show Me\n");
printf("A Display Program for Meshes and More.\n");
printf("Version 1.3\n\n");
printf(
"Copyright 1996 Jonathan Richard Shewchuk (bugs/comments to jrs@cs.cmu.edu)\n"
);
printf("School of Computer Science / Carnegie Mellon University\n");
printf("5000 Forbes Avenue / Pittsburgh, Pennsylvania 15213-3891\n");
printf(
"Created as part of the Archimedes project (tools for parallel FEM).\n");
printf(
"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
printf("There is no warranty whatsoever. Use at your own risk.\n");
#ifdef SINGLE
printf("This executable is compiled for single precision arithmetic.\n\n\n");
#else
printf("This executable is compiled for double precision arithmetic.\n\n\n");
#endif
printf(
"Show Me graphically displays the contents of geometric files, especially\n");
printf(
"those generated by Triangle, my two-dimensional quality mesh generator and\n"
);
printf(
"Delaunay triangulator. Show Me can also write images in PostScript form.\n");
printf(
"Show Me is also useful for checking the consistency of the files you create\n"
);
printf(
"as input to Triangle; Show Me does these checks more thoroughly than\n");
printf("Triangle does. The command syntax is:\n\n");
printf("showme [-bfw_Qh] input_file\n\n");
printf(
"The underscore indicates that a number should follow the -w switch.\n");
printf(
"input_file may be one of several types of file. It must have extension\n");
printf(
".node, .poly, .ele, .edge, .part, or .adj. If no extension is provided,\n");
printf(
"Show Me will assume the extension .ele. A .node file represents a set of\n");
printf(
"points; a .poly file represents a Planar Straight Line Graph; an .ele file\n"
);
printf(
"(coupled with a .node file) represents the elements of a mesh or the\n");
printf(
"triangles of a triangulation; an .edge file (coupled with a .node file)\n");
printf(
"represents a set of edges; a .part file specifies a partition of a mesh;\n");
printf(
"and a .adj file represents the adjacency graph defined by a partition.\n");
printf("\n");
printf("Command Line Switches:\n");
printf("\n");
printf(
" -b Makes all PostScript output black and white. If this switch is not\n"
);
printf(
" selected, color PostScript is used for partitioned meshes and\n");
printf(" adjacency graphs (.part and .adj files).\n");
printf(
" -f On color displays and in color PostScript, displays partitioned\n");
printf(
" meshes by filling triangles with color, rather than by coloring the\n"
);
printf(
" edges. This switch will result in a clearer picture if all\n");
printf(
" triangles are reasonably large, and a less clear picture if small\n");
printf(
" triangles are present. (There is also a button to toggle this\n");
printf(" behavior.)\n");
printf(
" -w Followed by an integer, specifies the line width used in all\n");
printf(
" images. (There are also buttons to change the line width.)\n");
printf(
" -Q Quiet: Suppresses all explanation of what Show Me is doing, unless\n"
);
printf(" an error occurs.\n");
printf(" -h Help: Displays these instructions.\n");
printf("\n");
printf("Controls:\n");
printf("\n");
printf(
" To zoom in on an image, point at the location where you want a closer\n");
printf(
" look, and click the left mouse button. To zoom out, click the right\n");
printf(
" mouse button. In either case, the point you click on will be centered in\n"
);
printf(
" the window. If you want to know the coordinates of a point, click the\n");
printf(
" middle mouse button; the coordinates will be printed on the terminal you\n"
);
printf(" invoked Show Me from.\n\n");
printf(
" If you resize the window, the image will grow or shrink to match.\n");
printf("\n");
printf(
" There is a panel of control buttons at the bottom of the Show Me window:\n"
);
printf("\n");
printf(" Quit: Shuts down Show Me.\n");
printf(" <, >, ^, v: Moves the image in the indicated direction.\n");
printf(
" Reset: Unzooms and centers the image in the window. When you switch from\n"
);
printf(
" one image to another, the viewing region does not change, so you may\n");
printf(
" need to reset the new image to make it fully visible. This often is\n");
printf(
" the case when switching between Delaunay triangulations and their\n");
printf(
" corresponding Voronoi diagrams, as Voronoi vertices can be far from the\n"
);
printf(" initial point set.\n");
printf(
" Width+, -: Increases or decreases the width of all lines and points.\n");
printf(
" Exp, +, -: These buttons appear only when you are viewing a partitioned\n"
);
printf(
" mesh (.part file). `Exp' toggles between an exploded and non-exploded\n"
);
printf(
" image of the mesh. The non-exploded image will not show the partition\n"
);
printf(
" on a black and white monitor. `+' and `-' allow you to adjust the\n");
printf(
" spacing between pieces of the mesh to better distinguish them.\n");
printf(
" Fill: This button appears only when you are viewing a partitioned mesh\n");
printf(
" (.part file). It toggles between color-filled triangles and colored\n");
printf(
" edges (as the -f switch does). Filled triangles look better when all\n");
printf(
" triangles are reasonably large; colored edges look better when there\n");
printf(" are very small triangles present.\n");
printf(
" PS: Creates a PostScript file containing the image you are viewing. If\n"
);
printf(
" the -b switch is selected, all PostScript output will be black and\n");
printf(
" white; otherwise, .part.ps and .adj.ps files will be color, independent\n"
);
printf(
" of whether you are using a color monitor. Normally the output will\n");
printf(
" preserve the properties of the image you see on the screen, including\n");
printf(
" zoom and line width; however, if black and white output is selected (-b\n"
);
printf(
" switch), partitioned meshes will always be drawn exploded. The output\n"
);
printf(
" file name depends on the image being viewed. If you want several\n");
printf(
" different snapshots (zooming in on different parts) of the same object,\n"
);
printf(
" you'll have to rename each file after Show Me creates it so that it\n");
printf(" isn't overwritten by the next snapshot.\n");
printf(
" EPS: Creates an encapsulated PostScript file, suitable for inclusion in\n"
);
printf(
" documents. Otherwise, this button is just like the PS button. (The\n");
printf(
" main difference is that .eps files lack a `showpage' command at the\n");
printf(" end.)\n\n");
printf(
" There are two nearly-identical rows of buttons that load different images\n"
);
printf(" from disk. Each row contains the following buttons:\n\n");
printf(" node: Loads a .node file.\n");
printf(
" poly: Loads a .poly file (and possibly an associated .node file).\n");
printf(" ele: Loads an .ele file (and associated .node file).\n");
printf(" edge: Loads an .edge file (and associated .node file).\n");
printf(
" part: Loads a .part file (and associated .node and .ele files).\n");
printf(
" adj: Loads an .adj file (and associated .node, .ele, and .part files).\n");
printf(" voro: Loads a .v.node and .v.edge file for a Voronoi diagram.\n");
printf("\n");
printf(
" Each row represents a different iteration number of the geometry files.\n");
printf(
" For a full explanation of iteration numbers, read the instructions for\n");
printf(
" Triangle. Briefly, iteration numbers are used to allow a user to easily\n"
);
printf(
" represent a sequence of related triangulations. Iteration numbers are\n");
printf(
" used in the names of geometry files; for instance, mymesh.3.ele is a\n");
printf(
" triangle file with iteration number three, and mymesh.ele has an implicit\n"
);
printf(" iteration number of zero.\n\n");
printf(
" The control buttons at the right end of each row display the two\n");
printf(
" iterations currently under view. These buttons can be clicked to\n");
printf(
" increase or decrease the iteration numbers, and thus conveniently view\n");
printf(" a sequence of meshes.\n\n");
printf(
" Show Me keeps each file in memory after loading it, but you can force\n");
printf(
" Show Me to reread a set of files (for one iteration number) by reclicking\n"
);
printf(
" the button that corresponds to the current image. This is convenient if\n"
);
printf(" you have changed a geometry file.\n\n");
printf("File Formats:\n\n");
printf(
" All files may contain comments prefixed by the character '#'. Points,\n");
printf(
" segments, holes, triangles, edges, and subdomains must be numbered\n");
printf(
" consecutively, starting from either 1 or 0. Whichever you choose, all\n");
printf(
" input files must be consistent (for any single iteration number); if the\n"
);
printf(
" nodes are numbered from 1, so must be all other objects. Show Me\n");
printf(
" automatically detects your choice while reading a .node (or .poly) file.\n"
);
printf(" Examples of these file formats are given below.\n\n");
printf(" .node files:\n");
printf(
" First line: <# of points> <dimension (must be 2)> <# of attributes>\n");
printf(
" <# of boundary markers (0 or 1)>\n"
);
printf(
" Remaining lines: <point #> <x> <y> [attributes] [boundary marker]\n");
printf("\n");
printf(
" The attributes, which are typically floating-point values of physical\n");
printf(
" quantities (such as mass or conductivity) associated with the nodes of\n"
);
printf(
" a finite element mesh, are ignored by Show Me. Show Me also ignores\n");
printf(
" boundary markers. See the instructions for Triangle to find out what\n");
printf(" attributes and boundary markers are.\n\n");
printf(" .poly files:\n");
printf(
" First line: <# of points> <dimension (must be 2)> <# of attributes>\n");
printf(
" <# of boundary markers (0 or 1)>\n"
);
printf(
" Following lines: <point #> <x> <y> [attributes] [boundary marker]\n");
printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
printf(
" Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
printf(" One line: <# of holes>\n");
printf(" Following lines: <hole #> <x> <y>\n");
printf(" [Optional additional lines that are ignored]\n\n");
printf(
" A .poly file represents a Planar Straight Line Graph (PSLG), an idea\n");
printf(
" familiar to computational geometers. By definition, a PSLG is just a\n");
printf(
" list of points and edges. A .poly file also contains some additional\n");
printf(" information.\n\n");
printf(
" The first section lists all the points, and is identical to the format\n"
);
printf(
" of .node files. <# of points> may be set to zero to indicate that the\n"
);
printf(
" points are listed in a separate .node file; .poly files produced by\n");
printf(
" Triangle always have this format. When Show Me reads such a file, it\n");
printf(" also reads the corresponding .node file.\n\n");
printf(
" The second section lists the segments. Segments are edges whose\n");
printf(
" presence in a triangulation produced from the PSLG is enforced. Each\n");
printf(
" segment is specified by listing the indices of its two endpoints. This\n"
);
printf(
" means that its endpoints must be included in the point list. Each\n");
printf(
" segment, like each point, may have a boundary marker, which is ignored\n"
);
printf(" by Show Me.\n\n");
printf(
" The third section lists holes and concavities that are desired in any\n");
printf(
" triangulation generated from the PSLG. Holes are specified by\n");
printf(" identifying a point inside each hole.\n\n");
printf(" .ele files:\n");
printf(
" First line: <# of triangles> <points per triangle> <# of attributes>\n");
printf(
" Remaining lines: <triangle #> <point> <point> <point> ... [attributes]\n"
);
printf("\n");
printf(
" Points are indices into the corresponding .node file. Show Me ignores\n"
);
printf(
" all but the first three points of each triangle; these should be the\n");
printf(
" corners listed in counterclockwise order around the triangle. The\n");
printf(" attributes are ignored by Show Me.\n\n");
printf(" .edge files:\n");
printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
printf(
" Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
printf("\n");
printf(
" Endpoints are indices into the corresponding .node file. The boundary\n"
);
printf(" markers are ignored by Show Me.\n\n");
printf(
" In Voronoi diagrams, one also finds a special kind of edge that is an\n");
printf(
" infinite ray with only one endpoint. For these edges, a different\n");
printf(" format is used:\n\n");
printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
printf(
" The `direction' is a floating-point vector that indicates the direction\n"
);
printf(" of the infinite ray.\n\n");
printf(" .part files:\n");
printf(" First line: <# of triangles> <# of subdomains>\n");
printf(" Remaining lines: <triangle #> <subdomain #>\n\n");
printf(
" The set of triangles is partitioned by a .part file; each triangle is\n");
printf(" mapped to a subdomain.\n\n");
printf(" .adj files:\n");
printf(" First line: <# of subdomains>\n");
printf(" Remaining lines: <adjacency matrix entry>\n\n");
printf(
" An .adj file represents adjacencies between subdomains (presumably\n");
printf(" computed by a partitioner). The first line is followed by\n");
printf(
" (subdomains X subdomains) lines, each containing one entry of the\n");
printf(
" adjacency matrix. A nonzero entry indicates that two subdomains are\n");
printf(" adjacent (share a point).\n\n");
printf("Example:\n\n");
printf(
" Here is a sample file `box.poly' describing a square with a square hole:\n"
);
printf("\n");
printf(
" # A box with eight points in 2D, no attributes, no boundary marker.\n");
printf(" 8 2 0 0\n");
printf(" # Outer box has these vertices:\n");
printf(" 1 0 0\n");
printf(" 2 0 3\n");
printf(" 3 3 0\n");
printf(" 4 3 3\n");
printf(" # Inner square has these vertices:\n");
printf(" 5 1 1\n");
printf(" 6 1 2\n");
printf(" 7 2 1\n");
printf(" 8 2 2\n");
printf(" # Five segments without boundary markers.\n");
printf(" 5 0\n");
printf(" 1 1 2 # Left side of outer box.\n");
printf(" 2 5 7 # Segments 2 through 5 enclose the hole.\n");
printf(" 3 7 8\n");
printf(" 4 8 6\n");
printf(" 5 6 5\n");
printf(" # One hole in the middle of the inner square.\n");
printf(" 1\n");
printf(" 1 1.5 1.5\n\n");
printf(
" After this PSLG is triangulated by Triangle, the resulting triangulation\n"
);
printf(
" consists of a .node and .ele file. Here is the former, `box.1.node',\n");
printf(" which duplicates the points of the PSLG:\n\n");
printf(" 8 2 0 0\n");
printf(" 1 0 0\n");
printf(" 2 0 3\n");
printf(" 3 3 0\n");
printf(" 4 3 3\n");
printf(" 5 1 1\n");
printf(" 6 1 2\n");
printf(" 7 2 1\n");
printf(" 8 2 2\n");
printf(" # Generated by triangle -pcBev box\n");
printf("\n");
printf(" Here is the triangulation file, `box.1.ele'.\n");
printf("\n");
printf(" 8 3 0\n");
printf(" 1 1 5 6\n");
printf(" 2 5 1 3\n");
printf(" 3 2 6 8\n");
printf(" 4 6 2 1\n");
printf(" 5 7 3 4\n");
printf(" 6 3 7 5\n");
printf(" 7 8 4 2\n");
printf(" 8 4 8 7\n");
printf(" # Generated by triangle -pcBev box\n\n");
printf(" Here is the edge file for the triangulation, `box.1.edge'.\n\n");
printf(" 16 0\n");
printf(" 1 1 5\n");
printf(" 2 5 6\n");
printf(" 3 6 1\n");
printf(" 4 1 3\n");
printf(" 5 3 5\n");
printf(" 6 2 6\n");
printf(" 7 6 8\n");
printf(" 8 8 2\n");
printf(" 9 2 1\n");
printf(" 10 7 3\n");
printf(" 11 3 4\n");
printf(" 12 4 7\n");
printf(" 13 7 5\n");
printf(" 14 8 4\n");
printf(" 15 4 2\n");
printf(" 16 8 7\n");
printf(" # Generated by triangle -pcBev box\n");
printf("\n");
printf(
" Here's a file `box.1.part' that partitions the mesh into four subdomains.\n"
);
printf("\n");
printf(" 8 4\n");
printf(" 1 3\n");
printf(" 2 3\n");
printf(" 3 4\n");
printf(" 4 4\n");
printf(" 5 1\n");
printf(" 6 1\n");
printf(" 7 2\n");
printf(" 8 2\n");
printf(" # Generated by slice -s4 box.1\n\n");
printf(
" Here's a file `box.1.adj' that represents the resulting adjacencies.\n");
printf("\n");
printf(" 4\n");
printf(" 9\n");
printf(" 2\n");
printf(" 2\n");
printf(" 0\n");
printf(" 2\n");
printf(" 9\n");
printf(" 0\n");
printf(" 2\n");
printf(" 2\n");
printf(" 0\n");
printf(" 9\n");
printf(" 2\n");
printf(" 0\n");
printf(" 2\n");
printf(" 2\n");
printf(" 9\n");
printf("\n");
printf("Display Speed:\n");
printf("\n");
printf(
" It is worthwhile to note that .edge files typically plot and print twice\n"
);
printf(
" as quickly as .ele files, because .ele files cause each internal edge to\n"
);
printf(
" be drawn twice. For the same reason, PostScript files created from edge\n"
);
printf(" sets are smaller than those created from triangulations.\n\n");
printf("Show Me on the Web:\n\n");
printf(
" To see an illustrated, updated version of these instructions, check out\n");
printf("\n");
printf(" http://www.cs.cmu.edu/~quake/showme.html\n");
printf("\n");
printf("A Brief Plea:\n");
printf("\n");
printf(
" If you use Show Me (or Triangle), and especially if you use it to\n");
printf(
" accomplish real work, I would like very much to hear from you. A short\n");
printf(
" letter or email (to jrs@cs.cmu.edu) describing how you use Show Me (and\n");
printf(
" its sister programs) will mean a lot to me. The more people I know\n");
printf(
" are using my programs, the more easily I can justify spending time on\n");
printf(
" improvements, which in turn will benefit you. Also, I can put you\n");
printf(
" on a list to receive email whenever new versions are available.\n");
printf("\n");
printf(
" If you use a PostScript file generated by Show Me in a publication,\n");
printf(" please include an acknowledgment as well.\n\n");
exit(0);
}
void set_filenames(filename, lowermeshnumber)
char *filename;
int lowermeshnumber;
{
char numberstring[100];
int i;
for (i = 0; i < 2; i++) {
strcpy(nodefilename[i], filename);
strcpy(polyfilename[i], filename);
strcpy(elefilename[i], filename);
strcpy(edgefilename[i], filename);
strcpy(partfilename[i], filename);
strcpy(adjfilename[i], filename);
strcpy(vnodefilename[i], filename);
strcpy(vedgefilename[i], filename);
if (lowermeshnumber + i > 0) {
sprintf(numberstring, ".%d", lowermeshnumber + i);
strcat(nodefilename[i], numberstring);
strcat(polyfilename[i], numberstring);
strcat(elefilename[i], numberstring);
strcat(edgefilename[i], numberstring);
strcat(partfilename[i], numberstring);
strcat(adjfilename[i], numberstring);
strcat(vnodefilename[i], numberstring);
strcat(vedgefilename[i], numberstring);
}
strcat(nodefilename[i], ".node");
strcat(polyfilename[i], ".poly");
strcat(elefilename[i], ".ele");
strcat(edgefilename[i], ".edge");
strcat(partfilename[i], ".part");
strcat(adjfilename[i], ".adj");
strcat(vnodefilename[i], ".v.node");
strcat(vedgefilename[i], ".v.edge");
}
}
void parsecommandline(argc, argv)
int argc;
char **argv;
{
int increment;
int meshnumber;
int i, j;
quiet = 0;
fillelem = 0;
line_width = 1;
bw_ps = 0;
start_image = ELE;
filename[0] = '\0';
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
for (j = 1; argv[i][j] != '\0'; j++) {
if (argv[i][j] == 'f') {
fillelem = 1;
}
if (argv[i][j] == 'w') {
if ((argv[i][j + 1] >= '1') && (argv[i][j + 1] <= '9')) {
line_width = 0;
while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
j++;
line_width = line_width * 10 + (int) (argv[i][j] - '0');
}
if (line_width > 100) {
printf("Error: Line width cannot exceed 100.\n");
line_width = 1;
}
}
}
if (argv[i][j] == 'b') {
bw_ps = 1;
}
if (argv[i][j] == 'Q') {
quiet = 1;
}
if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
(argv[i][j] == '?')) {
info();
}
}
} else {
strcpy(filename, argv[i]);
}
}
if (filename[0] == '\0') {
syntax();
}
if (!strcmp(&filename[strlen(filename) - 5], ".node")) {
filename[strlen(filename) - 5] = '\0';
start_image = NODE;
}
if (!strcmp(&filename[strlen(filename) - 5], ".poly")) {
filename[strlen(filename) - 5] = '\0';
start_image = POLY;
}
if (!strcmp(&filename[strlen(filename) - 4], ".ele")) {
filename[strlen(filename) - 4] = '\0';
start_image = ELE;
}
if (!strcmp(&filename[strlen(filename) - 5], ".edge")) {
filename[strlen(filename) - 5] = '\0';
start_image = EDGE;
}
if (!strcmp(&filename[strlen(filename) - 5], ".part")) {
filename[strlen(filename) - 5] = '\0';
start_image = PART;
}
if (!strcmp(&filename[strlen(filename) - 4], ".adj")) {
filename[strlen(filename) - 4] = '\0';
start_image = ADJ;
}
increment = 0;
j = 1;
while (filename[j] != '\0') {
if ((filename[j] == '.') && (filename[j + 1] != '\0')) {
increment = j + 1;
}
j++;
}
meshnumber = 0;
if (increment > 0) {
j = increment;
do {
if ((filename[j] >= '0') && (filename[j] <= '9')) {
meshnumber = meshnumber * 10 + (int) (filename[j] - '0');
} else {
increment = 0;
}
j++;
} while (filename[j] != '\0');
}
if (increment > 0) {
filename[increment - 1] = '\0';
}
if (meshnumber == 0) {
start_inc = 0;
loweriteration = 0;
} else {
start_inc = 1;
loweriteration = meshnumber - 1;
}
set_filenames(filename, loweriteration);
}
void free_inc(inc)
int inc;
{
if (loaded[inc][NODE]) {
free(nodeptr[inc]);
}
if (loaded[inc][POLY]) {
if (polynodes[inc] > 0) {
free(polynodeptr[inc]);
}
free(polyedgeptr[inc]);
free(polyholeptr[inc]);
}
if (loaded[inc][ELE]) {
free(eleptr[inc]);
}
if (loaded[inc][PART]) {
free(partpart[inc]);
free(partcenter[inc]);
free(partshift[inc]);
}
if (loaded[inc][EDGE]) {
free(edgeptr[inc]);
free(normptr[inc]);
}
if (loaded[inc][ADJ]) {
free(adjptr[inc]);
}
if (loaded[inc][VORO]) {
free(vnodeptr[inc]);
free(vedgeptr[inc]);
free(vnormptr[inc]);
}
}
void move_inc(inc)
int inc;
{
int i;
free_inc(1 - inc);
for (i = 0; i < IMAGE_TYPES; i++) {
loaded[1 - inc][i] = loaded[inc][i];
loaded[inc][i] = 0;
xlo[1 - inc][i] = xlo[inc][i];
ylo[1 - inc][i] = ylo[inc][i];
xhi[1 - inc][i] = xhi[inc][i];
yhi[1 - inc][i] = yhi[inc][i];
}
nodes[1 - inc] = nodes[inc];
node_dim[1 - inc] = node_dim[inc];
nodeptr[1 - inc] = nodeptr[inc];
polynodes[1 - inc] = polynodes[inc];
poly_dim[1 - inc] = poly_dim[inc];
polyedges[1 - inc] = polyedges[inc];
polyholes[1 - inc] = polyholes[inc];
polynodeptr[1 - inc] = polynodeptr[inc];
polyedgeptr[1 - inc] = polyedgeptr[inc];
polyholeptr[1 - inc] = polyholeptr[inc];
elems[1 - inc] = elems[inc];
ele_corners[1 - inc] = ele_corners[inc];
eleptr[1 - inc] = eleptr[inc];
edges[1 - inc] = edges[inc];
edgeptr[1 - inc] = edgeptr[inc];
normptr[1 - inc] = normptr[inc];
subdomains[1 - inc] = subdomains[inc];
partpart[1 - inc] = partpart[inc];
partcenter[1 - inc] = partcenter[inc];
partshift[1 - inc] = partshift[inc];
adjsubdomains[1 - inc] = adjsubdomains[inc];
adjptr[1 - inc] = adjptr[inc];
vnodes[1 - inc] = vnodes[inc];
vnode_dim[1 - inc] = vnode_dim[inc];
vnodeptr[1 - inc] = vnodeptr[inc];
vedges[1 - inc] = vedges[inc];
vedgeptr[1 - inc] = vedgeptr[inc];
vnormptr[1 - inc] = vnormptr[inc];
firstnumber[1 - inc] = firstnumber[inc];
firstnumber[inc] = -1;
}
void unload_inc(inc)
int inc;
{
int i;
current_image = NOTHING;
for (i = 0; i < IMAGE_TYPES; i++) {
loaded[inc][i] = 0;
firstnumber[inc] = -1;
}
}
void showme_init()
{
current_image = NOTHING;
current_inc = 0;
explosion = STARTEXPLOSION;
unload_inc(0);
unload_inc(1);
}
char *readline(string, infile, infilename)
char *string;
FILE *infile;
char *infilename;
{
char *result;
do {
result = fgets(string, INPUTLINESIZE, infile);
if (result == (char *) NULL) {
printf(" Error: Unexpected end of file in %s.\n",
infilename);
exit(1);
}
while ((*result != '\0') && (*result != '#')
&& (*result != '.') && (*result != '+') && (*result != '-')
&& ((*result < '0') || (*result > '9'))) {
result++;
}
} while ((*result == '#') || (*result == '\0'));
return result;
}
char *findfield(string)
char *string;
{
char *result;
result = string;
while ((*result != '\0') && (*result != '#')
&& (*result != ' ') && (*result != '\t')) {
result++;
}
while ((*result != '\0') && (*result != '#')
&& (*result != '.') && (*result != '+') && (*result != '-')
&& ((*result < '0') || (*result > '9'))) {
result++;
}
if (*result == '#') {
*result = '\0';
}
return result;
}
int load_node(fname, firstnumber, nodes, dim, ptr, xmin, ymin, xmax, ymax)
char *fname;
int *firstnumber;
int *nodes;
int *dim;
REAL **ptr;
REAL *xmin;
REAL *ymin;
REAL *xmax;
REAL *ymax;
{
FILE *infile;
char inputline[INPUTLINESIZE];
char *stringptr;
int extras;
int nodemarks;
int index;
int nodenumber;
int i, j;
int smallerr;
REAL x, y;
*xmin = *ymin = 0.0;
*xmax = *ymax = 1.0;
if (!quiet) {
printf("Opening %s.\n", fname);
}
infile = fopen(fname, "r");
if (infile == (FILE *) NULL) {
printf(" Error: Cannot access file %s.\n", fname);
return 1;
}
stringptr = readline(inputline, infile, fname);
*nodes = (int) strtol (stringptr, &stringptr, 0);
if (*nodes < 3) {
printf(" Error: %s contains %d points.\n", fname, *nodes);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
*dim = 2;
} else {
*dim = (int) strtol (stringptr, &stringptr, 0);
}
if (*dim < 1) {
printf(" Error: %s has dimensionality %d.\n", fname, *dim);
return 1;
}
if (*dim != 2) {
printf(" I only understand two-dimensional meshes.\n");
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
extras = 0;
} else {
extras = (int) strtol (stringptr, &stringptr, 0);
}
if (extras < 0) {
printf(" Error: %s has negative value for number of attributes.\n",
fname);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
nodemarks = 0;
} else {
nodemarks = (int) strtol (stringptr, &stringptr, 0);
}
if (nodemarks < 0) {
printf(" Warning: %s has negative value for number of point markers.\n",
fname);
}
if (nodemarks > 1) {
printf(
" Warning: %s has value greater than one for number of point markers.\n",
fname);
}
*ptr = (REAL *) malloc((*nodes + 1) * *dim * sizeof(REAL));
if (*ptr == (REAL *) NULL) {
printf(" Out of memory.\n");
return 1;
}
index = *dim;
smallerr = 1;
for (i = 0; i < *nodes; i++) {
stringptr = readline(inputline, infile, fname);
nodenumber = (int) strtol (stringptr, &stringptr, 0);
if ((i == 0) && (*firstnumber == -1)) {
if (nodenumber == 0) {
*firstnumber = 0;
} else {
*firstnumber = 1;
}
}
if ((nodenumber != *firstnumber + i) && (smallerr)) {
printf(" Warning: Points in %s are not numbered correctly\n", fname);
printf(" (starting with point %d).\n", *firstnumber + i);
smallerr = 0;
}
for (j = 0; j < *dim; j++) {
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Point %d is missing a coordinate in %s.\n",
*firstnumber + i, fname);
free(*ptr);
return 1;
}
(*ptr)[index++] = (REAL) strtod(stringptr, &stringptr);
}
}
fclose(infile);
index = *dim;
*xmin = *xmax = (*ptr)[index];
*ymin = *ymax = (*ptr)[index + 1];
for (i = 2; i <= *nodes; i++) {
index += *dim;
x = (*ptr)[index];
y = (*ptr)[index + 1];
if (x < *xmin) {
*xmin = x;
}
if (y < *ymin) {
*ymin = y;
}
if (x > *xmax) {
*xmax = x;
}
if (y > *ymax) {
*ymax = y;
}
}
if (*xmin == *xmax) {
*xmin -= 0.5;
*xmax += 0.5;
}
if (*ymin == *ymax) {
*ymin -= 0.5;
*ymax += 0.5;
}
return 0;
}
int load_poly(inc, fname, firstnumber, pnodes, dim, edges, holes, nodeptr,
edgeptr, holeptr, xmin, ymin, xmax, ymax)
int inc;
char *fname;
int *firstnumber;
int *pnodes;
int *dim;
int *edges;
int *holes;
REAL **nodeptr;
int **edgeptr;
REAL **holeptr;
REAL *xmin;
REAL *ymin;
REAL *xmax;
REAL *ymax;
{
FILE *infile;
char inputline[INPUTLINESIZE];
char *stringptr;
int extras;
int nodemarks;
int segmentmarks;
int index;
int nodenumber, edgenumber, holenumber;
int maxnode;
int i, j;
int smallerr;
REAL x, y;
if (!quiet) {
printf("Opening %s.\n", fname);
}
infile = fopen(fname, "r");
if (infile == (FILE *) NULL) {
printf(" Error: Cannot access file %s.\n", fname);
return 1;
}
stringptr = readline(inputline, infile, fname);
*pnodes = (int) strtol (stringptr, &stringptr, 0);
if (*pnodes == 0) {
if (!loaded[inc][NODE]) {
if (load_image(inc, NODE)) {
return 1;
}
}
maxnode = nodes[inc];
*xmin = xlo[inc][NODE];
*ymin = ylo[inc][NODE];
*xmax = xhi[inc][NODE];
*ymax = yhi[inc][NODE];
} else {
if (*pnodes < 1) {
printf(" Error: %s contains %d points.\n", fname, *pnodes);
return 1;
}
maxnode = *pnodes;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
*dim = 2;
} else {
*dim = (int) strtol (stringptr, &stringptr, 0);
}
if (*dim < 1) {
printf(" Error: %s has dimensionality %d.\n", fname, *dim);
return 1;
}
if (*dim != 2) {
printf(" I only understand two-dimensional meshes.\n");
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
extras = 0;
} else {
extras = (int) strtol (stringptr, &stringptr, 0);
}
if (extras < 0) {
printf(" Error: %s has negative value for number of attributes.\n",
fname);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
nodemarks = 0;
} else {
nodemarks = (int) strtol (stringptr, &stringptr, 0);
}
if (nodemarks < 0) {
printf(" Warning: %s has negative value for number of point markers.\n",
fname);
}
if (nodemarks > 1) {
printf(
" Warning: %s has value greater than one for number of point markers.\n",
fname);
}
if (*pnodes > 0) {
*nodeptr = (REAL *) malloc((*pnodes + 1) * *dim * sizeof(REAL));
if (*nodeptr == (REAL *) NULL) {
printf(" Out of memory.\n");
return 1;
}
index = *dim;
smallerr = 1;
for (i = 0; i < *pnodes; i++) {
stringptr = readline(inputline, infile, fname);
nodenumber = (int) strtol (stringptr, &stringptr, 0);
if ((i == 0) && (*firstnumber == -1)) {
if (nodenumber == 0) {
*firstnumber = 0;
} else {
*firstnumber = 1;
}
}
if ((nodenumber != *firstnumber + i) && (smallerr)) {
printf(" Warning: Points in %s are not numbered correctly.\n",
fname);
printf(" (starting with point %d).\n", *firstnumber + i);
smallerr = 0;
}
for (j = 0; j < *dim; j++) {
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Point %d is missing a coordinate in %s.\n",
*firstnumber + i, fname);
free(*nodeptr);
return 1;
}
(*nodeptr)[index++] = (REAL) strtod(stringptr, &stringptr);
}
}
}
stringptr = readline(inputline, infile, fname);
*edges = (int) strtol (stringptr, &stringptr, 0);
if (*edges < 0) {
printf(" Error: %s contains %d segments.\n", fname, *edges);
free(*nodeptr);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
segmentmarks = 0;
} else {
segmentmarks = (int) strtol (stringptr, &stringptr, 0);
}
if (segmentmarks < 0) {
printf(" Error: %s has negative value for number of segment markers.\n",
fname);
free(*nodeptr);
return 1;
}
if (segmentmarks > 1) {
printf(
" Error: %s has value greater than one for number of segment markers.\n",
fname);
free(*nodeptr);
return 1;
}
*edgeptr = (int *) malloc(((*edges + 1) << 1) * sizeof(int));
if (*edgeptr == (int *) NULL) {
printf(" Out of memory.\n");
free(*nodeptr);
return 1;
}
index = 2;
smallerr = 1;
for (i = *firstnumber; i < *firstnumber + *edges; i++) {
stringptr = readline(inputline, infile, fname);
edgenumber = (int) strtol (stringptr, &stringptr, 0);
if ((edgenumber != i) && (smallerr)) {
printf(" Warning: Segments in %s are not numbered correctly.\n",
fname);
printf(" (starting with segment %d).\n", i);
smallerr = 0;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Segment %d is missing its endpoints in %s.\n", i, fname);
free(*nodeptr);
free(*edgeptr);
return 1;
}
(*edgeptr)[index] = (int) strtol (stringptr, &stringptr, 0) + 1 -
*firstnumber;
if (((*edgeptr)[index] < 1) || ((*edgeptr)[index] > maxnode)) {
printf("Error: Segment %d has invalid endpoint in %s.\n", i, fname);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Segment %d is missing an endpoint in %s.\n", i, fname);
free(*nodeptr);
free(*edgeptr);
return 1;
}
(*edgeptr)[index + 1] = (int) strtol (stringptr, &stringptr, 0) + 1 -
*firstnumber;
if (((*edgeptr)[index + 1] < 1) || ((*edgeptr)[index + 1] > maxnode)) {
printf("Error: Segment %d has invalid endpoint in %s.\n", i, fname);
return 1;
}
index += 2;
}
stringptr = readline(inputline, infile, fname);
*holes = (int) strtol (stringptr, &stringptr, 0);
if (*holes < 0) {
printf(" Error: %s contains %d holes.\n", fname, *holes);
free(*nodeptr);
free(*edgeptr);
return 1;
}
*holeptr = (REAL *) malloc((*holes + 1) * *dim * sizeof(REAL));
if (*holeptr == (REAL *) NULL) {
printf(" Out of memory.\n");
free(*nodeptr);
free(*edgeptr);
return 1;
}
index = *dim;
smallerr = 1;
for (i = *firstnumber; i < *firstnumber + *holes; i++) {
stringptr = readline(inputline, infile, fname);
holenumber = (int) strtol (stringptr, &stringptr, 0);
if ((holenumber != i) && (smallerr)) {
printf(" Warning: Holes in %s are not numbered correctly.\n", fname);
printf(" (starting with hole %d).\n", i);
smallerr = 0;
}
for (j = 0; j < *dim; j++) {
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Hole %d is missing a coordinate in %s.\n", i,
fname);
free(*nodeptr);
free(*edgeptr);
free(*holeptr);
return 1;
}
(*holeptr)[index++] = (REAL) strtod(stringptr, &stringptr);
}
}
fclose(infile);
if (*pnodes > 0) {
index = *dim;
*xmin = *xmax = (*nodeptr)[index];
*ymin = *ymax = (*nodeptr)[index + 1];
for (i = 2; i <= *pnodes; i++) {
index += *dim;
x = (*nodeptr)[index];
y = (*nodeptr)[index + 1];
if (x < *xmin) {
*xmin = x;
}
if (y < *ymin) {
*ymin = y;
}
if (x > *xmax) {
*xmax = x;
}
if (y > *ymax) {
*ymax = y;
}
}
}
index = *dim;
for (i = 1; i <= *holes; i++) {
x = (*holeptr)[index];
y = (*holeptr)[index + 1];
if (x < *xmin) {
*xmin = x;
}
if (y < *ymin) {
*ymin = y;
}
if (x > *xmax) {
*xmax = x;
}
if (y > *ymax) {
*ymax = y;
}
index += *dim;
}
return 0;
}
int load_ele(fname, firstnumber, nodes, elems, corners, ptr)
char *fname;
int firstnumber;
int nodes;
int *elems;
int *corners;
int **ptr;
{
FILE *infile;
char inputline[INPUTLINESIZE];
char *stringptr;
int extras;
int index;
int elemnumber;
int i, j;
int smallerr;
if (!quiet) {
printf("Opening %s.\n", fname);
}
infile = fopen(fname, "r");
if (infile == (FILE *) NULL) {
printf(" Error: Cannot access file %s.\n", fname);
return 1;
}
stringptr = readline(inputline, infile, fname);
*elems = (int) strtol (stringptr, &stringptr, 0);
if (*elems < 1) {
printf(" Error: %s contains %d triangles.\n", fname, *elems);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
*corners = 3;
} else {
*corners = (int) strtol (stringptr, &stringptr, 0);
}
if (*corners < 3) {
printf(" Error: Triangles in %s have only %d corners.\n", fname,
*corners);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
extras = 0;
} else {
extras = (int) strtol (stringptr, &stringptr, 0);
}
if (extras < 0) {
printf(" Error: %s has negative value for extra fields.\n", fname);
return 1;
}
*ptr = (int *) malloc((*elems + 1) * 3 * sizeof(int));
if (*ptr == (int *) NULL) {
printf(" Out of memory.\n");
return 1;
}
index = 3;
smallerr = 1;
for (i = firstnumber; i < firstnumber + *elems; i++) {
stringptr = readline(inputline, infile, fname);
elemnumber = (int) strtol (stringptr, &stringptr, 0);
if ((elemnumber != i) && (smallerr)) {
printf(" Warning: Triangles in %s are not numbered correctly.\n",
fname);
printf(" (starting with triangle %d).\n", i);
smallerr = 0;
}
for (j = 0; j < 3; j++) {
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Triangle %d is missing a corner in %s.\n", i, fname);
free(*ptr);
return 1;
}
(*ptr)[index] = (int) strtol (stringptr, &stringptr, 0) + 1 -
firstnumber;
if (((*ptr)[index] < 1) || ((*ptr)[index] > nodes)) {
printf("Error: Triangle %d has invalid corner in %s.\n", i, fname);
return 1;
}
index++;
}
}
fclose(infile);
return 0;
}
int load_edge(fname, firstnumber, nodes, edges, edgeptr, normptr)
char *fname;
int firstnumber;
int nodes;
int *edges;
int **edgeptr;
REAL **normptr;
{
FILE *infile;
char inputline[INPUTLINESIZE];
char *stringptr;
int index;
int edgenumber;
int edgemarks;
int i;
int smallerr;
if (!quiet) {
printf("Opening %s.\n", fname);
}
infile = fopen(fname, "r");
if (infile == (FILE *) NULL) {
printf(" Error: Cannot access file %s.\n", fname);
return 1;
}
stringptr = readline(inputline, infile, fname);
*edges = (int) strtol (stringptr, &stringptr, 0);
if (*edges < 1) {
printf(" Error: %s contains %d edges.\n", fname, *edges);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
edgemarks = 0;
} else {
edgemarks = (int) strtol (stringptr, &stringptr, 0);
}
if (edgemarks < 0) {
printf(" Error: %s has negative value for number of edge markers.\n",
fname);
return 1;
}
if (edgemarks > 1) {
printf(
" Error: %s has value greater than one for number of edge markers.\n",
fname);
return 1;
}
*edgeptr = (int *) malloc(((*edges + 1) << 1) * sizeof(int));
if (*edgeptr == (int *) NULL) {
printf(" Out of memory.\n");
return 1;
}
*normptr = (REAL *) malloc(((*edges + 1) << 1) * sizeof(REAL));
if (*normptr == (REAL *) NULL) {
printf(" Out of memory.\n");
free(*edgeptr);
return 1;
}
index = 2;
smallerr = 1;
for (i = firstnumber; i < firstnumber + *edges; i++) {
stringptr = readline(inputline, infile, fname);
edgenumber = (int) strtol (stringptr, &stringptr, 0);
if ((edgenumber != i) && (smallerr)) {
printf(" Warning: Edges in %s are not numbered correctly.\n", fname);
printf(" (starting with edge %d).\n", i);
smallerr = 0;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Edge %d is missing its endpoints in %s.\n", i, fname);
free(*edgeptr);
free(*normptr);
return 1;
}
(*edgeptr)[index] = (int) strtol (stringptr, &stringptr, 0) + 1 -
firstnumber;
if (((*edgeptr)[index] < 1) || ((*edgeptr)[index] > nodes)) {
printf("Error: Edge %d has invalid endpoint in %s.\n", i, fname);
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Edge %d is missing an endpoint in %s.\n", i, fname);
free(*edgeptr);
free(*normptr);
return 1;
}
(*edgeptr)[index + 1] = (int) strtol (stringptr, &stringptr, 0);
if ((*edgeptr)[index + 1] == -1) {
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Edge %d is missing its direction in %s.\n", i, fname);
free(*edgeptr);
free(*normptr);
return 1;
}
(*normptr)[index] = (REAL) strtod(stringptr, &stringptr);
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Edge %d is missing a direction coordinate in %s.\n",
i, fname);
free(*edgeptr);
free(*normptr);
return 1;
}
(*normptr)[index + 1] = (REAL) strtod(stringptr, &stringptr);
} else {
(*edgeptr)[index + 1] += 1 - firstnumber;
if (((*edgeptr)[index + 1] < 1) || ((*edgeptr)[index + 1] > nodes)) {
printf("Error: Edge %d has invalid endpoint in %s.\n", i, fname);
return 1;
}
}
index += 2;
}
fclose(infile);
return 0;
}
int load_part(fname, dim, firstnumber, elems, nodeptr, eleptr, parts,
partition, partcenter, partshift)
char *fname;
int dim;
int firstnumber;
int elems;
REAL *nodeptr;
int *eleptr;
int *parts;
int **partition;
REAL **partcenter;
REAL **partshift;
{
FILE *infile;
char inputline[INPUTLINESIZE];
char *stringptr;
int partelems;
int index;
int elemnumber;
int i, j;
int smallerr;
int *partsize;
if (!quiet) {
printf("Opening %s.\n", fname);
}
infile = fopen(fname, "r");
if (infile == (FILE *) NULL) {
printf(" Error: Cannot access file %s.\n", fname);
return 1;
}
stringptr = readline(inputline, infile, fname);
partelems = (int) strtol (stringptr, &stringptr, 0);
if (partelems != elems) {
printf(
" Error: .ele and .part files do not agree on number of triangles.\n");
return 1;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
*parts = 1;
} else {
*parts = (int) strtol (stringptr, &stringptr, 0);
}
if (*parts < 1) {
printf(" Error: %s specifies %d subdomains.\n", fname, *parts);
return 1;
}
*partition = (int *) malloc((elems + 1) * sizeof(int));
if (*partition == (int *) NULL) {
printf(" Out of memory.\n");
return 1;
}
smallerr = 1;
for (i = firstnumber; i < firstnumber + partelems; i++) {
stringptr = readline(inputline, infile, fname);
elemnumber = (int) strtol (stringptr, &stringptr, 0);
if ((elemnumber != i) && (smallerr)) {
printf(" Warning: Triangles in %s are not numbered correctly.\n",
fname);
printf(" (starting with triangle %d).\n", i);
smallerr = 0;
}
stringptr = findfield(stringptr);
if (*stringptr == '\0') {
printf("Error: Triangle %d has no subdomain in %s.\n", i, fname);
free(*partition);
return 1;
}
(*partition)[i] = (int) strtol (stringptr, &stringptr, 0) - firstnumber;
if (((*partition)[i] >= *parts) || ((*partition)[i] < 0)) {
printf(" Error: Triangle %d of %s has an invalid subdomain.\n",
i, fname);
free(*partition);
return 1;
}
}
fclose(infile);
*partcenter = (REAL *) malloc(((*parts + 1) << 1) * sizeof(REAL));
if (*partcenter == (REAL *) NULL) {
printf("Error: Out of memory.\n");
free(*partition);
return 1;
}
*partshift = (REAL *) malloc((*parts << 1) * sizeof(REAL));
if (*partshift == (REAL *) NULL) {
printf("Error: Out of memory.\n");
free(*partition);
free(*partcenter);
return 1;
}
partsize = (int *) malloc((*parts + 1) * sizeof(int));
if (partsize == (int *) NULL) {
printf("Error: Out of memory.\n");
free(*partition);
free(*partcenter);
free(*partshift);
return 1;
}
index = 3;
for (i = 0; i <= *parts; i++) {
partsize[i] = 0;
(*partcenter)[i << 1] = 0.0;
(*partcenter)[(i << 1) + 1] = 0.0;
}
for (i = 1; i <= elems; i++) {
partsize[(*partition)[i]] += 3;
for (j = 0; j < 3; j++) {
(*partcenter)[(*partition)[i] << 1] +=
nodeptr[eleptr[index] * dim];
(*partcenter)[((*partition)[i] << 1) + 1] +=
nodeptr[eleptr[index++] * dim + 1];
}
}
for (i = 0; i < *parts; i++) {
(*partcenter)[i << 1] /= (REAL) partsize[i];
(*partcenter)[(i << 1) + 1] /= (REAL) partsize[i];
(*partcenter)[*parts << 1] += (*partcenter)[i << 1];
(*partcenter)[(*parts << 1) + 1] += (*partcenter)[(i << 1) + 1];
}
(*partcenter)[*parts << 1] /= (REAL) *parts;
(*partcenter)[(*parts << 1) + 1] /= (REAL) *parts;
free(partsize);
return 0;
}
int load_adj(fname, subdomains, ptr)
char *fname;
int *subdomains;
int **ptr;
{
FILE *infile;
char inputline[INPUTLINESIZE];
char *stringptr;
int i, j;
if (!quiet) {
printf("Opening %s.\n", fname);
}
infile = fopen(fname, "r");
if (infile == (FILE *) NULL) {
printf(" Error: Cannot access file %s.\n", fname);
return 1;
}
stringptr = readline(inputline, infile, fname);
*subdomains = (int) strtol (stringptr, &stringptr, 0);
if (*subdomains < 1) {
printf(" Error: %s contains %d subdomains.\n", fname, *subdomains);
return 1;
}
*ptr = (int *) malloc(*subdomains * *subdomains * sizeof(int));
if (*ptr == (int *) NULL) {
printf(" Out of memory.\n");
return 1;
}
for (i = 0; i < *subdomains; i++) {
for (j = 0; j < *subdomains; j++) {
stringptr = readline(inputline, infile, fname);
(*ptr)[i * *subdomains + j] = (int) strtol (stringptr, &stringptr, 0);
}
}
return 0;
}
void findpartshift(parts, explosion, partcenter, partshift)
int parts;
REAL explosion;
REAL *partcenter;
REAL *partshift;
{
int i;
for (i = 0; i < parts; i++) {
partshift[i << 1] = explosion *
(partcenter[i << 1] - partcenter[parts << 1]);
partshift[(i << 1) + 1] = explosion *
(partcenter[(i << 1) + 1] - partcenter[(parts << 1) + 1]);
}
}
int load_image(inc, image)
int inc;
int image;
{
int error;
switch (image) {
case NODE:
error = load_node(nodefilename[inc], &firstnumber[inc], &nodes[inc],
&node_dim[inc], &nodeptr[inc], &xlo[inc][NODE],
&ylo[inc][NODE], &xhi[inc][NODE], &yhi[inc][NODE]);
break;
case POLY:
error = load_poly(inc, polyfilename[inc], &firstnumber[inc],
&polynodes[inc], &poly_dim[inc], &polyedges[inc],
&polyholes[inc], &polynodeptr[inc], &polyedgeptr[inc],
&polyholeptr[inc],
&xlo[inc][POLY], &ylo[inc][POLY],
&xhi[inc][POLY], &yhi[inc][POLY]);
break;
case ELE:
error = load_ele(elefilename[inc], firstnumber[inc], nodes[inc],
&elems[inc], &ele_corners[inc], &eleptr[inc]);
xlo[inc][ELE] = xlo[inc][NODE];
ylo[inc][ELE] = ylo[inc][NODE];
xhi[inc][ELE] = xhi[inc][NODE];
yhi[inc][ELE] = yhi[inc][NODE];
break;
case EDGE:
error = load_edge(edgefilename[inc], firstnumber[inc], nodes[inc],
&edges[inc], &edgeptr[inc], &normptr[inc]);
xlo[inc][EDGE] = xlo[inc][NODE];
ylo[inc][EDGE] = ylo[inc][NODE];
xhi[inc][EDGE] = xhi[inc][NODE];
yhi[inc][EDGE] = yhi[inc][NODE];
break;
case PART:
error = load_part(partfilename[inc], node_dim[inc], firstnumber[inc],
elems[inc], nodeptr[inc], eleptr[inc],
&subdomains[inc], &partpart[inc], &partcenter[inc],
&partshift[inc]);
if (!error) {
findpartshift(subdomains[inc], explosion, partcenter[inc],
partshift[inc]);
}
xlo[inc][PART] = xlo[inc][NODE];
ylo[inc][PART] = ylo[inc][NODE];
xhi[inc][PART] = xhi[inc][NODE];
yhi[inc][PART] = yhi[inc][NODE];
break;
case ADJ:
error = load_adj(adjfilename[inc], &adjsubdomains[inc], &adjptr[inc]);
xlo[inc][ADJ] = xlo[inc][NODE];
ylo[inc][ADJ] = ylo[inc][NODE];
xhi[inc][ADJ] = xhi[inc][NODE];
yhi[inc][ADJ] = yhi[inc][NODE];
break;
case VORO:
error = load_node(vnodefilename[inc], &firstnumber[inc], &vnodes[inc],
&vnode_dim[inc], &vnodeptr[inc], &xlo[inc][VORO],
&ylo[inc][VORO], &xhi[inc][VORO], &yhi[inc][VORO]);
if (!error) {
error = load_edge(vedgefilename[inc], firstnumber[inc], vnodes[inc],
&vedges[inc], &vedgeptr[inc], &vnormptr[inc]);
}
break;
default:
error = 1;
}
if (!error) {
loaded[inc][image] = 1;
}
return error;
}
void choose_image(inc, image)
int inc;
int image;
{
if (!loaded[inc][image]) {
if ((image == ELE) || (image == EDGE) || (image == PART)
|| (image == ADJ)) {
if (!loaded[inc][NODE]) {
if (load_image(inc, NODE)) {
return;
}
}
}
if ((image == PART) || (image == ADJ)) {
if (!loaded[inc][ELE]) {
if (load_image(inc, ELE)) {
return;
}
}
}
if (image == ADJ) {
if (!loaded[inc][PART]) {
if (load_image(inc, PART)) {
return;
}
}
}
if (load_image(inc, image)) {
return;
}
}
current_inc = inc;
current_image = image;
}
Window make_button(name, x, y, width)
char *name;
int x;
int y;
int width;
{
XSetWindowAttributes attr;
XSizeHints hints;
Window button;
attr.background_pixel = black;
attr.border_pixel = white;
attr.backing_store = NotUseful;
attr.event_mask = ExposureMask | ButtonReleaseMask | ButtonPressMask;
attr.bit_gravity = SouthWestGravity;
attr.win_gravity = SouthWestGravity;
attr.save_under = False;
button = XCreateWindow(display, mainwindow, x, y, width, BUTTONHEIGHT - 4,
2, 0, InputOutput, CopyFromParent,
CWBackPixel | CWBorderPixel | CWEventMask |
CWBitGravity | CWWinGravity | CWBackingStore |
CWSaveUnder, &attr);
hints.width = width;
hints.height = BUTTONHEIGHT - 4;
hints.min_width = 0;
hints.min_height = BUTTONHEIGHT - 4;
hints.max_width = width;
hints.max_height = BUTTONHEIGHT - 4;
hints.width_inc = 1;
hints.height_inc = 1;
hints.flags = PMinSize | PMaxSize | PSize | PResizeInc;
XSetStandardProperties(display, button, name, "showme", None, (char **) NULL,
0, &hints);
return button;
}
void make_buttons(y)
int y;
{
int i;
for (i = 1; i >= 0; i--) {
nodewin[i] = make_button("node", 0, y + (1 - i) * BUTTONHEIGHT, 42);
XMapWindow(display, nodewin[i]);
polywin[i] = make_button("poly", 44, y + (1 - i) * BUTTONHEIGHT, 42);
XMapWindow(display, polywin[i]);
elewin[i] = make_button("ele", 88, y + (1 - i) * BUTTONHEIGHT, 33);
XMapWindow(display, elewin[i]);
edgewin[i] = make_button("edge", 123, y + (1 - i) * BUTTONHEIGHT, 42);
XMapWindow(display, edgewin[i]);
partwin[i] = make_button("part", 167, y + (1 - i) * BUTTONHEIGHT, 42);
XMapWindow(display, partwin[i]);
adjwin[i] = make_button("adj", 211, y + (1 - i) * BUTTONHEIGHT, 33);
XMapWindow(display, adjwin[i]);
voronoiwin[i] = make_button("voro", 246, y + (1 - i) * BUTTONHEIGHT, 42);
XMapWindow(display, voronoiwin[i]);
}
versionpluswin = make_button(" +", 290, y, 52);
XMapWindow(display, versionpluswin);
versionminuswin = make_button(" -", 290, y + BUTTONHEIGHT, 52);
XMapWindow(display, versionminuswin);
quitwin = make_button("Quit", 0, y + 2 * BUTTONHEIGHT, 42);
XMapWindow(display, quitwin);
leftwin = make_button("<", 44, y + 2 * BUTTONHEIGHT, 14);
XMapWindow(display, leftwin);
rightwin = make_button(">", 60, y + 2 * BUTTONHEIGHT, 14);
XMapWindow(display, rightwin);
upwin = make_button("^", 76, y + 2 * BUTTONHEIGHT, 14);
XMapWindow(display, upwin);
downwin = make_button("v", 92, y + 2 * BUTTONHEIGHT, 14);
XMapWindow(display, downwin);
resetwin = make_button("Reset", 108, y + 2 * BUTTONHEIGHT, 52);
XMapWindow(display, resetwin);
widthpluswin = make_button("Width+", 162, y + 2 * BUTTONHEIGHT, 61);
XMapWindow(display, widthpluswin);
widthminuswin = make_button("-", 225, y + 2 * BUTTONHEIGHT, 14);
XMapWindow(display, widthminuswin);
expwin = make_button("Exp", 241, y + 2 * BUTTONHEIGHT, 33);
XMapWindow(display, expwin);
exppluswin = make_button("+", 276, y + 2 * BUTTONHEIGHT, 14);
XMapWindow(display, exppluswin);
expminuswin = make_button("-", 292, y + 2 * BUTTONHEIGHT, 14);
XMapWindow(display, expminuswin);
fillwin = make_button("Fill", 308, y + 2 * BUTTONHEIGHT, 41);
XMapWindow(display, fillwin);
pswin = make_button("PS", 351, y + 2 * BUTTONHEIGHT, 24);
XMapWindow(display, pswin);
epswin = make_button("EPS", 377, y + 2 * BUTTONHEIGHT, 33);
XMapWindow(display, epswin);
}
void fill_button(button)
Window button;
{
int x, y;
unsigned int w, h, d, b;
Window rootw;
XGetGeometry(display, button, &rootw, &x, &y, &w, &h, &d, &b);
XFillRectangle(display, button, fontgc, 0, 0, w, h);
}
void draw_buttons()
{
char numberstring[32];
char buttonstring[6];
int i;
for (i = 1; i >= 0; i--) {
if ((current_image == NODE) && (current_inc == i)) {
fill_button(nodewin[i]);
XDrawString(display, nodewin[i], blackfontgc, 2, 13, "node", 4);
} else {
XClearWindow(display, nodewin[i]);
XDrawString(display, nodewin[i], fontgc, 2, 13, "node", 4);
}
if ((current_image == POLY) && (current_inc == i)) {
fill_button(polywin[i]);
XDrawString(display, polywin[i], blackfontgc, 2, 13, "poly", 4);
} else {
XClearWindow(display, polywin[i]);
XDrawString(display, polywin[i], fontgc, 2, 13, "poly", 4);
}
if ((current_image == ELE) && (current_inc == i)) {
fill_button(elewin[i]);
XDrawString(display, elewin[i], blackfontgc, 2, 13, "ele", 3);
} else {
XClearWindow(display, elewin[i]);
XDrawString(display, elewin[i], fontgc, 2, 13, "ele", 3);
}
if ((current_image == EDGE) && (current_inc == i)) {
fill_button(edgewin[i]);
XDrawString(display, edgewin[i], blackfontgc, 2, 13, "edge", 4);
} else {
XClearWindow(display, edgewin[i]);
XDrawString(display, edgewin[i], fontgc, 2, 13, "edge", 4);
}
if ((current_image == PART) && (current_inc == i)) {
fill_button(partwin[i]);
XDrawString(display, partwin[i], blackfontgc, 2, 13, "part", 4);
} else {
XClearWindow(display, partwin[i]);
XDrawString(display, partwin[i], fontgc, 2, 13, "part", 4);
}
if ((current_image == ADJ) && (current_inc == i)) {
fill_button(adjwin[i]);
XDrawString(display, adjwin[i], blackfontgc, 2, 13, "adj", 3);
} else {
XClearWindow(display, adjwin[i]);
XDrawString(display, adjwin[i], fontgc, 2, 13, "adj", 3);
}
if ((current_image == VORO) && (current_inc == i)) {
fill_button(voronoiwin[i]);
XDrawString(display, voronoiwin[i], blackfontgc, 2, 13, "voro", 4);
} else {
XClearWindow(display, voronoiwin[i]);
XDrawString(display, voronoiwin[i], fontgc, 2, 13, "voro", 4);
}
}
XClearWindow(display, versionpluswin);
sprintf(numberstring, "%d", loweriteration + 1);
sprintf(buttonstring, "%-4.4s+", numberstring);
XDrawString(display, versionpluswin, fontgc, 2, 13, buttonstring, 5);
XClearWindow(display, versionminuswin);
sprintf(numberstring, "%d", loweriteration);
if (loweriteration == 0) {
sprintf(buttonstring, "%-4.4s", numberstring);
} else {
sprintf(buttonstring, "%-4.4s-", numberstring);
}
XDrawString(display, versionminuswin, fontgc, 2, 13, buttonstring, 5);
XClearWindow(display, quitwin);
XDrawString(display, quitwin, fontgc, 2, 13, "Quit", 4);
XClearWindow(display, leftwin);
XDrawString(display, leftwin, fontgc, 2, 13, "<", 1);
XClearWindow(display, rightwin);
XDrawString(display, rightwin, fontgc, 2, 13, ">", 1);
XClearWindow(display, upwin);
XDrawString(display, upwin, fontgc, 2, 13, "^", 1);
XClearWindow(display, downwin);
XDrawString(display, downwin, fontgc, 2, 13, "v", 1);
XClearWindow(display, resetwin);
XDrawString(display, resetwin, fontgc, 2, 13, "Reset", 6);
XClearWindow(display, widthpluswin);
if (line_width < 100) {
XDrawString(display, widthpluswin, fontgc, 2, 13, "Width+", 6);
} else {
XDrawString(display, widthpluswin, fontgc, 2, 13, "Width ", 6);
}
XClearWindow(display, widthminuswin);
if (line_width > 1) {
XDrawString(display, widthminuswin, fontgc, 2, 13, "-", 1);
}
XClearWindow(display, expwin);
XClearWindow(display, exppluswin);
XClearWindow(display, expminuswin);
XClearWindow(display, fillwin);
if (current_image == PART) {
if (explode) {
fill_button(expwin);
XDrawString(display, expwin, blackfontgc, 2, 13, "Exp", 3);
} else {
XDrawString(display, expwin, fontgc, 2, 13, "Exp", 3);
}
XDrawString(display, exppluswin, fontgc, 2, 13, "+", 1);
XDrawString(display, expminuswin, fontgc, 2, 13, "-", 1);
if (fillelem) {
fill_button(fillwin);
XDrawString(display, fillwin, blackfontgc, 2, 13, "Fill", 4);
} else {
XDrawString(display, fillwin, fontgc, 2, 13, "Fill", 4);
}
}
XClearWindow(display, pswin);
XDrawString(display, pswin, fontgc, 2, 13, "PS", 2);
XClearWindow(display, epswin);
XDrawString(display, epswin, fontgc, 2, 13, "EPS", 3);
}
void showme_window(argc, argv)
int argc;
char **argv;
{
XSetWindowAttributes attr;
XSizeHints hints;
XGCValues fontvalues, linevalues;
XColor alloc_color, exact_color;
int i;
display = XOpenDisplay((char *) NULL);
if (!display) {
printf("Error: Cannot open display.\n");
exit(1);
}
screen = DefaultScreen(display);
rootwindow = DefaultRootWindow(display);
black = BlackPixel(display, screen);
white = WhitePixel(display, screen);
windowdepth = DefaultDepth(display, screen);
rootmap = DefaultColormap(display, screen);
width = STARTWIDTH;
height = STARTHEIGHT;
attr.background_pixel = black;
attr.border_pixel = white;
attr.backing_store = NotUseful;
attr.event_mask = ExposureMask | ButtonReleaseMask | ButtonPressMask |
StructureNotifyMask;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = False;
mainwindow = XCreateWindow(display, rootwindow, 0, 0, width,
height + PANELHEIGHT, 3, 0,
InputOutput, CopyFromParent,
CWBackPixel | CWBorderPixel | CWEventMask |
CWBitGravity | CWWinGravity | CWBackingStore |
CWSaveUnder, &attr);
hints.width = width;
hints.height = height + PANELHEIGHT;
hints.min_width = MINWIDTH;
hints.min_height = MINHEIGHT + PANELHEIGHT;
hints.width_inc = 1;
hints.height_inc = 1;
hints.flags = PMinSize | PSize | PResizeInc;
XSetStandardProperties(display, mainwindow, "Show Me", "showme", None,
argv, argc, &hints);
XChangeProperty(display, mainwindow, XA_WM_CLASS, XA_STRING, 8,
PropModeReplace, "showme\0Archimedes", 18);
XClearWindow(display, mainwindow);
XMapWindow(display, mainwindow);
if ((windowdepth > 1) &&
XAllocNamedColor(display, rootmap, "yellow", &alloc_color,
&exact_color)) {
color = 1;
explode = bw_ps;
fontvalues.foreground = alloc_color.pixel;
linevalues.foreground = alloc_color.pixel;
showme_foreground = alloc_color.pixel;
for (i = 0; i < 64; i++) {
if (XAllocNamedColor(display, rootmap, colorname[i], &alloc_color,
&rgb[i])) {
colors[i] = alloc_color.pixel;
} else {
colors[i] = white;
rgb[i].red = alloc_color.red;
rgb[i].green = alloc_color.green;
rgb[i].blue = alloc_color.blue;
if (!quiet) {
printf("Warning: I could not allocate %s.\n", colorname[i]);
}
}
}
} else {
color = 0;
fillelem = 0;
explode = 1;
fontvalues.foreground = white;
linevalues.foreground = white;
showme_foreground = white;
}
font = XLoadQueryFont(display, "9x15");
fontvalues.background = black;
fontvalues.font = font->fid;
fontvalues.fill_style = FillSolid;
fontvalues.line_width = 2;
fontgc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
GCFont | GCLineWidth | GCFillStyle, &fontvalues);
fontvalues.foreground = black;
blackfontgc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
GCFont | GCLineWidth | GCFillStyle, &fontvalues);
linevalues.background = black;
linevalues.line_width = line_width;
linevalues.cap_style = CapRound;
linevalues.join_style = JoinRound;
linevalues.fill_style = FillSolid;
linegc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
GCLineWidth | GCCapStyle | GCJoinStyle | GCFillStyle,
&linevalues);
trianglegc = XCreateGC(display, rootwindow, GCForeground | GCBackground |
GCLineWidth | GCCapStyle | GCJoinStyle | GCFillStyle,
&linevalues);
make_buttons(height);
XFlush(display);
}
void draw_node(nodes, dim, ptr, xscale, yscale, xoffset, yoffset)
int nodes;
int dim;
REAL *ptr;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
{
int i;
int index;
index = dim;
for (i = 1; i <= nodes; i++) {
XFillRectangle(display, mainwindow, linegc,
(int) (ptr[index] * xscale + xoffset) - (line_width >> 1),
(int) (ptr[index + 1] * yscale + yoffset) -
(line_width >> 1), line_width, line_width);
index += dim;
}
}
void draw_poly(nodes, dim, edges, holes, nodeptr, edgeptr, holeptr,
xscale, yscale, xoffset, yoffset)
int nodes;
int dim;
int edges;
int holes;
REAL *nodeptr;
int *edgeptr;
REAL *holeptr;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
{
int i;
int index;
REAL *point1, *point2;
int x1, y1, x2, y2;
index = dim;
for (i = 1; i <= nodes; i++) {
XFillRectangle(display, mainwindow, linegc,
(int) (nodeptr[index] * xscale + xoffset) -
(line_width >> 1),
(int) (nodeptr[index + 1] * yscale + yoffset) -
(line_width >> 1), line_width, line_width);
index += dim;
}
index = 2;
for (i = 1; i <= edges; i++) {
point1 = &nodeptr[edgeptr[index++] * dim];
point2 = &nodeptr[edgeptr[index++] * dim];
XDrawLine(display, mainwindow, linegc,
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset),
(int) (point2[0] * xscale + xoffset),
(int) (point2[1] * yscale + yoffset));
}
index = dim;
if (color) {
XSetForeground(display, linegc, colors[0]);
}
for (i = 1; i <= holes; i++) {
x1 = (int) (holeptr[index] * xscale + xoffset) - 3;
y1 = (int) (holeptr[index + 1] * yscale + yoffset) - 3;
x2 = x1 + 6;
y2 = y1 + 6;
XDrawLine(display, mainwindow, linegc, x1, y1, x2, y2);
XDrawLine(display, mainwindow, linegc, x1, y2, x2, y1);
index += dim;
}
XSetForeground(display, linegc, showme_foreground);
}
void draw_ele(inc, elems, corners, ptr, partition, shift,
xscale, yscale, xoffset, yoffset)
int inc;
int elems;
int corners;
int *ptr;
int *partition;
REAL *shift;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
{
int i, j;
int index;
REAL shiftx, shifty;
REAL *prevpoint, *nowpoint;
XPoint *vertices;
if (color && fillelem && (partition != (int *) NULL)) {
vertices = (XPoint *) malloc(3 * sizeof(XPoint));
if (vertices == (XPoint *) NULL) {
printf("Error: Out of memory.\n");
exit(1);
}
}
index = 3;
for (i = 1; i <= elems; i++) {
if ((partition != (int *) NULL) && explode) {
shiftx = shift[partition[i] << 1];
shifty = shift[(partition[i] << 1) + 1];
}
if (color && (partition != (int *) NULL)) {
if (fillelem) {
XSetForeground(display, trianglegc, colors[partition[i] & 63]);
} else {
XSetForeground(display, linegc, colors[partition[i] & 63]);
}
}
if (color && fillelem && (partition != (int *) NULL)) {
if ((partition != (int *) NULL) && explode) {
for (j = 0; j < 3; j++) {
nowpoint = &nodeptr[inc][ptr[index + j] * node_dim[inc]];
vertices[j].x = (nowpoint[0] + shiftx) * xscale + xoffset;
vertices[j].y = (nowpoint[1] + shifty) * yscale + yoffset;
}
} else {
for (j = 0; j < 3; j++) {
nowpoint = &nodeptr[inc][ptr[index + j] * node_dim[inc]];
vertices[j].x = nowpoint[0] * xscale + xoffset;
vertices[j].y = nowpoint[1] * yscale + yoffset;
}
}
XFillPolygon(display, mainwindow, trianglegc, vertices, 3,
Convex, CoordModeOrigin);
}
prevpoint = &nodeptr[inc][ptr[index + 2] * node_dim[inc]];
if ((partition != (int *) NULL) && explode) {
for (j = 0; j < 3; j++) {
nowpoint = &nodeptr[inc][ptr[index++] * node_dim[inc]];
XDrawLine(display, mainwindow, linegc,
(int) ((prevpoint[0] + shiftx) * xscale + xoffset),
(int) ((prevpoint[1] + shifty) * yscale + yoffset),
(int) ((nowpoint[0] + shiftx) * xscale + xoffset),
(int) ((nowpoint[1] + shifty) * yscale + yoffset));
prevpoint = nowpoint;
}
} else {
for (j = 0; j < 3; j++) {
nowpoint = &nodeptr[inc][ptr[index++] * node_dim[inc]];
XDrawLine(display, mainwindow, linegc,
(int) (prevpoint[0] * xscale + xoffset),
(int) (prevpoint[1] * yscale + yoffset),
(int) (nowpoint[0] * xscale + xoffset),
(int) (nowpoint[1] * yscale + yoffset));
prevpoint = nowpoint;
}
}
}
if (color && fillelem && (partition != (int *) NULL)) {
free(vertices);
}
XSetForeground(display, linegc, showme_foreground);
}
void draw_edge(nodes, dim, edges, nodeptr, edgeptr, normptr,
xscale, yscale, xoffset, yoffset)
int nodes;
int dim;
int edges;
REAL *nodeptr;
int *edgeptr;
REAL *normptr;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
{
int i;
int index;
REAL *point1, *point2;
REAL normx, normy;
REAL normmult, normmultx, normmulty;
REAL windowxmin, windowymin, windowxmax, windowymax;
index = 2;
for (i = 1; i <= edges; i++) {
point1 = &nodeptr[edgeptr[index++] * dim];
if (edgeptr[index] == -1) {
normx = normptr[index - 1];
normy = normptr[index++];
normmultx = 0.0;
if (normx > 0) {
windowxmax = (width - 1 - xoffset) / xscale;
normmultx = (windowxmax - point1[0]) / normx;
} else if (normx < 0) {
windowxmin = -xoffset / xscale;
normmultx = (windowxmin - point1[0]) / normx;
}
normmulty = 0.0;
if (normy > 0) {
windowymax = -yoffset / yscale;
normmulty = (windowymax - point1[1]) / normy;
} else if (normy < 0) {
windowymin = (height - 1 - yoffset) / yscale;
normmulty = (windowymin - point1[1]) / normy;
}
if (normmultx == 0.0) {
normmult = normmulty;
} else if (normmulty == 0.0) {
normmult = normmultx;
} else if (normmultx < normmulty) {
normmult = normmultx;
} else {
normmult = normmulty;
}
if (normmult > 0.0) {
XDrawLine(display, mainwindow, linegc,
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset),
(int) ((point1[0] + normmult * normx) * xscale + xoffset),
(int) ((point1[1] + normmult * normy) * yscale + yoffset));
}
} else {
point2 = &nodeptr[edgeptr[index++] * dim];
XDrawLine(display, mainwindow, linegc,
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset),
(int) (point2[0] * xscale + xoffset),
(int) (point2[1] * yscale + yoffset));
}
}
}
void draw_adj(dim, subdomains, ptr, center, xscale, yscale,
xoffset, yoffset)
int dim;
int subdomains;
int *ptr;
REAL *center;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
{
int i, j;
REAL *point1, *point2;
for (i = 0; i < subdomains; i++) {
for (j = i + 1; j < subdomains; j++) {
if (ptr[i * subdomains + j]) {
point1 = &center[i * dim];
point2 = &center[j * dim];
XDrawLine(display, mainwindow, linegc,
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset),
(int) (point2[0] * xscale + xoffset),
(int) (point2[1] * yscale + yoffset));
}
}
}
for (i = 0; i < subdomains; i++) {
point1 = &center[i * dim];
if (color) {
XSetForeground(display, linegc, colors[i & 63]);
}
XFillArc(display, mainwindow, linegc,
(int) (point1[0] * xscale + xoffset) - 5 - (line_width >> 1),
(int) (point1[1] * yscale + yoffset) - 5 - (line_width >> 1),
line_width + 10, line_width + 10, 0, 23040);
}
XSetForeground(display, linegc, showme_foreground);
}
void draw(inc, image, xmin, ymin, xmax, ymax)
int inc;
int image;
REAL xmin;
REAL ymin;
REAL xmax;
REAL ymax;
{
draw_buttons();
XClearWindow(display, mainwindow);
if (image == NOTHING) {
return;
}
if (!loaded[inc][image]) {
return;
}
if ((image == PART) && explode) {
xmin += (xmin - partcenter[inc][subdomains[inc] << 1]) * explosion;
xmax += (xmax - partcenter[inc][subdomains[inc] << 1]) * explosion;
ymin += (ymin - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
ymax += (ymax - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
}
xscale = (REAL) (width - line_width - 4) / (xmax - xmin);
yscale = (REAL) (height - line_width - 4) / (ymax - ymin);
if (xscale > yscale) {
xscale = yscale;
} else {
yscale = xscale;
}
xoffset = 0.5 * ((REAL) width - xscale * (xmax - xmin)) -
xscale * xmin;
yoffset = (REAL) height - 0.5 * ((REAL) height - yscale * (ymax - ymin)) +
yscale * ymin;
yscale = - yscale;
switch(image) {
case NODE:
draw_node(nodes[inc], node_dim[inc], nodeptr[inc],
xscale, yscale, xoffset, yoffset);
break;
case POLY:
if (polynodes[inc] > 0) {
draw_poly(polynodes[inc], poly_dim[inc], polyedges[inc],
polyholes[inc], polynodeptr[inc], polyedgeptr[inc],
polyholeptr[inc],
xscale, yscale, xoffset, yoffset);
} else {
draw_poly(nodes[inc], node_dim[inc], polyedges[inc],
polyholes[inc], nodeptr[inc], polyedgeptr[inc],
polyholeptr[inc],
xscale, yscale, xoffset, yoffset);
}
break;
case ELE:
draw_ele(inc, elems[inc], ele_corners[inc], eleptr[inc],
(int *) NULL, (REAL *) NULL,
xscale, yscale, xoffset, yoffset);
break;
case EDGE:
draw_edge(nodes[inc], node_dim[inc], edges[inc],
nodeptr[inc], edgeptr[inc], normptr[inc],
xscale, yscale, xoffset, yoffset);
break;
case PART:
draw_ele(inc, elems[inc], ele_corners[inc], eleptr[inc],
partpart[inc], partshift[inc],
xscale, yscale, xoffset, yoffset);
break;
case ADJ:
draw_adj(node_dim[inc], adjsubdomains[inc], adjptr[inc], partcenter[inc],
xscale, yscale, xoffset, yoffset);
break;
case VORO:
if (loaded[inc][NODE]) {
draw_node(nodes[inc], node_dim[inc], nodeptr[inc],
xscale, yscale, xoffset, yoffset);
}
draw_edge(vnodes[inc], vnode_dim[inc], vedges[inc],
vnodeptr[inc], vedgeptr[inc], vnormptr[inc],
xscale, yscale, xoffset, yoffset);
break;
default:
break;
}
}
void addps(instring, outstring, eps)
char *instring;
char *outstring;
int eps;
{
strcpy(outstring, instring);
if (eps) {
strcat(outstring, ".eps");
} else {
strcat(outstring, ".ps");
}
}
int print_head(fname, file, llcornerx, llcornery, eps)
char *fname;
FILE **file;
int llcornerx;
int llcornery;
int eps;
{
if (!quiet) {
printf("Writing %s\n", fname);
}
*file = fopen(fname, "w");
if (*file == (FILE *) NULL) {
printf(" Error: Could not open %s\n", fname);
return 1;
}
if (eps) {
fprintf(*file, "%%!PS-Adobe-2.0 EPSF-2.0\n");
} else {
fprintf(*file, "%%!PS-Adobe-2.0\n");
}
fprintf(*file, "%%%%BoundingBox: %d %d %d %d\n", llcornerx, llcornery,
612 - llcornerx, 792 - llcornery);
fprintf(*file, "%%%%Creator: Show Me\n");
fprintf(*file, "%%%%EndComments\n\n");
fprintf(*file, "1 setlinecap\n");
fprintf(*file, "1 setlinejoin\n");
fprintf(*file, "%d setlinewidth\n", line_width);
fprintf(*file, "%d %d moveto\n", llcornerx, llcornery);
fprintf(*file, "%d %d lineto\n", 612 - llcornerx, llcornery);
fprintf(*file, "%d %d lineto\n", 612 - llcornerx, 792 - llcornery);
fprintf(*file, "%d %d lineto\n", llcornerx, 792 - llcornery);
fprintf(*file, "closepath\nclip\nnewpath\n");
return 0;
}
void print_node(nodefile, nodes, dim, ptr, xscale, yscale,
xoffset, yoffset)
FILE *nodefile;
int nodes;
int dim;
REAL *ptr;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
{
int i;
int index;
index = dim;
for (i = 1; i <= nodes; i++) {
fprintf(nodefile, "%d %d %d 0 360 arc\nfill\n",
(int) (ptr[index] * xscale + xoffset),
(int) (ptr[index + 1] * yscale + yoffset),
1 + (line_width >> 1));
index += dim;
}
}
void print_poly(polyfile, nodes, dim, edges, holes, nodeptr, edgeptr, holeptr,
xscale, yscale, xoffset, yoffset)
FILE *polyfile;
int nodes;
int dim;
int edges;
int holes;
REAL *nodeptr;
int *edgeptr;
REAL *holeptr;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
{
int i;
int index;
REAL *point1, *point2;
index = dim;
for (i = 1; i <= nodes; i++) {
fprintf(polyfile, "%d %d %d 0 360 arc\nfill\n",
(int) (nodeptr[index] * xscale + xoffset),
(int) (nodeptr[index + 1] * yscale + yoffset),
1 + (line_width >> 1));
index += dim;
}
index = 2;
for (i = 1; i <= edges; i++) {
point1 = &nodeptr[edgeptr[index++] * dim];
point2 = &nodeptr[edgeptr[index++] * dim];
fprintf(polyfile, "%d %d moveto\n",
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset));
fprintf(polyfile, "%d %d lineto\nstroke\n",
(int) (point2[0] * xscale + xoffset),
(int) (point2[1] * yscale + yoffset));
}
}
void print_ele(elefile, nodes, dim, elems, corners, nodeptr, eleptr,
partition, shift,
xscale, yscale, xoffset, yoffset, llcornerx, llcornery)
FILE *elefile;
int nodes;
int dim;
int elems;
int corners;
REAL *nodeptr;
int *eleptr;
int *partition;
REAL *shift;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
int llcornerx;
int llcornery;
{
int i, j;
int index, colorindex;
REAL shiftx, shifty;
REAL *nowpoint;
index = 3;
if ((partition != (int *) NULL) && !bw_ps) {
fprintf(elefile, "0 0 0 setrgbcolor\n");
fprintf(elefile, "%d %d moveto\n", llcornerx, llcornery);
fprintf(elefile, "%d %d lineto\n", 612 - llcornerx, llcornery);
fprintf(elefile, "%d %d lineto\n", 612 - llcornerx, 792 - llcornery);
fprintf(elefile, "%d %d lineto\n", llcornerx, 792 - llcornery);
fprintf(elefile, "fill\n");
}
for (i = 1; i <= elems; i++) {
if ((partition != (int *) NULL) && !bw_ps) {
colorindex = partition[i] & 63;
fprintf(elefile, "%6.3f %6.3f %6.3f setrgbcolor\n",
(REAL) rgb[colorindex].red / 65535.0,
(REAL) rgb[colorindex].green / 65535.0,
(REAL) rgb[colorindex].blue / 65535.0);
}
nowpoint = &nodeptr[eleptr[index + 2] * dim];
if ((partition != (int *) NULL) && (explode || bw_ps)) {
shiftx = shift[partition[i] << 1];
shifty = shift[(partition[i] << 1) + 1];
fprintf(elefile, "%d %d moveto\n",
(int) ((nowpoint[0] + shiftx) * xscale + xoffset),
(int) ((nowpoint[1] + shifty) * yscale + yoffset));
for (j = 0; j < 3; j++) {
nowpoint = &nodeptr[eleptr[index++] * dim];
fprintf(elefile, "%d %d lineto\n",
(int) ((nowpoint[0] + shiftx) * xscale + xoffset),
(int) ((nowpoint[1] + shifty) * yscale + yoffset));
}
} else {
fprintf(elefile, "%d %d moveto\n",
(int) (nowpoint[0] * xscale + xoffset),
(int) (nowpoint[1] * yscale + yoffset));
for (j = 0; j < 3; j++) {
nowpoint = &nodeptr[eleptr[index++] * dim];
fprintf(elefile, "%d %d lineto\n",
(int) (nowpoint[0] * xscale + xoffset),
(int) (nowpoint[1] * yscale + yoffset));
}
}
if (fillelem && !bw_ps) {
fprintf(elefile, "gsave\nfill\ngrestore\n1 1 0 setrgbcolor\n");
}
fprintf(elefile, "stroke\n");
}
}
void print_edge(edgefile, nodes, dim, edges, nodeptr, edgeptr, normptr,
xscale, yscale, xoffset, yoffset, llcornerx, llcornery)
FILE *edgefile;
int nodes;
int dim;
int edges;
REAL *nodeptr;
int *edgeptr;
REAL *normptr;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
int llcornerx;
int llcornery;
{
int i;
int index;
REAL *point1, *point2;
REAL normx, normy;
REAL normmult, normmultx, normmulty;
REAL windowxmin, windowymin, windowxmax, windowymax;
index = 2;
for (i = 1; i <= edges; i++) {
point1 = &nodeptr[edgeptr[index++] * dim];
if (edgeptr[index] == -1) {
normx = normptr[index - 1];
normy = normptr[index++];
normmultx = 0.0;
if (normx > 0) {
windowxmax = ((REAL) (612 - llcornerx) - xoffset) / xscale;
normmultx = (windowxmax - point1[0]) / normx;
} else if (normx < 0) {
windowxmin = ((REAL) llcornerx - xoffset) / xscale;
normmultx = (windowxmin - point1[0]) / normx;
}
normmulty = 0.0;
if (normy > 0) {
windowymax = ((REAL) (792 - llcornery) - yoffset) / yscale;
normmulty = (windowymax - point1[1]) / normy;
} else if (normy < 0) {
windowymin = ((REAL) llcornery - yoffset) / yscale;
normmulty = (windowymin - point1[1]) / normy;
}
if (normmultx == 0.0) {
normmult = normmulty;
} else if (normmulty == 0.0) {
normmult = normmultx;
} else if (normmultx < normmulty) {
normmult = normmultx;
} else {
normmult = normmulty;
}
if (normmult > 0.0) {
fprintf(edgefile, "%d %d moveto\n",
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset));
fprintf(edgefile, "%d %d lineto\nstroke\n",
(int) ((point1[0] + normmult * normx) * xscale + xoffset),
(int) ((point1[1] + normmult * normy) * yscale + yoffset));
}
} else {
point2 = &nodeptr[edgeptr[index++] * dim];
fprintf(edgefile, "%d %d moveto\n",
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset));
fprintf(edgefile, "%d %d lineto\nstroke\n",
(int) (point2[0] * xscale + xoffset),
(int) (point2[1] * yscale + yoffset));
}
}
}
void print_adj(adjfile, dim, subdomains, ptr, center, xscale, yscale,
xoffset, yoffset, llcornerx, llcornery)
FILE *adjfile;
int dim;
int subdomains;
int *ptr;
REAL *center;
REAL xscale;
REAL yscale;
REAL xoffset;
REAL yoffset;
int llcornerx;
int llcornery;
{
int i, j;
REAL *point1, *point2;
int colorindex;
if (!bw_ps) {
fprintf(adjfile, "0 0 0 setrgbcolor\n");
fprintf(adjfile, "%d %d moveto\n", llcornerx, llcornery);
fprintf(adjfile, "%d %d lineto\n", 612 - llcornerx, llcornery);
fprintf(adjfile, "%d %d lineto\n", 612 - llcornerx, 792 - llcornery);
fprintf(adjfile, "%d %d lineto\n", llcornerx, 792 - llcornery);
fprintf(adjfile, "fill\n");
fprintf(adjfile, "1 1 0 setrgbcolor\n");
}
for (i = 0; i < subdomains; i++) {
for (j = i + 1; j < subdomains; j++) {
if (ptr[i * subdomains + j]) {
point1 = &center[i * dim];
point2 = &center[j * dim];
fprintf(adjfile, "%d %d moveto\n",
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset));
fprintf(adjfile, "%d %d lineto\nstroke\n",
(int) (point2[0] * xscale + xoffset),
(int) (point2[1] * yscale + yoffset));
}
}
}
for (i = 0; i < subdomains; i++) {
point1 = &center[i * dim];
if (!bw_ps) {
colorindex = i & 63;
fprintf(adjfile, "%6.3f %6.3f %6.3f setrgbcolor\n",
(REAL) rgb[colorindex].red / 65535.0,
(REAL) rgb[colorindex].green / 65535.0,
(REAL) rgb[colorindex].blue / 65535.0);
fprintf(adjfile, "%d %d %d 0 360 arc\nfill\n",
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset),
5 + (line_width >> 1));
} else {
fprintf(adjfile, "%d %d %d 0 360 arc\nfill\n",
(int) (point1[0] * xscale + xoffset),
(int) (point1[1] * yscale + yoffset),
3 + (line_width >> 1));
}
}
}
void print(inc, image, xmin, ymin, xmax, ymax, eps)
int inc;
int image;
REAL xmin;
REAL ymin;
REAL xmax;
REAL ymax;
int eps;
{
REAL xxscale, yyscale, xxoffset, yyoffset;
char psfilename[FILENAMESIZE];
int llcornerx, llcornery;
FILE *psfile;
if (image == NOTHING) {
return;
}
if (!loaded[inc][image]) {
return;
}
if ((image == PART) && (explode || bw_ps)) {
xmin += (xmin - partcenter[inc][subdomains[inc] << 1]) * explosion;
xmax += (xmax - partcenter[inc][subdomains[inc] << 1]) * explosion;
ymin += (ymin - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
ymax += (ymax - partcenter[inc][(subdomains[inc] << 1) + 1]) * explosion;
}
xxscale = (460.0 - (REAL) line_width) / (xmax - xmin);
yyscale = (640.0 - (REAL) line_width) / (ymax - ymin);
if (xxscale > yyscale) {
xxscale = yyscale;
llcornerx = (604 - (int) (yyscale * (xmax - xmin)) - line_width) >> 1;
llcornery = 72;
} else {
yyscale = xxscale;
llcornerx = 72;
llcornery = (784 - (int) (xxscale * (ymax - ymin)) - line_width) >> 1;
}
xxoffset = 0.5 * (612.0 - xxscale * (xmax - xmin)) - xxscale * xmin +
(line_width >> 1);
yyoffset = 0.5 * (792.0 - yyscale * (ymax - ymin)) - yyscale * ymin +
(line_width >> 1);
switch(image) {
case NODE:
addps(nodefilename[inc], psfilename, eps);
break;
case POLY:
addps(polyfilename[inc], psfilename, eps);
break;
case ELE:
addps(elefilename[inc], psfilename, eps);
break;
case EDGE:
addps(edgefilename[inc], psfilename, eps);
break;
case PART:
addps(partfilename[inc], psfilename, eps);
break;
case ADJ:
addps(adjfilename[inc], psfilename, eps);
break;
case VORO:
addps(vedgefilename[inc], psfilename, eps);
break;
default:
break;
}
if (print_head(psfilename, &psfile, llcornerx, llcornery, eps)) {
return;
}
switch(image) {
case NODE:
print_node(psfile, nodes[inc], node_dim[inc], nodeptr[inc],
xxscale, yyscale, xxoffset, yyoffset);
break;
case POLY:
if (polynodes[inc] > 0) {
print_poly(psfile, polynodes[inc], poly_dim[inc], polyedges[inc],
polyholes[inc], polynodeptr[inc], polyedgeptr[inc],
polyholeptr[inc], xxscale, yyscale, xxoffset, yyoffset);
} else {
print_poly(psfile, nodes[inc], node_dim[inc], polyedges[inc],
polyholes[inc], nodeptr[inc], polyedgeptr[inc],
polyholeptr[inc], xxscale, yyscale, xxoffset, yyoffset);
}
break;
case ELE:
print_ele(psfile, nodes[inc], node_dim[inc], elems[inc],
ele_corners[inc], nodeptr[inc], eleptr[inc],
(int *) NULL, (REAL *) NULL,
xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
break;
case EDGE:
print_edge(psfile, nodes[inc], node_dim[inc], edges[inc],
nodeptr[inc], edgeptr[inc], normptr[inc],
xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
break;
case PART:
print_ele(psfile, nodes[inc], node_dim[inc], elems[inc],
ele_corners[inc], nodeptr[inc], eleptr[inc],
partpart[inc], partshift[inc],
xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
break;
case ADJ:
print_adj(psfile, node_dim[inc], adjsubdomains[inc], adjptr[inc],
partcenter[inc],
xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
break;
case VORO:
print_edge(psfile, vnodes[inc], vnode_dim[inc], vedges[inc],
vnodeptr[inc], vedgeptr[inc], vnormptr[inc],
xxscale, yyscale, xxoffset, yyoffset, llcornerx, llcornery);
break;
default:
break;
}
if (!eps) {
fprintf(psfile, "showpage\n");
}
fclose(psfile);
}
int main(argc, argv)
int argc;
char **argv;
{
REAL xmin, ymin, xmax, ymax;
REAL xptr, yptr, xspan, yspan;
int past_image;
int new_image;
int new_inc;
parsecommandline(argc, argv);
showme_init();
choose_image(start_inc, start_image);
showme_window(argc, argv);
if (current_image != NOTHING) {
xmin = xlo[current_inc][current_image];
ymin = ylo[current_inc][current_image];
xmax = xhi[current_inc][current_image];
ymax = yhi[current_inc][current_image];
zoom = 0;
}
XMaskEvent(display, ExposureMask, &event);
while (1) {
switch (event.type) {
case ButtonRelease:
if (event.xany.window == quitwin) {
XDestroyWindow(display, mainwindow);
XCloseDisplay(display);
return 0;
} else if (event.xany.window == leftwin) {
xspan = 0.25 * (xmax - xmin);
xmin += xspan;
xmax += xspan;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
} else if (event.xany.window == rightwin) {
xspan = 0.25 * (xmax - xmin);
xmin -= xspan;
xmax -= xspan;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
} else if (event.xany.window == upwin) {
yspan = 0.25 * (ymax - ymin);
ymin -= yspan;
ymax -= yspan;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
} else if (event.xany.window == downwin) {
yspan = 0.25 * (ymax - ymin);
ymin += yspan;
ymax += yspan;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
} else if (event.xany.window == resetwin) {
xmin = xlo[current_inc][current_image];
ymin = ylo[current_inc][current_image];
xmax = xhi[current_inc][current_image];
ymax = yhi[current_inc][current_image];
zoom = 0;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
} else if (event.xany.window == widthpluswin) {
if (line_width < 100) {
line_width++;
XSetLineAttributes(display, linegc, line_width, LineSolid,
CapRound, JoinRound);
XSetLineAttributes(display, trianglegc, line_width, LineSolid,
CapRound, JoinRound);
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
}
} else if (event.xany.window == widthminuswin) {
if (line_width > 1) {
line_width--;
XSetLineAttributes(display, linegc, line_width, LineSolid,
CapRound, JoinRound);
XSetLineAttributes(display, trianglegc, line_width, LineSolid,
CapRound, JoinRound);
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
}
} else if (event.xany.window == expwin) {
if ((current_image == PART) && loaded[current_inc][PART]) {
explode = !explode;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
}
} else if (event.xany.window == exppluswin) {
if ((current_image == PART) && loaded[PART] && explode) {
explosion += 0.125;
findpartshift(subdomains[current_inc], explosion,
partcenter[current_inc], partshift[current_inc]);
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
}
} else if (event.xany.window == expminuswin) {
if ((current_image == PART) && loaded[PART] && explode &&
(explosion >= 0.125)) {
explosion -= 0.125;
findpartshift(subdomains[current_inc], explosion,
partcenter[current_inc], partshift[current_inc]);
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
}
} else if (event.xany.window == fillwin) {
if ((current_image == PART) && loaded[PART]) {
fillelem = !fillelem;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
}
} else if (event.xany.window == pswin) {
fill_button(pswin);
XFlush(display);
print(current_inc, current_image, xmin, ymin, xmax, ymax, 0);
XClearWindow(display, pswin);
XDrawString(display, pswin, fontgc, 2, 13, "PS", 2);
} else if (event.xany.window == epswin) {
fill_button(epswin);
XFlush(display);
print(current_inc, current_image, xmin, ymin, xmax, ymax, 1);
XClearWindow(display, epswin);
XDrawString(display, epswin, fontgc, 2, 13, "EPS", 3);
} else if (event.xany.window == versionpluswin) {
move_inc(1);
loweriteration++;
set_filenames(filename, loweriteration);
if (current_inc == 1) {
current_inc = 0;
} else {
current_image = NOTHING;
XClearWindow(display, mainwindow);
}
draw_buttons();
} else if (event.xany.window == versionminuswin) {
if (loweriteration > 0) {
move_inc(0);
loweriteration--;
set_filenames(filename, loweriteration);
if (current_inc == 0) {
current_inc = 1;
} else {
current_image = NOTHING;
XClearWindow(display, mainwindow);
}
draw_buttons();
}
} else if ((event.xany.window == nodewin[0]) ||
(event.xany.window == polywin[0]) ||
(event.xany.window == elewin[0]) ||
(event.xany.window == edgewin[0]) ||
(event.xany.window == partwin[0]) ||
(event.xany.window == adjwin[0]) ||
(event.xany.window == voronoiwin[0]) ||
(event.xany.window == nodewin[1]) ||
(event.xany.window == polywin[1]) ||
(event.xany.window == elewin[1]) ||
(event.xany.window == edgewin[1]) ||
(event.xany.window == partwin[1]) ||
(event.xany.window == adjwin[1]) ||
(event.xany.window == voronoiwin[1])) {
if (event.xany.window == nodewin[0]) {
new_inc = 0;
new_image = NODE;
}
if (event.xany.window == polywin[0]) {
new_inc = 0;
new_image = POLY;
}
if (event.xany.window == elewin[0]) {
new_inc = 0;
new_image = ELE;
}
if (event.xany.window == edgewin[0]) {
new_inc = 0;
new_image = EDGE;
}
if (event.xany.window == partwin[0]) {
new_inc = 0;
new_image = PART;
}
if (event.xany.window == adjwin[0]) {
new_inc = 0;
new_image = ADJ;
}
if (event.xany.window == voronoiwin[0]) {
new_inc = 0;
new_image = VORO;
}
if (event.xany.window == nodewin[1]) {
new_inc = 1;
new_image = NODE;
}
if (event.xany.window == polywin[1]) {
new_inc = 1;
new_image = POLY;
}
if (event.xany.window == elewin[1]) {
new_inc = 1;
new_image = ELE;
}
if (event.xany.window == edgewin[1]) {
new_inc = 1;
new_image = EDGE;
}
if (event.xany.window == partwin[1]) {
new_inc = 1;
new_image = PART;
}
if (event.xany.window == adjwin[1]) {
new_inc = 1;
new_image = ADJ;
}
if (event.xany.window == voronoiwin[1]) {
new_inc = 1;
new_image = VORO;
}
past_image = current_image;
if ((current_inc == new_inc) && (current_image == new_image)) {
free_inc(new_inc);
unload_inc(new_inc);
}
choose_image(new_inc, new_image);
if ((past_image == NOTHING) && (current_image != NOTHING)) {
xmin = xlo[current_inc][current_image];
ymin = ylo[current_inc][current_image];
xmax = xhi[current_inc][current_image];
ymax = yhi[current_inc][current_image];
zoom = 0;
}
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
} else {
xptr = ((REAL) event.xbutton.x - xoffset) / xscale;
yptr = ((REAL) event.xbutton.y - yoffset) / yscale;
if ((current_image == PART) && loaded[PART] && explode) {
xptr = (xptr + partcenter[current_inc]
[subdomains[current_inc] << 1]
* explosion) / (1.0 + explosion);
yptr = (yptr + partcenter[current_inc]
[(subdomains[current_inc] << 1) + 1]
* explosion) / (1.0 + explosion);
}
if ((event.xbutton.button == Button1)
|| (event.xbutton.button == Button3)) {
if (event.xbutton.button == Button1) {
xspan = 0.25 * (xmax - xmin);
yspan = 0.25 * (ymax - ymin);
zoom++;
} else {
xspan = xmax - xmin;
yspan = ymax - ymin;
zoom--;
}
xmin = xptr - xspan;
ymin = yptr - yspan;
xmax = xptr + xspan;
ymax = yptr + yspan;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
} else if (event.xbutton.button == Button2) {
printf("x = %.4g, y = %.4g\n", xptr, yptr);
}
}
break;
case DestroyNotify:
XDestroyWindow(display, mainwindow);
XCloseDisplay(display);
return 0;
case ConfigureNotify:
if ((width != event.xconfigure.width) ||
(height != event.xconfigure.height - PANELHEIGHT)) {
width = event.xconfigure.width;
height = event.xconfigure.height - PANELHEIGHT;
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
while (XCheckMaskEvent(display, ExposureMask, &event));
}
break;
case Expose:
draw(current_inc, current_image, xmin, ymin, xmax, ymax);
while (XCheckMaskEvent(display, ExposureMask, &event));
break;
default:
break;
}
XNextEvent(display, &event);
}
}
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/*****************************************************************************/
/* */
/* (triangle.h) */
/* */
/* Include file for programs that call Triangle. */
/* */
/* Accompanies Triangle Version 1.3 */
/* July 19, 1996 */
/* */
/* Copyright 1996 */
/* Jonathan Richard Shewchuk */
/* School of Computer Science */
/* Carnegie Mellon University */
/* 5000 Forbes Avenue */
/* Pittsburgh, Pennsylvania 15213-3891 */
/* jrs@cs.cmu.edu */
/* */
/*****************************************************************************/
/*****************************************************************************/
/* */
/* How to call Triangle from another program */
/* */
/* */
/* If you haven't read Triangle's instructions (run "triangle -h" to read */
/* them), you won't understand what follows. */
/* */
/* Triangle must be compiled into an object file (triangle.o) with the */
/* TRILIBRARY symbol defined (preferably by using the -DTRILIBRARY compiler */
/* switch). The makefile included with Triangle will do this for you if */
/* you run "make trilibrary". The resulting object file can be called via */
/* the procedure triangulate(). */
/* */
/* If the size of the object file is important to you, you may wish to */
/* generate a reduced version of triangle.o. The REDUCED symbol gets rid */
/* of all features that are primarily of research interest. Specifically, */
/* the -DREDUCED switch eliminates Triangle's -i, -F, -s, and -C switches. */
/* The CDT_ONLY symbol gets rid of all meshing algorithms above and beyond */
/* constrained Delaunay triangulation. Specifically, the -DCDT_ONLY switch */
/* eliminates Triangle's -r, -q, -a, -S, and -s switches. */
/* */
/* IMPORTANT: These definitions (TRILIBRARY, REDUCED, CDT_ONLY) must be */
/* made in the makefile or in triangle.c itself. Putting these definitions */
/* in this file will not create the desired effect. */
/* */
/* */
/* The calling convention for triangulate() follows. */
/* */
/* void triangulate(triswitches, in, out, vorout) */
/* char *triswitches; */
/* struct triangulateio *in; */
/* struct triangulateio *out; */
/* struct triangulateio *vorout; */
/* */
/* `triswitches' is a string containing the command line switches you wish */
/* to invoke. No initial dash is required. Some suggestions: */
/* */
/* - You'll probably find it convenient to use the `z' switch so that */
/* points (and other items) are numbered from zero. This simplifies */
/* indexing, because the first item of any type always starts at index */
/* [0] of the corresponding array, whether that item's number is zero or */
/* one. */
/* - You'll probably want to use the `Q' (quiet) switch in your final code, */
/* but you can take advantage of Triangle's printed output (including the */
/* `V' switch) while debugging. */
/* - If you are not using the `q' or `a' switches, then the output points */
/* will be identical to the input points, except possibly for the */
/* boundary markers. If you don't need the boundary markers, you should */
/* use the `N' (no nodes output) switch to save memory. (If you do need */
/* boundary markers, but need to save memory, a good nasty trick is to */
/* set out->pointlist equal to in->pointlist before calling triangulate(),*/
/* so that Triangle overwrites the input points with identical copies.) */
/* - The `I' (no iteration numbers) and `g' (.off file output) switches */
/* have no effect when Triangle is compiled with TRILIBRARY defined. */
/* */
/* `in', `out', and `vorout' are descriptions of the input, the output, */
/* and the Voronoi output. If the `v' (Voronoi output) switch is not used, */
/* `vorout' may be NULL. `in' and `out' may never be NULL. */
/* */
/* Certain fields of the input and output structures must be initialized, */
/* as described below. */
/* */
/*****************************************************************************/
/*****************************************************************************/
/* */
/* The `triangulateio' structure. */
/* */
/* Used to pass data into and out of the triangulate() procedure. */
/* */
/* */
/* Arrays are used to store points, triangles, markers, and so forth. In */
/* all cases, the first item in any array is stored starting at index [0]. */
/* However, that item is item number `1' unless the `z' switch is used, in */
/* which case it is item number `0'. Hence, you may find it easier to */
/* index points (and triangles in the neighbor list) if you use the `z' */
/* switch. Unless, of course, you're calling Triangle from a Fortran */
/* program. */
/* */
/* Description of fields (except the `numberof' fields, which are obvious): */
/* */
/* `pointlist': An array of point coordinates. The first point's x */
/* coordinate is at index [0] and its y coordinate at index [1], followed */
/* by the coordinates of the remaining points. Each point occupies two */
/* REALs. */
/* `pointattributelist': An array of point attributes. Each point's */
/* attributes occupy `numberofpointattributes' REALs. */
/* `pointmarkerlist': An array of point markers; one int per point. */
/* */
/* `trianglelist': An array of triangle corners. The first triangle's */
/* first corner is at index [0], followed by its other two corners in */
/* counterclockwise order, followed by any other nodes if the triangle */
/* represents a nonlinear element. Each triangle occupies */
/* `numberofcorners' ints. */
/* `triangleattributelist': An array of triangle attributes. Each */
/* triangle's attributes occupy `numberoftriangleattributes' REALs. */
/* `trianglearealist': An array of triangle area constraints; one REAL per */
/* triangle. Input only. */
/* `neighborlist': An array of triangle neighbors; three ints per */
/* triangle. Output only. */
/* */
/* `segmentlist': An array of segment endpoints. The first segment's */
/* endpoints are at indices [0] and [1], followed by the remaining */
/* segments. Two ints per segment. */
/* `segmentmarkerlist': An array of segment markers; one int per segment. */
/* */
/* `holelist': An array of holes. The first hole's x and y coordinates */
/* are at indices [0] and [1], followed by the remaining holes. Two */
/* REALs per hole. Input only, although the pointer is copied to the */
/* output structure for your convenience. */
/* */
/* `regionlist': An array of regional attributes and area constraints. */
/* The first constraint's x and y coordinates are at indices [0] and [1], */
/* followed by the regional attribute and index [2], followed by the */
/* maximum area at index [3], followed by the remaining area constraints. */
/* Four REALs per area constraint. Note that each regional attribute is */
/* used only if you select the `A' switch, and each area constraint is */
/* used only if you select the `a' switch (with no number following), but */
/* omitting one of these switches does not change the memory layout. */
/* Input only, although the pointer is copied to the output structure for */
/* your convenience. */
/* */
/* `edgelist': An array of edge endpoints. The first edge's endpoints are */
/* at indices [0] and [1], followed by the remaining edges. Two ints per */
/* edge. Output only. */
/* `edgemarkerlist': An array of edge markers; one int per edge. Output */
/* only. */
/* `normlist': An array of normal vectors, used for infinite rays in */
/* Voronoi diagrams. The first normal vector's x and y magnitudes are */
/* at indices [0] and [1], followed by the remaining vectors. For each */
/* finite edge in a Voronoi diagram, the normal vector written is the */
/* zero vector. Two REALs per edge. Output only. */
/* */
/* */
/* Any input fields that Triangle will examine must be initialized. */
/* Furthermore, for each output array that Triangle will write to, you */
/* must either provide space by setting the appropriate pointer to point */
/* to the space you want the data written to, or you must initialize the */
/* pointer to NULL, which tells Triangle to allocate space for the results. */
/* The latter option is preferable, because Triangle always knows exactly */
/* how much space to allocate. The former option is provided mainly for */
/* people who need to call Triangle from Fortran code, though it also makes */
/* possible some nasty space-saving tricks, like writing the output to the */
/* same arrays as the input. */
/* */
/* Triangle will not free() any input or output arrays, including those it */
/* allocates itself; that's up to you. */
/* */
/* Here's a guide to help you decide which fields you must initialize */
/* before you call triangulate(). */
/* */
/* `in': */
/* */
/* - `pointlist' must always point to a list of points; `numberofpoints' */
/* and `numberofpointattributes' must be properly set. */
/* `pointmarkerlist' must either be set to NULL (in which case all */
/* markers default to zero), or must point to a list of markers. If */
/* `numberofpointattributes' is not zero, `pointattributelist' must */
/* point to a list of point attributes. */
/* - If the `r' switch is used, `trianglelist' must point to a list of */
/* triangles, and `numberoftriangles', `numberofcorners', and */
/* `numberoftriangleattributes' must be properly set. If */
/* `numberoftriangleattributes' is not zero, `triangleattributelist' */
/* must point to a list of triangle attributes. If the `a' switch is */
/* used (with no number following), `trianglearealist' must point to a */
/* list of triangle area constraints. `neighborlist' may be ignored. */
/* - If the `p' switch is used, `segmentlist' must point to a list of */
/* segments, `numberofsegments' must be properly set, and */
/* `segmentmarkerlist' must either be set to NULL (in which case all */
/* markers default to zero), or must point to a list of markers. */
/* - If the `p' switch is used without the `r' switch, then */
/* `numberofholes' and `numberofregions' must be properly set. If */
/* `numberofholes' is not zero, `holelist' must point to a list of */
/* holes. If `numberofregions' is not zero, `regionlist' must point to */
/* a list of region constraints. */
/* - If the `p' switch is used, `holelist', `numberofholes', */
/* `regionlist', and `numberofregions' is copied to `out'. (You can */
/* nonetheless get away with not initializing them if the `r' switch is */
/* used.) */
/* - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */
/* ignored. */
/* */
/* `out': */
/* */
/* - `pointlist' must be initialized (NULL or pointing to memory) unless */
/* the `N' switch is used. `pointmarkerlist' must be initialized */
/* unless the `N' or `B' switch is used. If `N' is not used and */
/* `in->numberofpointattributes' is not zero, `pointattributelist' must */
/* be initialized. */
/* - `trianglelist' must be initialized unless the `E' switch is used. */
/* `neighborlist' must be initialized if the `n' switch is used. If */
/* the `E' switch is not used and (`in->numberofelementattributes' is */
/* not zero or the `A' switch is used), `elementattributelist' must be */
/* initialized. `trianglearealist' may be ignored. */
/* - `segmentlist' must be initialized if the `p' or `c' switch is used, */
/* and the `P' switch is not used. `segmentmarkerlist' must also be */
/* initialized under these circumstances unless the `B' switch is used. */
/* - `edgelist' must be initialized if the `e' switch is used. */
/* `edgemarkerlist' must be initialized if the `e' switch is used and */
/* the `B' switch is not. */
/* - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/
/* */
/* `vorout' (only needed if `v' switch is used): */
/* */
/* - `pointlist' must be initialized. If `in->numberofpointattributes' */
/* is not zero, `pointattributelist' must be initialized. */
/* `pointmarkerlist' may be ignored. */
/* - `edgelist' and `normlist' must both be initialized. */
/* `edgemarkerlist' may be ignored. */
/* - Everything else may be ignored. */
/* */
/* After a call to triangulate(), the valid fields of `out' and `vorout' */
/* will depend, in an obvious way, on the choice of switches used. Note */
/* that when the `p' switch is used, the pointers `holelist' and */
/* `regionlist' are copied from `in' to `out', but no new space is */
/* allocated; be careful that you don't free() the same array twice. On */
/* the other hand, Triangle will never copy the `pointlist' pointer (or any */
/* others); new space is allocated for `out->pointlist', or if the `N' */
/* switch is used, `out->pointlist' remains uninitialized. */
/* */
/* All of the meaningful `numberof' fields will be properly set; for */
/* instance, `numberofedges' will represent the number of edges in the */
/* triangulation whether or not the edges were written. If segments are */
/* not used, `numberofsegments' will indicate the number of boundary edges. */
/* */
/*****************************************************************************/
struct triangulateio {
REAL *pointlist; /* In / out */
REAL *pointattributelist; /* In / out */
int *pointmarkerlist; /* In / out */
int numberofpoints; /* In / out */
int numberofpointattributes; /* In / out */
int *trianglelist; /* In / out */
REAL *triangleattributelist; /* In / out */
REAL *trianglearealist; /* In only */
int *neighborlist; /* Out only */
int numberoftriangles; /* In / out */
int numberofcorners; /* In / out */
int numberoftriangleattributes; /* In / out */
int *segmentlist; /* In / out */
int *segmentmarkerlist; /* In / out */
int numberofsegments; /* In / out */
REAL *holelist; /* In / pointer to array copied out */
int numberofholes; /* In / copied out */
REAL *regionlist; /* In / pointer to array copied out */
int numberofregions; /* In / copied out */
int *edgelist; /* Out only */
int *edgemarkerlist; /* Not used with Voronoi diagram; out only */
REAL *normlist; /* Used only with Voronoi diagram; out only */
int numberofedges; /* Out only */
};
#ifdef ANSI_DECLARATORS
void triangulate(char *, struct triangulateio *, struct triangulateio *,
struct triangulateio *);
#else /* not ANSI_DECLARATORS */
void triangulate();
#endif /* not ANSI_DECLARATORS */
/*****************************************************************************/
/* */
/* (tricall.c) */
/* */
/* Example program that demonstrates how to call Triangle. */
/* */
/* Accompanies Triangle Version 1.3 */
/* July 19, 1996 */
/* */
/* This file is placed in the public domain (but the file that it calls */
/* is still copyrighted!) by */
/* Jonathan Richard Shewchuk */
/* School of Computer Science */
/* Carnegie Mellon University */
/* 5000 Forbes Avenue */
/* Pittsburgh, Pennsylvania 15213-3891 */
/* jrs@cs.cmu.edu */
/* */
/*****************************************************************************/
/* If SINGLE is defined when triangle.o is compiled, it should also be */
/* defined here. If not, it should not be defined here. */
/* #define SINGLE */
#ifdef SINGLE
#define REAL float
#else /* not SINGLE */
#define REAL double
#endif /* not SINGLE */
#include <stdio.h>
#include "triangle.h"
#ifndef _STDLIB_H_
extern void *malloc();
extern void free();
#endif /* _STDLIB_H_ */
/*****************************************************************************/
/* */
/* report() Print the input or output. */
/* */
/*****************************************************************************/
void report(io, markers, reporttriangles, reportneighbors, reportsegments,
reportedges, reportnorms)
struct triangulateio *io;
int markers;
int reporttriangles;
int reportneighbors;
int reportsegments;
int reportedges;
int reportnorms;
{
int i, j;
for (i = 0; i < io->numberofpoints; i++) {
printf("Point %4d:", i);
for (j = 0; j < 2; j++) {
printf(" %.6g", io->pointlist[i * 2 + j]);
}
if (io->numberofpointattributes > 0) {
printf(" attributes");
}
for (j = 0; j < io->numberofpointattributes; j++) {
printf(" %.6g",
io->pointattributelist[i * io->numberofpointattributes + j]);
}
if (markers) {
printf(" marker %d\n", io->pointmarkerlist[i]);
} else {
printf("\n");
}
}
printf("\n");
if (reporttriangles || reportneighbors) {
for (i = 0; i < io->numberoftriangles; i++) {
if (reporttriangles) {
printf("Triangle %4d points:", i);
for (j = 0; j < io->numberofcorners; j++) {
printf(" %4d", io->trianglelist[i * io->numberofcorners + j]);
}
if (io->numberoftriangleattributes > 0) {
printf(" attributes");
}
for (j = 0; j < io->numberoftriangleattributes; j++) {
printf(" %.6g", io->triangleattributelist[i *
io->numberoftriangleattributes + j]);
}
printf("\n");
}
if (reportneighbors) {
printf("Triangle %4d neighbors:", i);
for (j = 0; j < 3; j++) {
printf(" %4d", io->neighborlist[i * 3 + j]);
}
printf("\n");
}
}
printf("\n");
}
if (reportsegments) {
for (i = 0; i < io->numberofsegments; i++) {
printf("Segment %4d points:", i);
for (j = 0; j < 2; j++) {
printf(" %4d", io->segmentlist[i * 2 + j]);
}
if (markers) {
printf(" marker %d\n", io->segmentmarkerlist[i]);
} else {
printf("\n");
}
}
printf("\n");
}
if (reportedges) {
for (i = 0; i < io->numberofedges; i++) {
printf("Edge %4d points:", i);
for (j = 0; j < 2; j++) {
printf(" %4d", io->edgelist[i * 2 + j]);
}
if (reportnorms && (io->edgelist[i * 2 + 1] == -1)) {
for (j = 0; j < 2; j++) {
printf(" %.6g", io->normlist[i * 2 + j]);
}
}
if (markers) {
printf(" marker %d\n", io->edgemarkerlist[i]);
} else {
printf("\n");
}
}
printf("\n");
}
}
/*****************************************************************************/
/* */
/* main() Create and refine a mesh. */
/* */
/*****************************************************************************/
int main()
{
struct triangulateio in, mid, out, vorout;
/* Define input points. */
in.numberofpoints = 4;
in.numberofpointattributes = 1;
in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
in.pointlist[0] = 0.0;
in.pointlist[1] = 0.0;
in.pointlist[2] = 1.0;
in.pointlist[3] = 0.0;
in.pointlist[4] = 1.0;
in.pointlist[5] = 10.0;
in.pointlist[6] = 0.0;
in.pointlist[7] = 10.0;
in.pointattributelist = (REAL *) malloc(in.numberofpoints *
in.numberofpointattributes *
sizeof(REAL));
in.pointattributelist[0] = 0.0;
in.pointattributelist[1] = 1.0;
in.pointattributelist[2] = 11.0;
in.pointattributelist[3] = 10.0;
in.pointmarkerlist = (int *) malloc(in.numberofpoints * sizeof(int));
in.pointmarkerlist[0] = 0;
in.pointmarkerlist[1] = 2;
in.pointmarkerlist[2] = 0;
in.pointmarkerlist[3] = 0;
in.numberofsegments = 0;
in.numberofholes = 0;
in.numberofregions = 1;
in.regionlist = (REAL *) malloc(in.numberofregions * 4 * sizeof(REAL));
in.regionlist[0] = 0.5;
in.regionlist[1] = 5.0;
in.regionlist[2] = 7.0; /* Regional attribute (for whole mesh). */
in.regionlist[3] = 0.1; /* Area constraint that will not be used. */
printf("Input point set:\n\n");
report(&in, 1, 0, 0, 0, 0, 0);
/* Make necessary initializations so that Triangle can return a */
/* triangulation in `mid' and a voronoi diagram in `vorout'. */
mid.pointlist = (REAL *) NULL; /* Not needed if -N switch used. */
/* Not needed if -N switch used or number of point attributes is zero: */
mid.pointattributelist = (REAL *) NULL;
mid.pointmarkerlist = (int *) NULL; /* Not needed if -N or -B switch used. */
mid.trianglelist = (int *) NULL; /* Not needed if -E switch used. */
/* Not needed if -E switch used or number of triangle attributes is zero: */
mid.triangleattributelist = (REAL *) NULL;
mid.neighborlist = (int *) NULL; /* Needed only if -n switch used. */
/* Needed only if segments are output (-p or -c) and -P not used: */
mid.segmentlist = (int *) NULL;
/* Needed only if segments are output (-p or -c) and -P and -B not used: */
mid.segmentmarkerlist = (int *) NULL;
mid.edgelist = (int *) NULL; /* Needed only if -e switch used. */
mid.edgemarkerlist = (int *) NULL; /* Needed if -e used and -B not used. */
vorout.pointlist = (REAL *) NULL; /* Needed only if -v switch used. */
/* Needed only if -v switch used and number of attributes is not zero: */
vorout.pointattributelist = (REAL *) NULL;
vorout.edgelist = (int *) NULL; /* Needed only if -v switch used. */
vorout.normlist = (REAL *) NULL; /* Needed only if -v switch used. */
/* Triangulate the points. Switches are chosen to read and write a */
/* PSLG (p), preserve the convex hull (c), number everything from */
/* zero (z), assign a regional attribute to each element (A), and */
/* produce an edge list (e), a Voronoi diagram (v), and a triangle */
/* neighbor list (n). */
triangulate("pczAevn", &in, &mid, &vorout);
printf("Initial triangulation:\n\n");
report(&mid, 1, 1, 1, 1, 1, 0);
printf("Initial Voronoi diagram:\n\n");
report(&vorout, 0, 0, 0, 0, 1, 1);
/* Attach area constraints to the triangles in preparation for */
/* refining the triangulation. */
/* Needed only if -r and -a switches used: */
mid.trianglearealist = (REAL *) malloc(mid.numberoftriangles * sizeof(REAL));
mid.trianglearealist[0] = 3.0;
mid.trianglearealist[1] = 1.0;
/* Make necessary initializations so that Triangle can return a */
/* triangulation in `out'. */
out.pointlist = (REAL *) NULL; /* Not needed if -N switch used. */
/* Not needed if -N switch used or number of attributes is zero: */
out.pointattributelist = (REAL *) NULL;
out.trianglelist = (int *) NULL; /* Not needed if -E switch used. */
/* Not needed if -E switch used or number of triangle attributes is zero: */
out.triangleattributelist = (REAL *) NULL;
/* Refine the triangulation according to the attached */
/* triangle area constraints. */
triangulate("prazBP", &mid, &out, (struct triangulateio *) NULL);
printf("Refined triangulation:\n\n");
report(&out, 0, 1, 0, 0, 0, 0);
/* Free all allocated arrays, including those allocated by Triangle. */
free(in.pointlist);
free(in.pointattributelist);
free(in.pointmarkerlist);
free(in.regionlist);
free(mid.pointlist);
free(mid.pointattributelist);
free(mid.pointmarkerlist);
free(mid.trianglelist);
free(mid.triangleattributelist);
free(mid.trianglearealist);
free(mid.neighborlist);
free(mid.segmentlist);
free(mid.segmentmarkerlist);
free(mid.edgelist);
free(mid.edgemarkerlist);
free(vorout.pointlist);
free(vorout.pointattributelist);
free(vorout.edgelist);
free(vorout.normlist);
free(out.pointlist);
free(out.pointattributelist);
free(out.trianglelist);
free(out.triangleattributelist);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment