From 7ee54664b6e1a49d9c57dacd3aa3500df742975d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 20 Oct 1997 19:52:18 +0000
Subject: [PATCH 001/283] Initial revision.

---
 Tools/Makefile |  91 +++++++++++++++++++++++++++++++++++
 Tools/make.inc | 125 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 216 insertions(+)
 create mode 100644 Tools/Makefile
 create mode 100644 Tools/make.inc

diff --git a/Tools/Makefile b/Tools/Makefile
new file mode 100644
index 000000000..34b2a5254
--- /dev/null
+++ b/Tools/Makefile
@@ -0,0 +1,91 @@
+#---------------------------------------------------------------------------
+# Toplevel FGTools Makefile
+#
+# Written by Curtis Olson, started October 1997.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+include make.inc
+
+
+SUBDIRS = Dem2node Tri2terrain Triangle
+
+
+all: 
+	for dir in $(SUBDIRS); do \
+	    ( cd $$dir; $(MAKE) ) ; \
+	done
+
+depend:
+	for dir in $(SUBDIRS); do \
+	    ( echo "Making depend in $$dir"; \
+	      cd $$dir; $(CC) -MM *.c > depend ) ; \
+	done
+
+Makefile-os2:
+	cat Makefile | perl mkmfos2.pl > Makefile.os2; \
+	for dir in $(SUBDIRS); do \
+	    ( echo "Making Makefile.os2 in $$dir"; \
+	      cat $$dir/Makefile | perl mkmfos2.pl > $$dir/Makefile.os2; \
+	      cat $$dir/depend   | perl mkmfos2.pl > $$dir/depend.os2) ; \
+	done
+
+clean:
+	-rm -f *.os2 *~
+	for dir in $(SUBDIRS); do \
+	    (cd $$dir; $(MAKE) clean) ; \
+	done
+
+
+source-tar: clean
+	echo "need to fix this"
+#	(cd ../..; \
+#	tar cvzf source-$(VERSION).tar.gz FlightGear/fgtop FlightGear/COPYING \
+#	FlightGear/Docs FlightGear/Src FlightGear/Thanks)
+
+source-zip: clean
+	echo "need to fix this"
+#	(cd ../..; \
+#	zip -r source-$(VERSION).zip FlightGear/fgtop FlightGear/COPYING \
+#	FlightGear/Docs FlightGear/Src FlightGear/Thanks)
+
+bin-tar: all
+	echo "need to fix this"
+#	cp GLUT/fg0 GLUT/runfg ..
+#	(cd ../..; \
+#	tar cvzf bin-$(VERSION).tar.gz FlightGear/fgtop FlightGear/fg0 \
+#	FlightGear/runfg FlightGear/COPYING FlightGear/Docs FlightGear/Thanks)
+
+bin-zip: 
+	echo "need to fix this"
+#	cp GLUT/fg0.exe GLUT/runfg.bat GLUT/cygwin.dll ..
+#	(cd ../..; \
+#	zip -r bin-$(VERSION).zip FlightGear/fgtop FlightGear/fg0.exe \
+#	FlightGear/runfg.bat FlightGear/cygwin.dll FlightGear/COPYING \
+#	FlightGear/Docs FlightGear/Thanks)
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1997/10/20 19:52:18  curt
+# Initial revision.
+#
diff --git a/Tools/make.inc b/Tools/make.inc
new file mode 100644
index 000000000..47b06d67b
--- /dev/null
+++ b/Tools/make.inc
@@ -0,0 +1,125 @@
+# Hey Emacs, this is a Makefile. -*- Mode: Makefile -*-
+#
+# Common FGTools Makefile section
+#
+# Written by Curtis Olson, started October 1997.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+VERSION = 0.01
+
+#---------------------------------------------------------------------------
+# Choose your weapons
+#---------------------------------------------------------------------------
+
+CC = gcc
+FLEX = flex -f -L
+BISON = bison -v --no-lines
+AR = ar
+RANLIB = ranlib
+
+
+#---------------------------------------------------------------------------
+# Global Compile Options
+#
+# You may set FG_CFLAGS to include any of the following options depending on 
+# your environment:
+#
+# -g           - Compile with debugging symbols
+#
+# -Wall        - Enable full compiler warnings
+#
+# -O2          - Enable compiler optimization
+#
+#---------------------------------------------------------------------------
+
+GLOBAL_CFLAGS = -g -Wall -DVERSION=\"$(VERSION)\"
+
+
+#---------------------------------------------------------------------------
+# Platform specific compile options, these should be set with FG_CFLAGS
+# below.  These have been predefined for the supported platforms below.
+#
+# -DNO_PRINTF -  Disable all printf()'s.  Works by replacing the printf
+#                fuction with an empty function.
+#
+# -DUSE_ITIMER - Use setitimer(), getitimer(), and signal() to mimic
+#                a real time system and call the flight model routines
+#                at a regular interval, rather than between screen updates
+#                which can be highly variable.  This can make the flight
+#                model calculations much smoother.
+#
+# -DUSE_FTIME -  Use ftime() to get an accurate current time instead of
+#                gettimeofday()
+#
+# -DUSE_RAND  -  Use rand() instead of random()
+#
+#---------------------------------------------------------------------------
+
+
+#---------------------------------------------------------------------------
+# Uncomment one of the following sections depending on your system
+#
+# You may set FG_GRAPHICS to include any of the following options depending
+# on your environment:
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# SGI IRIX with the GLUT toolkit 
+#     (Surprisingly, this also works on our SunOS 4.x machine with the 
+#     way we have Mesa & Glut installed.)
+#
+# INTERFACE_FLAGS = -DGLUT
+# INTERFACE_LIBS = -lglut
+# INTERFACE_FILES = GLUTmain.c GLUTkey.c
+# GRAPHICS_LIBS = -lGLU -lGL -lXmu -lX11
+# FG_CFLAGS = $(GLOBAL_CFLAGS)
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# Linux/Mesa with the GLUT toolkit
+#
+INTERFACE_FLAGS = -DGLUT
+INTERFACE_LIBS = -lglut
+INTERFACE_FILES = GLUTmain.c GLUTkey.c
+MESA_LIBS = -L/usr/lib/mesa -lMesatk -lMesaaux -lMesaGLU -lMesaGL
+X11_LIBS =  -L/usr/X11R6/lib -lXext -lXmu -lXi -lX11
+GRAPHICS_LIBS = $(MESA_LIBS) $(X11_LIBS)
+FG_CFLAGS = $(GLOBAL_CFLAGS)
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# Cygnus Win32 (gcc based) with a static version of the GLUT toolkit
+#
+# INTERFACE_FLAGS = -DGLUT 
+# INTERFACE_LIBS = ../Win32/libglut.a
+# INTERFACE_FILES = GLUTmain.c GLUTkey.c
+# GRAPHICS_LIBS = -lglu32 -lopengl32 -luser32 -lgdi32
+# FG_CFLAGS = $(GLOBAL_CFLAGS) -DWIN32 -DUSE_RAND
+#---------------------------------------------------------------------------
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1997/10/20 19:52:18  curt
+# Initial revision.
+#

From e5cd4c5b9d9545a9a59a361dfd6d6b8e6c0e49bd Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 20 Oct 1997 21:35:12 +0000
Subject: [PATCH 002/283] Initial revision.

---
 Triangle/A.poly     |    62 +
 Triangle/Makefile   |   111 +
 Triangle/README     |   181 +
 Triangle/depend     |     3 +
 Triangle/showme.c   |  3384 +++++++++++
 Triangle/triangle.c | 13232 ++++++++++++++++++++++++++++++++++++++++++
 Triangle/triangle.h |   284 +
 Triangle/tricall.c  |   279 +
 8 files changed, 17536 insertions(+)
 create mode 100644 Triangle/A.poly
 create mode 100644 Triangle/Makefile
 create mode 100644 Triangle/README
 create mode 100644 Triangle/depend
 create mode 100644 Triangle/showme.c
 create mode 100644 Triangle/triangle.c
 create mode 100644 Triangle/triangle.h
 create mode 100644 Triangle/tricall.c

diff --git a/Triangle/A.poly b/Triangle/A.poly
new file mode 100644
index 000000000..166a71773
--- /dev/null
+++ b/Triangle/A.poly
@@ -0,0 +1,62 @@
+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
diff --git a/Triangle/Makefile b/Triangle/Makefile
new file mode 100644
index 000000000..e048c5a67
--- /dev/null
+++ b/Triangle/Makefile
@@ -0,0 +1,111 @@
+# 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
+
+clean: distclean
+
+distclean:
+	$(RM) $(BIN)triangle $(BIN)triangle.o $(BIN)showme
diff --git a/Triangle/README b/Triangle/README
new file mode 100644
index 000000000..571d5689f
--- /dev/null
+++ b/Triangle/README
@@ -0,0 +1,181 @@
+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
diff --git a/Triangle/depend b/Triangle/depend
new file mode 100644
index 000000000..8265ad69e
--- /dev/null
+++ b/Triangle/depend
@@ -0,0 +1,3 @@
+showme.o: showme.c
+triangle.o: triangle.c
+tricall.o: tricall.c triangle.h
diff --git a/Triangle/showme.c b/Triangle/showme.c
new file mode 100644
index 000000000..6c4f0a95d
--- /dev/null
+++ b/Triangle/showme.c
@@ -0,0 +1,3384 @@
+/*****************************************************************************/
+/*                                                                           */
+/*    ,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);
+  }
+}
diff --git a/Triangle/triangle.c b/Triangle/triangle.c
new file mode 100644
index 000000000..67bd00ddb
--- /dev/null
+++ b/Triangle/triangle.c
@@ -0,0 +1,13232 @@
+/*****************************************************************************/
+/*                                                                           */
+/*      888888888        ,o,                          / 888                  */
+/*         888    88o88o  "    o8888o  88o8888o o88888o 888  o88888o         */
+/*         888    888    888       88b 888  888 888 888 888 d888  88b        */
+/*         888    888    888  o88^o888 888  888 "88888" 888 8888oo888        */
+/*         888    888    888 C888  888 888  888  /      888 q888             */
+/*         888    888    888  "88o^888 888  888 Cb      888  "88oooo"        */
+/*                                              "8oo8D                       */
+/*                                                                           */
+/*  A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.      */
+/*  (triangle.c)                                                             */
+/*                                                                           */
+/*  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                                                           */
+/*                                                                           */
+/*  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/triangle.html                           */
+/*                                                                           */
+/*  Some of the references listed below are marked [*].  These are available */
+/*    for downloading from the Web page                                      */
+/*                                                                           */
+/*      http://www.cs.cmu.edu/~quake/triangle.research.html                  */
+/*                                                                           */
+/*  A paper discussing some aspects of Triangle is available.  See Jonathan  */
+/*    Richard Shewchuk, "Triangle:  Engineering a 2D Quality Mesh Generator  */
+/*    and Delaunay Triangulator," First Workshop on Applied Computational    */
+/*    Geometry, ACM, May 1996.  [*]                                          */
+/*                                                                           */
+/*  Triangle 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.           */
+/*                                                                           */
+/*  The quality mesh generation algorithm is due to Jim Ruppert, "A          */
+/*    Delaunay Refinement Algorithm for Quality 2-Dimensional Mesh           */
+/*    Generation," Journal of Algorithms 18(3):548-585, May 1995.  [*]       */
+/*                                                                           */
+/*  My implementation of the divide-and-conquer and incremental Delaunay     */
+/*    triangulation algorithms follows closely the presentation of Guibas    */
+/*    and Stolfi, even though I use a triangle-based data structure instead  */
+/*    of their quad-edge data structure.  (In fact, I originally implemented */
+/*    Triangle using the quad-edge data structure, but switching to a        */
+/*    triangle-based data structure sped Triangle by a factor of two.)  The  */
+/*    mesh manipulation primitives and the two aforementioned Delaunay       */
+/*    triangulation algorithms are described by Leonidas J. Guibas and Jorge */
+/*    Stolfi, "Primitives for the Manipulation of General Subdivisions and   */
+/*    the Computation of Voronoi Diagrams," ACM Transactions on Graphics     */
+/*    4(2):74-123, April 1985.                                               */
+/*                                                                           */
+/*  Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai   */
+/*    Lee and Bruce J. Schachter, "Two Algorithms for Constructing the       */
+/*    Delaunay Triangulation," International Journal of Computer and         */
+/*    Information Science 9(3):219-242, 1980.  The idea to improve the       */
+/*    divide-and-conquer algorithm by alternating between vertical and       */
+/*    horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and-  */
+/*    Conquer Algorithm for Constructing Delaunay Triangulations,"           */
+/*    Algorithmica 2(2):137-151, 1987.                                       */
+/*                                                                           */
+/*  The incremental insertion algorithm was first proposed by C. L. Lawson,  */
+/*    "Software for C1 Surface Interpolation," in Mathematical Software III, */
+/*    John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977.     */
+/*    For point location, I use the algorithm of Ernst P. Mucke, Isaac       */
+/*    Saias, and Binhai Zhu, "Fast Randomized Point Location Without         */
+/*    Preprocessing in Two- and Three-dimensional Delaunay Triangulations,"  */
+/*    Proceedings of the Twelfth Annual Symposium on Computational Geometry, */
+/*    ACM, May 1996.  [*]  If I were to randomize the order of point         */
+/*    insertion (I currently don't bother), their result combined with the   */
+/*    result of Leonidas J. Guibas, Donald E. Knuth, and Micha Sharir,       */
+/*    "Randomized Incremental Construction of Delaunay and Voronoi           */
+/*    Diagrams," Algorithmica 7(4):381-413, 1992, would yield an expected    */
+/*    O(n^{4/3}) bound on running time.                                      */
+/*                                                                           */
+/*  The O(n log n) sweepline Delaunay triangulation algorithm is taken from  */
+/*    Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams",          */
+/*    Algorithmica 2(2):153-174, 1987.  A random sample of edges on the      */
+/*    boundary of the triangulation are maintained in a splay tree for the   */
+/*    purpose of point location.  Splay trees are described by Daniel        */
+/*    Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
+/*    Trees," Journal of the ACM 32(3):652-686, July 1985.                   */
+/*                                                                           */
+/*  The algorithms for exact computation of the signs of determinants are    */
+/*    described in Jonathan Richard Shewchuk, "Adaptive Precision Floating-  */
+/*    Point Arithmetic and Fast Robust Geometric Predicates," Technical      */
+/*    Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon      */
+/*    University, Pittsburgh, Pennsylvania, May 1996.  [*]  (Submitted to    */
+/*    Discrete & Computational Geometry.)  An abbreviated version appears as */
+/*    Jonathan Richard Shewchuk, "Robust Adaptive Floating-Point Geometric   */
+/*    Predicates," Proceedings of the Twelfth Annual Symposium on Computa-   */
+/*    tional Geometry, ACM, May 1996.  [*]  Many of the ideas for my exact   */
+/*    arithmetic routines originate with Douglas M. Priest, "Algorithms for  */
+/*    Arbitrary Precision Floating Point Arithmetic," Tenth Symposium on     */
+/*    Computer Arithmetic, 132-143, IEEE Computer Society Press, 1991.  [*]  */
+/*    Many of the ideas for the correct evaluation of the signs of           */
+/*    determinants are taken from Steven Fortune and Christopher J. Van Wyk, */
+/*    "Efficient Exact Arithmetic for Computational Geometry," Proceedings   */
+/*    of the Ninth Annual Symposium on Computational Geometry, ACM,          */
+/*    pp. 163-172, May 1993, and from Steven Fortune, "Numerical Stability   */
+/*    of Algorithms for 2D Delaunay Triangulations," International Journal   */
+/*    of Computational Geometry & Applications 5(1-2):193-213, March-June    */
+/*    1995.                                                                  */
+/*                                                                           */
+/*  For definitions of and results involving Delaunay triangulations,        */
+/*    constrained and conforming versions thereof, and other aspects of      */
+/*    triangular mesh generation, see the excellent survey by Marshall Bern  */
+/*    and David Eppstein, "Mesh Generation and Optimal Triangulation," in    */
+/*    Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang,         */
+/*    editors, World Scientific, Singapore, pp. 23-90, 1992.                 */
+/*                                                                           */
+/*  The time for incrementally adding PSLG (planar straight line graph)      */
+/*    segments to create a constrained Delaunay triangulation is probably    */
+/*    O(n^2) per segment in the worst case and O(n) per edge in the common   */
+/*    case, where n is the number of triangles that intersect the segment    */
+/*    before it is inserted.  This doesn't count point location, which can   */
+/*    be much more expensive.  (This note does not apply to conforming       */
+/*    Delaunay triangulations, for which a different method is used to       */
+/*    insert segments.)                                                      */
+/*                                                                           */
+/*  The time for adding segments to a conforming Delaunay triangulation is   */
+/*    not clear, but does not depend upon n alone.  In some cases, very      */
+/*    small features (like a point lying next to a segment) can cause a      */
+/*    single segment to be split an arbitrary number of times.  Of course,   */
+/*    floating-point precision is a practical barrier to how much this can   */
+/*    happen.                                                                */
+/*                                                                           */
+/*  The time for deleting a point from a Delaunay triangulation is O(n^2) in */
+/*    the worst case and O(n) in the common case, where n is the degree of   */
+/*    the point being deleted.  I could improve this to expected O(n) time   */
+/*    by "inserting" the neighboring vertices in random order, but n is      */
+/*    usually quite small, so it's not worth the bother.  (The O(n) time     */
+/*    for random insertion follows from L. Paul Chew, "Building Voronoi      */
+/*    Diagrams for Convex Polygons in Linear Expected Time," Technical       */
+/*    Report PCS-TR90-147, Department of Mathematics and Computer Science,   */
+/*    Dartmouth College, 1990.                                               */
+/*                                                                           */
+/*  Ruppert's Delaunay refinement algorithm typically generates triangles    */
+/*    at a linear rate (constant time per triangle) after the initial        */
+/*    triangulation is formed.  There may be pathological cases where more   */
+/*    time is required, but these never arise in practice.                   */
+/*                                                                           */
+/*  The segment intersection formulae are straightforward.  If you want to   */
+/*    see them derived, see Franklin Antonio.  "Faster Line Segment          */
+/*    Intersection."  In Graphics Gems III (David Kirk, editor), pp. 199-    */
+/*    202.  Academic Press, Boston, 1992.                                    */
+/*                                                                           */
+/*  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.  This code is provided "as-is".  Use at your own risk.     */
+/*                                                                           */
+/*****************************************************************************/
+
+/* For single precision (which will save some memory and reduce paging),     */
+/*   define the symbol SINGLE by using the -DSINGLE compiler switch or by    */
+/*   writing "#define SINGLE" below.                                         */
+/*                                                                           */
+/* For double precision (which will allow you to refine meshes to a smaller  */
+/*   edge length), leave SINGLE undefined.                                   */
+/*                                                                           */
+/* 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.  Finally, 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.                                          */
+
+/* #define SINGLE */
+
+#ifdef SINGLE
+#define REAL float
+#else /* not SINGLE */
+#define REAL double
+#endif /* not SINGLE */
+
+/* If yours is not a Unix system, define the NO_TIMER compiler switch to     */
+/*   remove the Unix-specific timing code.                                   */
+
+/* #define NO_TIMER */
+
+/* To insert lots of self-checks for internal errors, define the SELF_CHECK  */
+/*   symbol.  This will slow down the program significantly.  It is best to  */
+/*   define the symbol using the -DSELF_CHECK compiler switch, but you could */
+/*   write "#define SELF_CHECK" below.  If you are modifying this code, I    */
+/*   recommend you turn self-checks on.                                      */
+
+/* #define SELF_CHECK */
+
+/* To compile Triangle as a callable object library (triangle.o), define the */
+/*   TRILIBRARY symbol.  Read the file triangle.h for details on how to call */
+/*   the procedure triangulate() that results.                               */
+
+/* #define TRILIBRARY */
+
+/* It is possible to generate a smaller version of Triangle using one or     */
+/*   both of the following symbols.  Define the REDUCED symbol to eliminate  */
+/*   all features that are primarily of research interest; specifically, the */
+/*   -i, -F, -s, and -C switches.  Define the CDT_ONLY symbol to eliminate   */
+/*   all meshing algorithms above and beyond constrained Delaunay            */
+/*   triangulation; specifically, the -r, -q, -a, -S, and -s switches.       */
+/*   These reductions are most likely to be useful when generating an object */
+/*   library (triangle.o) by defining the TRILIBRARY symbol.                 */
+
+/* #define REDUCED */
+/* #define CDT_ONLY */
+
+/* On some machines, the exact arithmetic routines might be defeated by the  */
+/*   use of internal extended precision floating-point registers.  Sometimes */
+/*   this problem can be fixed by defining certain values to be volatile,    */
+/*   thus forcing them to be stored to memory and rounded off.  This isn't   */
+/*   a great solution, though, as it slows Triangle down.                    */
+/*                                                                           */
+/* To try this out, write "#define INEXACT volatile" below.  Normally,       */
+/*   however, INEXACT should be defined to be nothing.  ("#define INEXACT".) */
+
+#define INEXACT /* Nothing */
+/* #define INEXACT volatile */
+
+/* Maximum number of characters in a file name (including the null).         */
+
+#define FILENAMESIZE 512
+
+/* Maximum number of characters in a line read from a file (including the    */
+/*   null).                                                                  */
+
+#define INPUTLINESIZE 512
+
+/* For efficiency, a variety of data structures are allocated in bulk.  The  */
+/*   following constants determine how many of each structure is allocated   */
+/*   at once.                                                                */
+
+#define TRIPERBLOCK 4092           /* Number of triangles allocated at once. */
+#define SHELLEPERBLOCK 508       /* Number of shell edges allocated at once. */
+#define POINTPERBLOCK 4092            /* Number of points allocated at once. */
+#define VIRUSPERBLOCK 1020   /* Number of virus triangles allocated at once. */
+/* Number of encroached segments allocated at once. */
+#define BADSEGMENTPERBLOCK 252
+/* Number of skinny triangles allocated at once. */
+#define BADTRIPERBLOCK 4092
+/* Number of splay tree nodes allocated at once. */
+#define SPLAYNODEPERBLOCK 508
+
+/* The point marker DEADPOINT is an arbitrary number chosen large enough to  */
+/*   (hopefully) not conflict with user boundary markers.  Make sure that it */
+/*   is small enough to fit into your machine's integer size.                */
+
+#define DEADPOINT -1073741824
+
+/* The next line is used to outsmart some very stupid compilers.  If your    */
+/*   compiler is smarter, feel free to replace the "int" with "void".        */
+/*   Not that it matters.                                                    */
+
+#define VOID int
+
+/* Two constants for algorithms based on random sampling.  Both constants    */
+/*   have been chosen empirically to optimize their respective algorithms.   */
+
+/* Used for the point location scheme of Mucke, Saias, and Zhu, to decide    */
+/*   how large a random sample of triangles to inspect.                      */
+#define SAMPLEFACTOR 11
+/* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */
+/*   of boundary edges should be maintained in the splay tree for point      */
+/*   location on the front.                                                  */
+#define SAMPLERATE 10
+
+/* A number that speaks for itself, every kissable digit.                    */
+
+#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
+
+/* Another fave.                                                             */
+
+#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
+
+/* And here's one for those of you who are intimidated by math.              */
+
+#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#ifndef NO_TIMER
+#include <sys/time.h>
+#endif /* NO_TIMER */
+#ifdef TRILIBRARY
+#include "triangle.h"
+#endif /* TRILIBRARY */
+
+/* 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 void *malloc();
+extern void free();
+extern void exit();
+extern double strtod();
+extern long strtol();
+#endif /* _STDLIB_H_ */
+
+/* A few forward declarations.                                               */
+
+void poolrestart();
+#ifndef TRILIBRARY
+char *readline();
+char *findfield();
+#endif /* not TRILIBRARY */
+
+/* Labels that signify whether a record consists primarily of pointers or of */
+/*   floating-point words.  Used to make decisions about data alignment.     */
+
+enum wordtype {POINTER, FLOATINGPOINT};
+
+/* Labels that signify the result of point location.  The result of a        */
+/*   search indicates that the point falls in the interior of a triangle, on */
+/*   an edge, on a vertex, or outside the mesh.                              */
+
+enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
+
+/* Labels that signify the result of site insertion.  The result indicates   */
+/*   that the point was inserted with complete success, was inserted but     */
+/*   encroaches on a segment, was not inserted because it lies on a segment, */
+/*   or was not inserted because another point occupies the same location.   */
+
+enum insertsiteresult {SUCCESSFULPOINT, ENCROACHINGPOINT, VIOLATINGPOINT,
+                       DUPLICATEPOINT};
+
+/* Labels that signify the result of direction finding.  The result          */
+/*   indicates that a segment connecting the two query points falls within   */
+/*   the direction triangle, along the left edge of the direction triangle,  */
+/*   or along the right edge of the direction triangle.                      */
+
+enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
+
+/* Labels that signify the result of the circumcenter computation routine.   */
+/*   The return value indicates which edge of the triangle is shortest.      */
+
+enum circumcenterresult {OPPOSITEORG, OPPOSITEDEST, OPPOSITEAPEX};
+
+/*****************************************************************************/
+/*                                                                           */
+/*  The basic mesh data structures                                           */
+/*                                                                           */
+/*  There are three:  points, triangles, and shell edges (abbreviated        */
+/*  `shelle').  These three data structures, linked by pointers, comprise    */
+/*  the mesh.  A point simply represents a point in space and its properties.*/
+/*  A triangle is a triangle.  A shell edge is a special data structure used */
+/*  to represent impenetrable segments in the mesh (including the outer      */
+/*  boundary, boundaries of holes, and internal boundaries separating two    */
+/*  triangulated regions).  Shell edges represent boundaries defined by the  */
+/*  user that triangles may not lie across.                                  */
+/*                                                                           */
+/*  A triangle consists of a list of three vertices, a list of three         */
+/*  adjoining triangles, a list of three adjoining shell edges (when shell   */
+/*  edges are used), an arbitrary number of optional user-defined floating-  */
+/*  point attributes, and an optional area constraint.  The latter is an     */
+/*  upper bound on the permissible area of each triangle in a region, used   */
+/*  for mesh refinement.                                                     */
+/*                                                                           */
+/*  For a triangle on a boundary of the mesh, some or all of the neighboring */
+/*  triangles may not be present.  For a triangle in the interior of the     */
+/*  mesh, often no neighboring shell edges are present.  Such absent         */
+/*  triangles and shell edges are never represented by NULL pointers; they   */
+/*  are represented by two special records:  `dummytri', the triangle that   */
+/*  fills "outer space", and `dummysh', the omnipresent shell edge.          */
+/*  `dummytri' and `dummysh' are used for several reasons; for instance,     */
+/*  they can be dereferenced and their contents examined without causing the */
+/*  memory protection exception that would occur if NULL were dereferenced.  */
+/*                                                                           */
+/*  However, it is important to understand that a triangle includes other    */
+/*  information as well.  The pointers to adjoining vertices, triangles, and */
+/*  shell edges are ordered in a way that indicates their geometric relation */
+/*  to each other.  Furthermore, each of these pointers contains orientation */
+/*  information.  Each pointer to an adjoining triangle indicates which face */
+/*  of that triangle is contacted.  Similarly, each pointer to an adjoining  */
+/*  shell edge indicates which side of that shell edge is contacted, and how */
+/*  the shell edge is oriented relative to the triangle.                     */
+/*                                                                           */
+/*  Shell edges are found abutting edges of triangles; either sandwiched     */
+/*  between two triangles, or resting against one triangle on an exterior    */
+/*  boundary or hole boundary.                                               */
+/*                                                                           */
+/*  A shell edge consists of a list of two vertices, a list of two           */
+/*  adjoining shell edges, and a list of two adjoining triangles.  One of    */
+/*  the two adjoining triangles may not be present (though there should      */
+/*  always be one), and neighboring shell edges might not be present.        */
+/*  Shell edges also store a user-defined integer "boundary marker".         */
+/*  Typically, this integer is used to indicate what sort of boundary        */
+/*  conditions are to be applied at that location in a finite element        */
+/*  simulation.                                                              */
+/*                                                                           */
+/*  Like triangles, shell edges maintain information about the relative      */
+/*  orientation of neighboring objects.                                      */
+/*                                                                           */
+/*  Points are relatively simple.  A point is a list of floating point       */
+/*  numbers, starting with the x, and y coordinates, followed by an          */
+/*  arbitrary number of optional user-defined floating-point attributes,     */
+/*  followed by an integer boundary marker.  During the segment insertion    */
+/*  phase, there is also a pointer from each point to a triangle that may    */
+/*  contain it.  Each pointer is not always correct, but when one is, it     */
+/*  speeds up segment insertion.  These pointers are assigned values once    */
+/*  at the beginning of the segment insertion phase, and are not used or     */
+/*  updated at any other time.  Edge swapping during segment insertion will  */
+/*  render some of them incorrect.  Hence, don't rely upon them for          */
+/*  anything.  For the most part, points do not have any information about   */
+/*  what triangles or shell edges they are linked to.                        */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  Handles                                                                  */
+/*                                                                           */
+/*  The oriented triangle (`triedge') and oriented shell edge (`edge') data  */
+/*  structures defined below do not themselves store any part of the mesh.   */
+/*  The mesh itself is made of `triangle's, `shelle's, and `point's.         */
+/*                                                                           */
+/*  Oriented triangles and oriented shell edges will usually be referred to  */
+/*  as "handles".  A handle is essentially a pointer into the mesh; it       */
+/*  allows you to "hold" one particular part of the mesh.  Handles are used  */
+/*  to specify the regions in which one is traversing and modifying the mesh.*/
+/*  A single `triangle' may be held by many handles, or none at all.  (The   */
+/*  latter case is not a memory leak, because the triangle is still          */
+/*  connected to other triangles in the mesh.)                               */
+/*                                                                           */
+/*  A `triedge' is a handle that holds a triangle.  It holds a specific side */
+/*  of the triangle.  An `edge' is a handle that holds a shell edge.  It     */
+/*  holds either the left or right side of the edge.                         */
+/*                                                                           */
+/*  Navigation about the mesh is accomplished through a set of mesh          */
+/*  manipulation primitives, further below.  Many of these primitives take   */
+/*  a handle and produce a new handle that holds the mesh near the first     */
+/*  handle.  Other primitives take two handles and glue the corresponding    */
+/*  parts of the mesh together.  The exact position of the handles is        */
+/*  important.  For instance, when two triangles are glued together by the   */
+/*  bond() primitive, they are glued by the sides on which the handles lie.  */
+/*                                                                           */
+/*  Because points have no information about which triangles they are        */
+/*  attached to, I commonly represent a point by use of a handle whose       */
+/*  origin is the point.  A single handle can simultaneously represent a     */
+/*  triangle, an edge, and a point.                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+/* The triangle data structure.  Each triangle contains three pointers to    */
+/*   adjoining triangles, plus three pointers to vertex points, plus three   */
+/*   pointers to shell edges (defined below; these pointers are usually      */
+/*   `dummysh').  It may or may not also contain user-defined attributes     */
+/*   and/or a floating-point "area constraint".  It may also contain extra   */
+/*   pointers for nodes, when the user asks for high-order elements.         */
+/*   Because the size and structure of a `triangle' is not decided until     */
+/*   runtime, I haven't simply defined the type `triangle' to be a struct.   */
+
+typedef REAL **triangle;            /* Really:  typedef triangle *triangle   */
+
+/* An oriented triangle:  includes a pointer to a triangle and orientation.  */
+/*   The orientation denotes an edge of the triangle.  Hence, there are      */
+/*   three possible orientations.  By convention, each edge is always        */
+/*   directed to point counterclockwise about the corresponding triangle.    */
+
+struct triedge {
+  triangle *tri;
+  int orient;                                         /* Ranges from 0 to 2. */
+};
+
+/* The shell data structure.  Each shell edge contains two pointers to       */
+/*   adjoining shell edges, plus two pointers to vertex points, plus two     */
+/*   pointers to adjoining triangles, plus one shell marker.                 */
+
+typedef REAL **shelle;                  /* Really:  typedef shelle *shelle   */
+
+/* An oriented shell edge:  includes a pointer to a shell edge and an        */
+/*   orientation.  The orientation denotes a side of the edge.  Hence, there */
+/*   are two possible orientations.  By convention, the edge is always       */
+/*   directed so that the "side" denoted is the right side of the edge.      */
+
+struct edge {
+  shelle *sh;
+  int shorient;                                       /* Ranges from 0 to 1. */
+};
+
+/* The point data structure.  Each point is actually an array of REALs.      */
+/*   The number of REALs is unknown until runtime.  An integer boundary      */
+/*   marker, and sometimes a pointer to a triangle, is appended after the    */
+/*   REALs.                                                                  */
+
+typedef REAL *point;
+
+/* A queue used to store encroached segments.  Each segment's vertices are   */
+/*   stored so that one can check whether a segment is still the same.       */
+
+struct badsegment {
+  struct edge encsegment;                          /* An encroached segment. */
+  point segorg, segdest;                                /* The two vertices. */
+  struct badsegment *nextsegment;     /* Pointer to next encroached segment. */
+};
+
+/* A queue used to store bad triangles.  The key is the square of the cosine */
+/*   of the smallest angle of the triangle.  Each triangle's vertices are    */
+/*   stored so that one can check whether a triangle is still the same.      */
+
+struct badface {
+  struct triedge badfacetri;                              /* A bad triangle. */
+  REAL key;                             /* cos^2 of smallest (apical) angle. */
+  point faceorg, facedest, faceapex;                  /* The three vertices. */
+  struct badface *nextface;                 /* Pointer to next bad triangle. */
+};
+
+/* A node in a heap used to store events for the sweepline Delaunay          */
+/*   algorithm.  Nodes do not point directly to their parents or children in */
+/*   the heap.  Instead, each node knows its position in the heap, and can   */
+/*   look up its parent and children in a separate array.  The `eventptr'    */
+/*   points either to a `point' or to a triangle (in encoded format, so that */
+/*   an orientation is included).  In the latter case, the origin of the     */
+/*   oriented triangle is the apex of a "circle event" of the sweepline      */
+/*   algorithm.  To distinguish site events from circle events, all circle   */
+/*   events are given an invalid (smaller than `xmin') x-coordinate `xkey'.  */
+
+struct event {
+  REAL xkey, ykey;                              /* Coordinates of the event. */
+  VOID *eventptr;       /* Can be a point or the location of a circle event. */
+  int heapposition;              /* Marks this event's position in the heap. */
+};
+
+/* A node in the splay tree.  Each node holds an oriented ghost triangle     */
+/*   that represents a boundary edge of the growing triangulation.  When a   */
+/*   circle event covers two boundary edges with a triangle, so that they    */
+/*   are no longer boundary edges, those edges are not immediately deleted   */
+/*   from the tree; rather, they are lazily deleted when they are next       */
+/*   encountered.  (Since only a random sample of boundary edges are kept    */
+/*   in the tree, lazy deletion is faster.)  `keydest' is used to verify     */
+/*   that a triangle is still the same as when it entered the splay tree; if */
+/*   it has been rotated (due to a circle event), it no longer represents a  */
+/*   boundary edge and should be deleted.                                    */
+
+struct splaynode {
+  struct triedge keyedge;                  /* Lprev of an edge on the front. */
+  point keydest;            /* Used to verify that splay node is still live. */
+  struct splaynode *lchild, *rchild;              /* Children in splay tree. */
+};
+
+/* A type used to allocate memory.  firstblock is the first block of items.  */
+/*   nowblock is the block from which items are currently being allocated.   */
+/*   nextitem points to the next slab of free memory for an item.            */
+/*   deaditemstack is the head of a linked list (stack) of deallocated items */
+/*   that can be recycled.  unallocateditems is the number of items that     */
+/*   remain to be allocated from nowblock.                                   */
+/*                                                                           */
+/* Traversal is the process of walking through the entire list of items, and */
+/*   is separate from allocation.  Note that a traversal will visit items on */
+/*   the "deaditemstack" stack as well as live items.  pathblock points to   */
+/*   the block currently being traversed.  pathitem points to the next item  */
+/*   to be traversed.  pathitemsleft is the number of items that remain to   */
+/*   be traversed in pathblock.                                              */
+/*                                                                           */
+/* itemwordtype is set to POINTER or FLOATINGPOINT, and is used to suggest   */
+/*   what sort of word the record is primarily made up of.  alignbytes       */
+/*   determines how new records should be aligned in memory.  itembytes and  */
+/*   itemwords are the length of a record in bytes (after rounding up) and   */
+/*   words.  itemsperblock is the number of items allocated at once in a     */
+/*   single block.  items is the number of currently allocated items.        */
+/*   maxitems is the maximum number of items that have been allocated at     */
+/*   once; it is the current number of items plus the number of records kept */
+/*   on deaditemstack.                                                       */
+
+struct memorypool {
+  VOID **firstblock, **nowblock;
+  VOID *nextitem;
+  VOID *deaditemstack;
+  VOID **pathblock;
+  VOID *pathitem;
+  enum wordtype itemwordtype;
+  int alignbytes;
+  int itembytes, itemwords;
+  int itemsperblock;
+  long items, maxitems;
+  int unallocateditems;
+  int pathitemsleft;
+};
+
+/* Variables used to allocate memory for triangles, shell edges, points,     */
+/*   viri (triangles being eaten), bad (encroached) segments, bad (skinny    */
+/*   or too large) triangles, and splay tree nodes.                          */
+
+struct memorypool triangles;
+struct memorypool shelles;
+struct memorypool points;
+struct memorypool viri;
+struct memorypool badsegments;
+struct memorypool badtriangles;
+struct memorypool splaynodes;
+
+/* Variables that maintain the bad triangle queues.  The tails are pointers  */
+/*   to the pointers that have to be filled in to enqueue an item.           */
+
+struct badface *queuefront[64];
+struct badface **queuetail[64];
+
+REAL xmin, xmax, ymin, ymax;                              /* x and y bounds. */
+REAL xminextreme;        /* Nonexistent x value used as a flag in sweepline. */
+int inpoints;                                     /* Number of input points. */
+int inelements;                                /* Number of input triangles. */
+int insegments;                                 /* Number of input segments. */
+int holes;                                         /* Number of input holes. */
+int regions;                                     /* Number of input regions. */
+long edges;                                       /* Number of output edges. */
+int mesh_dim;                                  /* Dimension (ought to be 2). */
+int nextras;                              /* Number of attributes per point. */
+int eextras;                           /* Number of attributes per triangle. */
+long hullsize;                            /* Number of edges of convex hull. */
+int triwords;                                   /* Total words per triangle. */
+int shwords;                                  /* Total words per shell edge. */
+int pointmarkindex;             /* Index to find boundary marker of a point. */
+int point2triindex;         /* Index to find a triangle adjacent to a point. */
+int highorderindex;    /* Index to find extra nodes for high-order elements. */
+int elemattribindex;              /* Index to find attributes of a triangle. */
+int areaboundindex;               /* Index to find area bound of a triangle. */
+int checksegments;           /* Are there segments in the triangulation yet? */
+int readnodefile;                             /* Has a .node file been read? */
+long samples;                /* Number of random samples for point location. */
+unsigned long randomseed;                     /* Current random number seed. */
+
+REAL splitter;       /* Used to split REAL factors for exact multiplication. */
+REAL epsilon;                             /* Floating-point machine epsilon. */
+REAL resulterrbound;
+REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
+REAL iccerrboundA, iccerrboundB, iccerrboundC;
+
+long incirclecount;                   /* Number of incircle tests performed. */
+long counterclockcount;       /* Number of counterclockwise tests performed. */
+long hyperbolacount;        /* Number of right-of-hyperbola tests performed. */
+long circumcentercount;    /* Number of circumcenter calculations performed. */
+long circletopcount;         /* Number of circle top calculations performed. */
+
+/* Switches for the triangulator.                                            */
+/*   poly: -p switch.  refine: -r switch.                                    */
+/*   quality: -q switch.                                                     */
+/*     minangle: minimum angle bound, specified after -q switch.             */
+/*     goodangle: cosine squared of minangle.                                */
+/*   vararea: -a switch without number.                                      */
+/*   fixedarea: -a switch with number.                                       */
+/*     maxarea: maximum area bound, specified after -a switch.               */
+/*   regionattrib: -A switch.  convex: -c switch.                            */
+/*   firstnumber: inverse of -z switch.  All items are numbered starting     */
+/*     from firstnumber.                                                     */
+/*   edgesout: -e switch.  voronoi: -v switch.                               */
+/*   neighbors: -n switch.  geomview: -g switch.                             */
+/*   nobound: -B switch.  nopolywritten: -P switch.                          */
+/*   nonodewritten: -N switch.  noelewritten: -E switch.                     */
+/*   noiterationnum: -I switch.  noholes: -O switch.                         */
+/*   noexact: -X switch.                                                     */
+/*   order: element order, specified after -o switch.                        */
+/*   nobisect: count of how often -Y switch is selected.                     */
+/*   steiner: maximum number of Steiner points, specified after -S switch.   */
+/*     steinerleft: number of Steiner points not yet used.                   */
+/*   incremental: -i switch.  sweepline: -F switch.                          */
+/*   dwyer: inverse of -l switch.                                            */
+/*   splitseg: -s switch.                                                    */
+/*   docheck: -C switch.                                                     */
+/*   quiet: -Q switch.  verbose: count of how often -V switch is selected.   */
+/*   useshelles: -p, -r, -q, or -c switch; determines whether shell edges    */
+/*     are used at all.                                                      */
+/*                                                                           */
+/* Read the instructions to find out the meaning of these switches.          */
+
+int poly, refine, quality, vararea, fixedarea, regionattrib, convex;
+int firstnumber;
+int edgesout, voronoi, neighbors, geomview;
+int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
+int noholes, noexact;
+int incremental, sweepline, dwyer;
+int splitseg;
+int docheck;
+int quiet, verbose;
+int useshelles;
+int order;
+int nobisect;
+int steiner, steinerleft;
+REAL minangle, goodangle;
+REAL maxarea;
+
+/* Variables for file names.                                                 */
+
+#ifndef TRILIBRARY
+char innodefilename[FILENAMESIZE];
+char inelefilename[FILENAMESIZE];
+char inpolyfilename[FILENAMESIZE];
+char areafilename[FILENAMESIZE];
+char outnodefilename[FILENAMESIZE];
+char outelefilename[FILENAMESIZE];
+char outpolyfilename[FILENAMESIZE];
+char edgefilename[FILENAMESIZE];
+char vnodefilename[FILENAMESIZE];
+char vedgefilename[FILENAMESIZE];
+char neighborfilename[FILENAMESIZE];
+char offfilename[FILENAMESIZE];
+#endif /* not TRILIBRARY */
+
+/* Triangular bounding box points.                                           */
+
+point infpoint1, infpoint2, infpoint3;
+
+/* Pointer to the `triangle' that occupies all of "outer space".             */
+
+triangle *dummytri;
+triangle *dummytribase;      /* Keep base address so we can free() it later. */
+
+/* Pointer to the omnipresent shell edge.  Referenced by any triangle or     */
+/*   shell edge that isn't really connected to a shell edge at that          */
+/*   location.                                                               */
+
+shelle *dummysh;
+shelle *dummyshbase;         /* Keep base address so we can free() it later. */
+
+/* Pointer to a recently visited triangle.  Improves point location if       */
+/*   proximate points are inserted sequentially.                             */
+
+struct triedge recenttri;
+
+/*****************************************************************************/
+/*                                                                           */
+/*  Mesh manipulation primitives.  Each triangle contains three pointers to  */
+/*  other triangles, with orientations.  Each pointer points not to the      */
+/*  first byte of a triangle, but to one of the first three bytes of a       */
+/*  triangle.  It is necessary to extract both the triangle itself and the   */
+/*  orientation.  To save memory, I keep both pieces of information in one   */
+/*  pointer.  To make this possible, I assume that all triangles are aligned */
+/*  to four-byte boundaries.  The `decode' routine below decodes a pointer,  */
+/*  extracting an orientation (in the range 0 to 2) and a pointer to the     */
+/*  beginning of a triangle.  The `encode' routine compresses a pointer to a */
+/*  triangle and an orientation into a single pointer.  My assumptions that  */
+/*  triangles are four-byte-aligned and that the `unsigned long' type is     */
+/*  long enough to hold a pointer are two of the few kludges in this program.*/
+/*                                                                           */
+/*  Shell edges are manipulated similarly.  A pointer to a shell edge        */
+/*  carries both an address and an orientation in the range 0 to 1.          */
+/*                                                                           */
+/*  The other primitives take an oriented triangle or oriented shell edge,   */
+/*  and return an oriented triangle or oriented shell edge or point; or they */
+/*  change the connections in the data structure.                            */
+/*                                                                           */
+/*****************************************************************************/
+
+/********* Mesh manipulation primitives begin here                   *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/* Fast lookup arrays to speed some of the mesh manipulation primitives.     */
+
+int plus1mod3[3] = {1, 2, 0};
+int minus1mod3[3] = {2, 0, 1};
+
+/********* Primitives for triangles                                  *********/
+/*                                                                           */
+/*                                                                           */
+
+/* decode() converts a pointer to an oriented triangle.  The orientation is  */
+/*   extracted from the two least significant bits of the pointer.           */
+
+#define decode(ptr, triedge)                                                  \
+  (triedge).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l);      \
+  (triedge).tri = (triangle *)                                                \
+                  ((unsigned long) (ptr) ^ (unsigned long) (triedge).orient)
+
+/* encode() compresses an oriented triangle into a single pointer.  It       */
+/*   relies on the assumption that all triangles are aligned to four-byte    */
+/*   boundaries, so the two least significant bits of (triedge).tri are zero.*/
+
+#define encode(triedge)                                                       \
+  (triangle) ((unsigned long) (triedge).tri | (unsigned long) (triedge).orient)
+
+/* The following edge manipulation primitives are all described by Guibas    */
+/*   and Stolfi.  However, they use an edge-based data structure, whereas I  */
+/*   am using a triangle-based data structure.                               */
+
+/* sym() finds the abutting triangle, on the same edge.  Note that the       */
+/*   edge direction is necessarily reversed, because triangle/edge handles   */
+/*   are always directed counterclockwise around the triangle.               */
+
+#define sym(triedge1, triedge2)                                               \
+  ptr = (triedge1).tri[(triedge1).orient];                                    \
+  decode(ptr, triedge2);
+
+#define symself(triedge)                                                      \
+  ptr = (triedge).tri[(triedge).orient];                                      \
+  decode(ptr, triedge);
+
+/* lnext() finds the next edge (counterclockwise) of a triangle.             */
+
+#define lnext(triedge1, triedge2)                                             \
+  (triedge2).tri = (triedge1).tri;                                            \
+  (triedge2).orient = plus1mod3[(triedge1).orient]
+
+#define lnextself(triedge)                                                    \
+  (triedge).orient = plus1mod3[(triedge).orient]
+
+/* lprev() finds the previous edge (clockwise) of a triangle.                */
+
+#define lprev(triedge1, triedge2)                                             \
+  (triedge2).tri = (triedge1).tri;                                            \
+  (triedge2).orient = minus1mod3[(triedge1).orient]
+
+#define lprevself(triedge)                                                    \
+  (triedge).orient = minus1mod3[(triedge).orient]
+
+/* onext() spins counterclockwise around a point; that is, it finds the next */
+/*   edge with the same origin in the counterclockwise direction.  This edge */
+/*   will be part of a different triangle.                                   */
+
+#define onext(triedge1, triedge2)                                             \
+  lprev(triedge1, triedge2);                                                  \
+  symself(triedge2);
+
+#define onextself(triedge)                                                    \
+  lprevself(triedge);                                                         \
+  symself(triedge);
+
+/* oprev() spins clockwise around a point; that is, it finds the next edge   */
+/*   with the same origin in the clockwise direction.  This edge will be     */
+/*   part of a different triangle.                                           */
+
+#define oprev(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lnextself(triedge2);
+
+#define oprevself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lnextself(triedge);
+
+/* dnext() spins counterclockwise around a point; that is, it finds the next */
+/*   edge with the same destination in the counterclockwise direction.  This */
+/*   edge will be part of a different triangle.                              */
+
+#define dnext(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lprevself(triedge2);
+
+#define dnextself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lprevself(triedge);
+
+/* dprev() spins clockwise around a point; that is, it finds the next edge   */
+/*   with the same destination in the clockwise direction.  This edge will   */
+/*   be part of a different triangle.                                        */
+
+#define dprev(triedge1, triedge2)                                             \
+  lnext(triedge1, triedge2);                                                  \
+  symself(triedge2);
+
+#define dprevself(triedge)                                                    \
+  lnextself(triedge);                                                         \
+  symself(triedge);
+
+/* rnext() moves one edge counterclockwise about the adjacent triangle.      */
+/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
+/*   changing triangles twice.)                                              */
+
+#define rnext(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lnextself(triedge2);                                                        \
+  symself(triedge2);
+
+#define rnextself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lnextself(triedge);                                                         \
+  symself(triedge);
+
+/* rnext() moves one edge clockwise about the adjacent triangle.             */
+/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
+/*   changing triangles twice.)                                              */
+
+#define rprev(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lprevself(triedge2);                                                        \
+  symself(triedge2);
+
+#define rprevself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lprevself(triedge);                                                         \
+  symself(triedge);
+
+/* These primitives determine or set the origin, destination, or apex of a   */
+/* triangle.                                                                 */
+
+#define org(triedge, pointptr)                                                \
+  pointptr = (point) (triedge).tri[plus1mod3[(triedge).orient] + 3]
+
+#define dest(triedge, pointptr)                                               \
+  pointptr = (point) (triedge).tri[minus1mod3[(triedge).orient] + 3]
+
+#define apex(triedge, pointptr)                                               \
+  pointptr = (point) (triedge).tri[(triedge).orient + 3]
+
+#define setorg(triedge, pointptr)                                             \
+  (triedge).tri[plus1mod3[(triedge).orient] + 3] = (triangle) pointptr
+
+#define setdest(triedge, pointptr)                                            \
+  (triedge).tri[minus1mod3[(triedge).orient] + 3] = (triangle) pointptr
+
+#define setapex(triedge, pointptr)                                            \
+  (triedge).tri[(triedge).orient + 3] = (triangle) pointptr
+
+#define setvertices2null(triedge)                                             \
+  (triedge).tri[3] = (triangle) NULL;                                         \
+  (triedge).tri[4] = (triangle) NULL;                                         \
+  (triedge).tri[5] = (triangle) NULL;
+
+/* Bond two triangles together.                                              */
+
+#define bond(triedge1, triedge2)                                              \
+  (triedge1).tri[(triedge1).orient] = encode(triedge2);                       \
+  (triedge2).tri[(triedge2).orient] = encode(triedge1)
+
+/* Dissolve a bond (from one side).  Note that the other triangle will still */
+/*   think it's connected to this triangle.  Usually, however, the other     */
+/*   triangle is being deleted entirely, or bonded to another triangle, so   */
+/*   it doesn't matter.                                                      */
+
+#define dissolve(triedge)                                                     \
+  (triedge).tri[(triedge).orient] = (triangle) dummytri
+
+/* Copy a triangle/edge handle.                                              */
+
+#define triedgecopy(triedge1, triedge2)                                       \
+  (triedge2).tri = (triedge1).tri;                                            \
+  (triedge2).orient = (triedge1).orient
+
+/* Test for equality of triangle/edge handles.                               */
+
+#define triedgeequal(triedge1, triedge2)                                      \
+  (((triedge1).tri == (triedge2).tri) &&                                      \
+   ((triedge1).orient == (triedge2).orient))
+
+/* Primitives to infect or cure a triangle with the virus.  These rely on    */
+/*   the assumption that all shell edges are aligned to four-byte boundaries.*/
+
+#define infect(triedge)                                                       \
+  (triedge).tri[6] = (triangle)                                               \
+                     ((unsigned long) (triedge).tri[6] | (unsigned long) 2l)
+
+#define uninfect(triedge)                                                     \
+  (triedge).tri[6] = (triangle)                                               \
+                     ((unsigned long) (triedge).tri[6] & ~ (unsigned long) 2l)
+
+/* Test a triangle for viral infection.                                      */
+
+#define infected(triedge)                                                     \
+  (((unsigned long) (triedge).tri[6] & (unsigned long) 2l) != 0)
+
+/* Check or set a triangle's attributes.                                     */
+
+#define elemattribute(triedge, attnum)                                        \
+  ((REAL *) (triedge).tri)[elemattribindex + (attnum)]
+
+#define setelemattribute(triedge, attnum, value)                              \
+  ((REAL *) (triedge).tri)[elemattribindex + (attnum)] = value
+
+/* Check or set a triangle's maximum area bound.                             */
+
+#define areabound(triedge)  ((REAL *) (triedge).tri)[areaboundindex]
+
+#define setareabound(triedge, value)                                          \
+  ((REAL *) (triedge).tri)[areaboundindex] = value
+
+/********* Primitives for shell edges                                *********/
+/*                                                                           */
+/*                                                                           */
+
+/* sdecode() converts a pointer to an oriented shell edge.  The orientation  */
+/*   is extracted from the least significant bit of the pointer.  The two    */
+/*   least significant bits (one for orientation, one for viral infection)   */
+/*   are masked out to produce the real pointer.                             */
+
+#define sdecode(sptr, edge)                                                   \
+  (edge).shorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l);      \
+  (edge).sh = (shelle *)                                                      \
+              ((unsigned long) (sptr) & ~ (unsigned long) 3l)
+
+/* sencode() compresses an oriented shell edge into a single pointer.  It    */
+/*   relies on the assumption that all shell edges are aligned to two-byte   */
+/*   boundaries, so the least significant bit of (edge).sh is zero.          */
+
+#define sencode(edge)                                                         \
+  (shelle) ((unsigned long) (edge).sh | (unsigned long) (edge).shorient)
+
+/* ssym() toggles the orientation of a shell edge.                           */
+
+#define ssym(edge1, edge2)                                                    \
+  (edge2).sh = (edge1).sh;                                                    \
+  (edge2).shorient = 1 - (edge1).shorient
+
+#define ssymself(edge)                                                        \
+  (edge).shorient = 1 - (edge).shorient
+
+/* spivot() finds the other shell edge (from the same segment) that shares   */
+/*   the same origin.                                                        */
+
+#define spivot(edge1, edge2)                                                  \
+  sptr = (edge1).sh[(edge1).shorient];                                        \
+  sdecode(sptr, edge2)
+
+#define spivotself(edge)                                                      \
+  sptr = (edge).sh[(edge).shorient];                                          \
+  sdecode(sptr, edge)
+
+/* snext() finds the next shell edge (from the same segment) in sequence;    */
+/*   one whose origin is the input shell edge's destination.                 */
+
+#define snext(edge1, edge2)                                                   \
+  sptr = (edge1).sh[1 - (edge1).shorient];                                    \
+  sdecode(sptr, edge2)
+
+#define snextself(edge)                                                       \
+  sptr = (edge).sh[1 - (edge).shorient];                                      \
+  sdecode(sptr, edge)
+
+/* These primitives determine or set the origin or destination of a shell    */
+/*   edge.                                                                   */
+
+#define sorg(edge, pointptr)                                                  \
+  pointptr = (point) (edge).sh[2 + (edge).shorient]
+
+#define sdest(edge, pointptr)                                                 \
+  pointptr = (point) (edge).sh[3 - (edge).shorient]
+
+#define setsorg(edge, pointptr)                                               \
+  (edge).sh[2 + (edge).shorient] = (shelle) pointptr
+
+#define setsdest(edge, pointptr)                                              \
+  (edge).sh[3 - (edge).shorient] = (shelle) pointptr
+
+/* These primitives read or set a shell marker.  Shell markers are used to   */
+/*   hold user boundary information.                                         */
+
+#define mark(edge)  (* (int *) ((edge).sh + 6))
+
+#define setmark(edge, value)                                                  \
+  * (int *) ((edge).sh + 6) = value
+
+/* Bond two shell edges together.                                            */
+
+#define sbond(edge1, edge2)                                                   \
+  (edge1).sh[(edge1).shorient] = sencode(edge2);                              \
+  (edge2).sh[(edge2).shorient] = sencode(edge1)
+
+/* Dissolve a shell edge bond (from one side).  Note that the other shell    */
+/*   edge will still think it's connected to this shell edge.                */
+
+#define sdissolve(edge)                                                       \
+  (edge).sh[(edge).shorient] = (shelle) dummysh
+
+/* Copy a shell edge.                                                        */
+
+#define shellecopy(edge1, edge2)                                              \
+  (edge2).sh = (edge1).sh;                                                    \
+  (edge2).shorient = (edge1).shorient
+
+/* Test for equality of shell edges.                                         */
+
+#define shelleequal(edge1, edge2)                                             \
+  (((edge1).sh == (edge2).sh) &&                                              \
+   ((edge1).shorient == (edge2).shorient))
+
+/********* Primitives for interacting triangles and shell edges      *********/
+/*                                                                           */
+/*                                                                           */
+
+/* tspivot() finds a shell edge abutting a triangle.                         */
+
+#define tspivot(triedge, edge)                                                \
+  sptr = (shelle) (triedge).tri[6 + (triedge).orient];                        \
+  sdecode(sptr, edge)
+
+/* stpivot() finds a triangle abutting a shell edge.  It requires that the   */
+/*   variable `ptr' of type `triangle' be defined.                           */
+
+#define stpivot(edge, triedge)                                                \
+  ptr = (triangle) (edge).sh[4 + (edge).shorient];                            \
+  decode(ptr, triedge)
+
+/* Bond a triangle to a shell edge.                                          */
+
+#define tsbond(triedge, edge)                                                 \
+  (triedge).tri[6 + (triedge).orient] = (triangle) sencode(edge);             \
+  (edge).sh[4 + (edge).shorient] = (shelle) encode(triedge)
+
+/* Dissolve a bond (from the triangle side).                                 */
+
+#define tsdissolve(triedge)                                                   \
+  (triedge).tri[6 + (triedge).orient] = (triangle) dummysh
+
+/* Dissolve a bond (from the shell edge side).                               */
+
+#define stdissolve(edge)                                                      \
+  (edge).sh[4 + (edge).shorient] = (shelle) dummytri
+
+/********* Primitives for points                                     *********/
+/*                                                                           */
+/*                                                                           */
+
+#define pointmark(pt)  ((int *) (pt))[pointmarkindex]
+
+#define setpointmark(pt, value)                                               \
+  ((int *) (pt))[pointmarkindex] = value
+
+#define point2tri(pt)  ((triangle *) (pt))[point2triindex]
+
+#define setpoint2tri(pt, value)                                               \
+  ((triangle *) (pt))[point2triindex] = value
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh manipulation primitives end here                     *********/
+
+/********* User interaction routines begin here                      *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  syntax()   Print list of command line switches.                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void syntax()
+{
+#ifdef CDT_ONLY
+#ifdef REDUCED
+  printf("triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n");
+#else /* not REDUCED */
+  printf("triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n");
+#endif /* not REDUCED */
+#else /* not CDT_ONLY */
+#ifdef REDUCED
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n");
+#else /* not REDUCED */
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
+#endif /* not REDUCED */
+#endif /* not CDT_ONLY */
+
+  printf("    -p  Triangulates a Planar Straight Line Graph (.poly file).\n");
+#ifndef CDT_ONLY
+  printf("    -r  Refines a previously generated mesh.\n");
+  printf(
+    "    -q  Quality mesh generation.  A minimum angle may be specified.\n");
+  printf("    -a  Applies a maximum triangle area constraint.\n");
+#endif /* not CDT_ONLY */
+  printf(
+    "    -A  Applies attributes to identify elements in certain regions.\n");
+  printf("    -c  Encloses the convex hull with segments.\n");
+  printf("    -e  Generates an edge list.\n");
+  printf("    -v  Generates a Voronoi diagram.\n");
+  printf("    -n  Generates a list of triangle neighbors.\n");
+  printf("    -g  Generates an .off file for Geomview.\n");
+  printf("    -B  Suppresses output of boundary information.\n");
+  printf("    -P  Suppresses output of .poly file.\n");
+  printf("    -N  Suppresses output of .node file.\n");
+  printf("    -E  Suppresses output of .ele file.\n");
+  printf("    -I  Suppresses mesh iteration numbers.\n");
+  printf("    -O  Ignores holes in .poly file.\n");
+  printf("    -X  Suppresses use of exact arithmetic.\n");
+  printf("    -z  Numbers all items starting from zero (rather than one).\n");
+  printf("    -o2 Generates second-order subparametric elements.\n");
+#ifndef CDT_ONLY
+  printf("    -Y  Suppresses boundary segment splitting.\n");
+  printf("    -S  Specifies maximum number of added Steiner points.\n");
+#endif /* not CDT_ONLY */
+#ifndef REDUCED
+  printf("    -i  Uses incremental method, rather than divide-and-conquer.\n");
+  printf("    -F  Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
+#endif /* not REDUCED */
+  printf("    -l  Uses vertical cuts only, rather than alternating cuts.\n");
+#ifndef REDUCED
+#ifndef CDT_ONLY
+  printf(
+    "    -s  Force segments into mesh by splitting (instead of using CDT).\n");
+#endif /* not CDT_ONLY */
+  printf("    -C  Check consistency of final mesh.\n");
+#endif /* not REDUCED */
+  printf("    -Q  Quiet:  No terminal output except errors.\n");
+  printf("    -V  Verbose:  Detailed information on what I'm doing.\n");
+  printf("    -h  Help:  Detailed instructions for Triangle.\n");
+  exit(0);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  info()   Print out complete instructions.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void info()
+{
+  printf("Triangle\n");
+  printf(
+"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\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 /* not SINGLE */
+  printf("This executable is compiled for double precision arithmetic.\n\n\n");
+#endif /* not SINGLE */
+  printf(
+"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
+  printf(
+"triangulations, and quality conforming Delaunay triangulations.  The latter\n"
+);
+  printf(
+"can be generated with no small angles, and are thus suitable for finite\n");
+  printf(
+"element analysis.  If no command line switches are specified, your .node\n");
+  printf(
+"input file will be read, and the Delaunay triangulation will be returned in\n"
+);
+  printf(".node and .ele output files.  The command syntax is:\n\n");
+#ifdef CDT_ONLY
+#ifdef REDUCED
+  printf("triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n\n");
+#else /* not REDUCED */
+  printf("triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n\n");
+#endif /* not REDUCED */
+#else /* not CDT_ONLY */
+#ifdef REDUCED
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n\n");
+#else /* not REDUCED */
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
+#endif /* not REDUCED */
+#endif /* not CDT_ONLY */
+  printf(
+"Underscores indicate that numbers may optionally follow certain switches;\n");
+  printf(
+"do not leave any space between a switch and its numeric parameter.\n");
+  printf(
+"input_file must be a file with extension .node, or extension .poly if the\n");
+  printf(
+"-p switch is used.  If -r is used, you must supply .node and .ele files,\n");
+  printf(
+"and possibly a .poly file and .area file as well.  The formats of these\n");
+  printf("files are described below.\n\n");
+  printf("Command Line Switches:\n\n");
+  printf(
+"    -p  Reads a Planar Straight Line Graph (.poly file), which can specify\n"
+);
+  printf(
+"        points, segments, holes, and regional attributes and area\n");
+  printf(
+"        constraints.  Will generate a constrained Delaunay triangulation\n");
+  printf(
+"        fitting the input; or, if -s, -q, or -a is used, a conforming\n");
+  printf(
+"        Delaunay triangulation.  If -p is not used, Triangle reads a .node\n"
+);
+  printf("        file by default.\n");
+  printf(
+"    -r  Refines a previously generated mesh.  The mesh is read from a .node\n"
+);
+  printf(
+"        file and an .ele file.  If -p is also used, a .poly file is read\n");
+  printf(
+"        and used to constrain edges in the mesh.  Further details on\n");
+  printf("        refinement are given below.\n");
+  printf(
+"    -q  Quality mesh generation by Jim Ruppert's Delaunay refinement\n");
+  printf(
+"        algorithm.  Adds points to the mesh to ensure that no angles\n");
+  printf(
+"        smaller than 20 degrees occur.  An alternative minimum angle may be\n"
+);
+  printf(
+"        specified after the `q'.  If the minimum angle is 20.7 degrees or\n");
+  printf(
+"        smaller, the triangulation algorithm is theoretically guaranteed to\n"
+);
+  printf(
+"        terminate (assuming infinite precision arithmetic - Triangle may\n");
+  printf(
+"        fail to terminate if you run out of precision).  In practice, the\n");
+  printf(
+"        algorithm often succeeds for minimum angles up to 33.8 degrees.\n");
+  printf(
+"        For highly refined meshes, however, it may be necessary to reduce\n");
+  printf(
+"        the minimum angle to well below 20 to avoid problems associated\n");
+  printf(
+"        with insufficient floating-point precision.  The specified angle\n");
+  printf("        may include a decimal point.\n");
+  printf(
+"    -a  Imposes a maximum triangle area.  If a number follows the `a', no\n");
+  printf(
+"        triangle will be generated whose area is larger than that number.\n");
+  printf(
+"        If no number is specified, an .area file (if -r is used) or .poly\n");
+  printf(
+"        file (if -r is not used) specifies a number of maximum area\n");
+  printf(
+"        constraints.  An .area file contains a separate area constraint for\n"
+);
+  printf(
+"        each triangle, and is useful for refining a finite element mesh\n");
+  printf(
+"        based on a posteriori error estimates.  A .poly file can optionally\n"
+);
+  printf(
+"        contain an area constraint for each segment-bounded region, thereby\n"
+);
+  printf(
+"        enforcing triangle densities in a first triangulation.  You can\n");
+  printf(
+"        impose both a fixed area constraint and a varying area constraint\n");
+  printf(
+"        by invoking the -a switch twice, once with and once without a\n");
+  printf(
+"        number following.  Each area specified may include a decimal point.\n"
+);
+  printf(
+"    -A  Assigns an additional attribute to each triangle that identifies\n");
+  printf(
+"        what segment-bounded region each triangle belongs to.  Attributes\n");
+  printf(
+"        are assigned to regions by the .poly file.  If a region is not\n");
+  printf(
+"        explicitly marked by the .poly file, triangles in that region are\n");
+  printf(
+"        assigned an attribute of zero.  The -A switch has an effect only\n");
+  printf("        when the -p switch is used and the -r switch is not.\n");
+  printf(
+"    -c  Creates segments on the convex hull of the triangulation.  If you\n");
+  printf(
+"        are triangulating a point set, this switch causes a .poly file to\n");
+  printf(
+"        be written, containing all edges in the convex hull.  (By default,\n"
+);
+  printf(
+"        a .poly file is written only if a .poly file is read.)  If you are\n"
+);
+  printf(
+"        triangulating a PSLG, this switch specifies that the interior of\n");
+  printf(
+"        the convex hull of the PSLG should be triangulated.  If you do not\n"
+);
+  printf(
+"        use this switch when triangulating a PSLG, it is assumed that you\n");
+  printf(
+"        have identified the region to be triangulated by surrounding it\n");
+  printf(
+"        with segments of the input PSLG.  Beware:  if you are not careful,\n"
+);
+  printf(
+"        this switch can cause the introduction of an extremely thin angle\n");
+  printf(
+"        between a PSLG segment and a convex hull segment, which can cause\n");
+  printf(
+"        overrefinement or failure if Triangle runs out of precision.  If\n");
+  printf(
+"        you are refining a mesh, the -c switch works differently; it\n");
+  printf(
+"        generates the set of boundary edges of the mesh, rather than the\n");
+  printf("        convex hull.\n");
+  printf(
+"    -e  Outputs (to an .edge file) a list of edges of the triangulation.\n");
+  printf(
+"    -v  Outputs the Voronoi diagram associated with the triangulation.\n");
+  printf("        Does not attempt to detect degeneracies.\n");
+  printf(
+"    -n  Outputs (to a .neigh file) a list of triangles neighboring each\n");
+  printf("        triangle.\n");
+  printf(
+"    -g  Outputs the mesh to an Object File Format (.off) file, suitable for\n"
+);
+  printf("        viewing with the Geometry Center's Geomview package.\n");
+  printf(
+"    -B  No boundary markers in the output .node, .poly, and .edge output\n");
+  printf(
+"        files.  See the detailed discussion of boundary markers below.\n");
+  printf(
+"    -P  No output .poly file.  Saves disk space, but you lose the ability\n");
+  printf(
+"        to impose segment constraints on later refinements of the mesh.\n");
+  printf("    -N  No output .node file.\n");
+  printf("    -E  No output .ele file.\n");
+  printf(
+"    -I  No iteration numbers.  Suppresses the output of .node and .poly\n");
+  printf(
+"        files, so your input files won't be overwritten.  (If your input is\n"
+);
+  printf(
+"        a .poly file only, a .node file will be written.)  Cannot be used\n");
+  printf(
+"        with the -r switch, because that would overwrite your input .ele\n");
+  printf(
+"        file.  Shouldn't be used with the -s, -q, or -a switch if you are\n");
+  printf(
+"        using a .node file for input, because no .node file will be\n");
+  printf("        written, so there will be no record of any added points.\n");
+  printf("    -O  No holes.  Ignores the holes in the .poly file.\n");
+  printf(
+"    -X  No exact arithmetic.  Normally, Triangle uses exact floating-point\n"
+);
+  printf(
+"        arithmetic for certain tests if it thinks the inexact tests are not\n"
+);
+  printf(
+"        accurate enough.  Exact arithmetic ensures the robustness of the\n");
+  printf(
+"        triangulation algorithms, despite floating-point roundoff error.\n");
+  printf(
+"        Disabling exact arithmetic with the -X switch will cause a small\n");
+  printf(
+"        improvement in speed and create the possibility (albeit small) that\n"
+);
+  printf(
+"        Triangle will fail to produce a valid mesh.  Not recommended.\n");
+  printf(
+"    -z  Numbers all items starting from zero (rather than one).  Note that\n"
+);
+  printf(
+"        this switch is normally overrided by the value used to number the\n");
+  printf(
+"        first point of the input .node or .poly file.  However, this switch\n"
+);
+  printf("        is useful when calling Triangle from another program.\n");
+  printf(
+"    -o2 Generates second-order subparametric elements with six nodes each.\n"
+);
+  printf(
+"    -Y  No new points on the boundary.  This switch is useful when the mesh\n"
+);
+  printf(
+"        boundary must be preserved so that it conforms to some adjacent\n");
+  printf(
+"        mesh.  Be forewarned that you will probably sacrifice some of the\n");
+  printf(
+"        quality of the mesh; Triangle will try, but the resulting mesh may\n"
+);
+  printf(
+"        contain triangles of poor aspect ratio.  Works well if all the\n");
+  printf(
+"        boundary points are closely spaced.  Specify this switch twice\n");
+  printf(
+"        (`-YY') to prevent all segment splitting, including internal\n");
+  printf("        boundaries.\n");
+  printf(
+"    -S  Specifies the maximum number of Steiner points (points that are not\n"
+);
+  printf(
+"        in the input, but are added to meet the constraints of minimum\n");
+  printf(
+"        angle and maximum area).  The default is to allow an unlimited\n");
+  printf(
+"        number.  If you specify this switch with no number after it,\n");
+  printf(
+"        the limit is set to zero.  Triangle always adds points at segment\n");
+  printf(
+"        intersections, even if it needs to use more points than the limit\n");
+  printf(
+"        you set.  When Triangle inserts segments by splitting (-s), it\n");
+  printf(
+"        always adds enough points to ensure that all the segments appear in\n"
+);
+  printf(
+"        the triangulation, again ignoring the limit.  Be forewarned that\n");
+  printf(
+"        the -S switch may result in a conforming triangulation that is not\n"
+);
+  printf(
+"        truly Delaunay, because Triangle may be forced to stop adding\n");
+  printf(
+"        points when the mesh is in a state where a segment is non-Delaunay\n"
+);
+  printf(
+"        and needs to be split.  If so, Triangle will print a warning.\n");
+  printf(
+"    -i  Uses an incremental rather than divide-and-conquer algorithm to\n");
+  printf(
+"        form a Delaunay triangulation.  Try it if the divide-and-conquer\n");
+  printf("        algorithm fails.\n");
+  printf(
+"    -F  Uses Steven Fortune's sweepline algorithm to form a Delaunay\n");
+  printf(
+"        triangulation.  Warning:  does not use exact arithmetic for all\n");
+  printf("        calculations.  An exact result is not guaranteed.\n");
+  printf(
+"    -l  Uses only vertical cuts in the divide-and-conquer algorithm.  By\n");
+  printf(
+"        default, Triangle uses alternating vertical and horizontal cuts,\n");
+  printf(
+"        which usually improve the speed except with point sets that are\n");
+  printf(
+"        small or short and wide.  This switch is primarily of theoretical\n");
+  printf("        interest.\n");
+  printf(
+"    -s  Specifies that segments should be forced into the triangulation by\n"
+);
+  printf(
+"        recursively splitting them at their midpoints, rather than by\n");
+  printf(
+"        generating a constrained Delaunay triangulation.  Segment splitting\n"
+);
+  printf(
+"        is true to Ruppert's original algorithm, but can create needlessly\n"
+);
+  printf("        small triangles near external small features.\n");
+  printf(
+"    -C  Check the consistency of the final mesh.  Uses exact arithmetic for\n"
+);
+  printf(
+"        checking, even if the -X switch is used.  Useful if you suspect\n");
+  printf("        Triangle is buggy.\n");
+  printf(
+"    -Q  Quiet: Suppresses all explanation of what Triangle is doing, unless\n"
+);
+  printf("        an error occurs.\n");
+  printf(
+"    -V  Verbose: Gives detailed information about what Triangle is doing.\n");
+  printf(
+"        Add more `V's for increasing amount of detail.  `-V' gives\n");
+  printf(
+"        information on algorithmic progress and more detailed statistics.\n");
+  printf(
+"        `-VV' gives point-by-point details, and will print so much that\n");
+  printf(
+"        Triangle will run much more slowly.  `-VVV' gives information only\n"
+);
+  printf("        a debugger could love.\n");
+  printf("    -h  Help:  Displays these instructions.\n");
+  printf("\n");
+  printf("Definitions:\n");
+  printf("\n");
+  printf(
+"  A Delaunay triangulation of a point set is a triangulation whose vertices\n"
+);
+  printf(
+"  are the point set, having the property that no point in the point set\n");
+  printf(
+"  falls in the interior of the circumcircle (circle that passes through all\n"
+);
+  printf("  three vertices) of any triangle in the triangulation.\n\n");
+  printf(
+"  A Voronoi diagram of a point set is a subdivision of the plane into\n");
+  printf(
+"  polygonal regions (some of which may be infinite), where each region is\n");
+  printf(
+"  the set of points in the plane that are closer to some input point than\n");
+  printf(
+"  to any other input point.  (The Voronoi diagram is the geometric dual of\n"
+);
+  printf("  the Delaunay triangulation.)\n\n");
+  printf(
+"  A Planar Straight Line Graph (PSLG) is a collection of points and\n");
+  printf(
+"  segments.  Segments are simply edges, whose endpoints are points in the\n");
+  printf(
+"  PSLG.  The file format for PSLGs (.poly files) is described below.\n");
+  printf("\n");
+  printf(
+"  A constrained Delaunay triangulation of a PSLG is similar to a Delaunay\n");
+  printf(
+"  triangulation, but each PSLG segment is present as a single edge in the\n");
+  printf(
+"  triangulation.  (A constrained Delaunay triangulation is not truly a\n");
+  printf("  Delaunay triangulation.)\n\n");
+  printf(
+"  A conforming Delaunay triangulation of a PSLG is a true Delaunay\n");
+  printf(
+"  triangulation in which each PSLG segment may have been subdivided into\n");
+  printf(
+"  several edges by the insertion of additional points.  These inserted\n");
+  printf(
+"  points are necessary to allow the segments to exist in the mesh while\n");
+  printf("  maintaining the Delaunay property.\n\n");
+  printf("File Formats:\n\n");
+  printf(
+"  All files may contain comments prefixed by the character '#'.  Points,\n");
+  printf(
+"  triangles, edges, holes, and maximum area constraints must be numbered\n");
+  printf(
+"  consecutively, starting from either 1 or 0.  Whichever you choose, all\n");
+  printf(
+"  input files must be consistent; if the nodes are numbered from 1, so must\n"
+);
+  printf(
+"  be all other objects.  Triangle automatically detects your choice while\n");
+  printf(
+"  reading the .node (or .poly) file.  (When calling Triangle from another\n");
+  printf(
+"  program, use the -z switch if you wish to number objects from zero.)\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 copied unchanged to the output mesh.  If -s,\n"
+);
+  printf(
+"    -q, or -a is selected, each new Steiner point added to the mesh will\n");
+  printf("    have attributes assigned to it by linear interpolation.\n\n");
+  printf(
+"    If the fourth entry of the first line is `1', the last column of the\n");
+  printf(
+"    remainder of the file is assumed to contain boundary markers.  Boundary\n"
+);
+  printf(
+"    markers are used to identify boundary points and points resting on PSLG\n"
+);
+  printf(
+"    segments; a complete description appears in a section below.  The .node\n"
+);
+  printf(
+"    file produced by Triangle will contain boundary markers in the last\n");
+  printf("    column unless they are suppressed by the -B switch.\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.  The first three\n"
+);
+  printf(
+"    points are the corners, and are listed in counterclockwise order around\n"
+);
+  printf(
+"    each triangle.  (The remaining points, if any, depend on the type of\n");
+  printf(
+"    finite element used.)  The attributes are just like those of .node\n");
+  printf(
+"    files.  Because there is no simple mapping from input to output\n");
+  printf(
+"    triangles, an attempt is made to interpolate attributes, which may\n");
+  printf(
+"    result in a good deal of diffusion of attributes among nearby triangles\n"
+);
+  printf(
+"    as the triangulation is refined.  Diffusion does not occur across\n");
+  printf(
+"    segments, so attributes used to identify segment-bounded regions remain\n"
+);
+  printf(
+"    intact.  In output .ele files, all triangles have three points each\n");
+  printf(
+"    unless the -o2 switch is used, in which case they have six, and the\n");
+  printf(
+"    fourth, fifth, and sixth points lie on the midpoints of the edges\n");
+  printf("    opposite the first, second, and third corners.\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 line:  <# of regional attributes and/or area constraints>\n");
+  printf(
+"    Optional following lines:  <constraint #> <x> <y> <attrib> <max area>\n");
+  printf("\n");
+  printf(
+"    A .poly file represents a PSLG, as well as some additional information.\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.  This has the advantage that a point\n"
+);
+  printf(
+"    set may easily be triangulated with or without segments.  (The same\n");
+  printf(
+"    effect can be achieved, albeit using more disk space, by making a copy\n"
+);
+  printf(
+"    of the .poly file with the extension .node; all sections of the file\n");
+  printf("    but the first are ignored.)\n\n");
+  printf(
+"    The second section lists the segments.  Segments are edges whose\n");
+  printf(
+"    presence in the triangulation is enforced.  Each segment is specified\n");
+  printf(
+"    by listing the indices of its two endpoints.  This means that you must\n"
+);
+  printf(
+"    include its endpoints in the point list.  If -s, -q, and -a are not\n");
+  printf(
+"    selected, Triangle will produce a constrained Delaunay triangulation,\n");
+  printf(
+"    in which each segment appears as a single edge in the triangulation.\n");
+  printf(
+"    If -q or -a is selected, Triangle will produce a conforming Delaunay\n");
+  printf(
+"    triangulation, in which segments may be subdivided into smaller edges.\n"
+);
+  printf("    Each segment, like each point, may have a boundary marker.\n\n");
+  printf(
+"    The third section lists holes (and concavities, if -c is selected) in\n");
+  printf(
+"    the triangulation.  Holes are specified by identifying a point inside\n");
+  printf(
+"    each hole.  After the triangulation is formed, Triangle creates holes\n");
+  printf(
+"    by eating triangles, spreading out from each hole point until its\n");
+  printf(
+"    progress is blocked by PSLG segments; you must be careful to enclose\n");
+  printf(
+"    each hole in segments, or your whole triangulation may be eaten away.\n");
+  printf(
+"    If the two triangles abutting a segment are eaten, the segment itself\n");
+  printf(
+"    is also eaten.  Do not place a hole directly on a segment; if you do,\n");
+  printf("    Triangle will choose one side of the segment arbitrarily.\n\n");
+  printf(
+"    The optional fourth section lists regional attributes (to be assigned\n");
+  printf(
+"    to all triangles in a region) and regional constraints on the maximum\n");
+  printf(
+"    triangle area.  Triangle will read this section only if the -A switch\n");
+  printf(
+"    is used or the -a switch is used without a number following it, and the\n"
+);
+  printf(
+"    -r switch is not used.  Regional attributes and area constraints are\n");
+  printf(
+"    propagated in the same manner as holes; you specify a point for each\n");
+  printf(
+"    attribute and/or constraint, and the attribute and/or constraint will\n");
+  printf(
+"    affect the whole region (bounded by segments) containing the point.  If\n"
+);
+  printf(
+"    two values are written on a line after the x and y coordinate, the\n");
+  printf(
+"    former is assumed to be a regional attribute (but will only be applied\n"
+);
+  printf(
+"    if the -A switch is selected), and the latter is assumed to be a\n");
+  printf(
+"    regional area constraint (but will only be applied if the -a switch is\n"
+);
+  printf(
+"    selected).  You may also specify just one value after the coordinates,\n"
+);
+  printf(
+"    which can serve as both an attribute and an area constraint, depending\n"
+);
+  printf(
+"    on the choice of switches.  If you are using the -A and -a switches\n");
+  printf(
+"    simultaneously and wish to assign an attribute to some region without\n");
+  printf("    imposing an area constraint, use a negative maximum area.\n\n");
+  printf(
+"    When a triangulation is created from a .poly file, you must either\n");
+  printf(
+"    enclose the entire region to be triangulated in PSLG segments, or\n");
+  printf(
+"    use the -c switch, which encloses the convex hull of the input point\n");
+  printf(
+"    set.  If you do not use the -c switch, Triangle will eat all triangles\n"
+);
+  printf(
+"    on the outer boundary that are not protected by segments; if you are\n");
+  printf(
+"    not careful, your whole triangulation may be eaten away.  If you do\n");
+  printf(
+"    use the -c switch, you can still produce concavities by appropriate\n");
+  printf("    placement of holes just inside the convex hull.\n\n");
+  printf(
+"    An ideal PSLG has no intersecting segments, nor any points that lie\n");
+  printf(
+"    upon segments (except, of course, the endpoints of each segment.)  You\n"
+);
+  printf(
+"    aren't required to make your .poly files ideal, but you should be aware\n"
+);
+  printf(
+"    of what can go wrong.  Segment intersections are relatively safe -\n");
+  printf(
+"    Triangle will calculate the intersection points for you and add them to\n"
+);
+  printf(
+"    the triangulation - as long as your machine's floating-point precision\n"
+);
+  printf(
+"    doesn't become a problem.  You are tempting the fates if you have three\n"
+);
+  printf(
+"    segments that cross at the same location, and expect Triangle to figure\n"
+);
+  printf(
+"    out where the intersection point is.  Thanks to floating-point roundoff\n"
+);
+  printf(
+"    error, Triangle will probably decide that the three segments intersect\n"
+);
+  printf(
+"    at three different points, and you will find a minuscule triangle in\n");
+  printf(
+"    your output - unless Triangle tries to refine the tiny triangle, uses\n");
+  printf(
+"    up the last bit of machine precision, and fails to terminate at all.\n");
+  printf(
+"    You're better off putting the intersection point in the input files,\n");
+  printf(
+"    and manually breaking up each segment into two.  Similarly, if you\n");
+  printf(
+"    place a point at the middle of a segment, and hope that Triangle will\n");
+  printf(
+"    break up the segment at that point, you might get lucky.  On the other\n"
+);
+  printf(
+"    hand, Triangle might decide that the point doesn't lie precisely on the\n"
+);
+  printf(
+"    line, and you'll have a needle-sharp triangle in your output - or a lot\n"
+);
+  printf("    of tiny triangles if you're generating a quality mesh.\n\n");
+  printf(
+"    When Triangle reads a .poly file, it also writes a .poly file, which\n");
+  printf(
+"    includes all edges that are part of input segments.  If the -c switch\n");
+  printf(
+"    is used, the output .poly file will also include all of the edges on\n");
+  printf(
+"    the convex hull.  Hence, the output .poly file is useful for finding\n");
+  printf(
+"    edges associated with input segments and setting boundary conditions in\n"
+);
+  printf(
+"    finite element simulations.  More importantly, you will need it if you\n"
+);
+  printf(
+"    plan to refine the output mesh, and don't want segments to be missing\n");
+  printf("    in later triangulations.\n\n");
+  printf("  .area files:\n");
+  printf("    First line:  <# of triangles>\n");
+  printf("    Following lines:  <triangle #> <maximum area>\n\n");
+  printf(
+"    An .area file associates with each triangle a maximum area that is used\n"
+);
+  printf(
+"    for mesh refinement.  As with other file formats, every triangle must\n");
+  printf(
+"    be represented, and they must be numbered consecutively.  A triangle\n");
+  printf(
+"    may be left unconstrained by assigning it a negative maximum area.\n");
+  printf("\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.  Triangle can\n"
+);
+  printf(
+"    produce .edge files (use the -e switch), but cannot read them.  The\n");
+  printf(
+"    optional column of boundary markers is suppressed by the -B switch.\n");
+  printf("\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("  .neigh files:\n");
+  printf(
+"    First line:  <# of triangles> <# of neighbors per triangle (always 3)>\n"
+);
+  printf(
+"    Following lines:  <triangle #> <neighbor> <neighbor> <neighbor>\n");
+  printf("\n");
+  printf(
+"    Neighbors are indices into the corresponding .ele file.  An index of -1\n"
+);
+  printf(
+"    indicates a mesh boundary, and therefore no neighbor.  Triangle can\n");
+  printf(
+"    produce .neigh files (use the -n switch), but cannot read them.\n");
+  printf("\n");
+  printf(
+"    The first neighbor of triangle i is opposite the first corner of\n");
+  printf("    triangle i, and so on.\n\n");
+  printf("Boundary Markers:\n\n");
+  printf(
+"  Boundary markers are tags used mainly to identify which output points and\n"
+);
+  printf(
+"  edges are associated with which PSLG segment, and to identify which\n");
+  printf(
+"  points and edges occur on a boundary of the triangulation.  A common use\n"
+);
+  printf(
+"  is to determine where boundary conditions should be applied to a finite\n");
+  printf(
+"  element mesh.  You can prevent boundary markers from being written into\n");
+  printf("  files produced by Triangle by using the -B switch.\n\n");
+  printf(
+"  The boundary marker associated with each segment in an output .poly file\n"
+);
+  printf("  or edge in an output .edge file is chosen as follows:\n");
+  printf(
+"    - If an output edge is part or all of a PSLG segment with a nonzero\n");
+  printf(
+"      boundary marker, then the edge is assigned the same marker.\n");
+  printf(
+"    - Otherwise, if the edge occurs on a boundary of the triangulation\n");
+  printf(
+"      (including boundaries of holes), then the edge is assigned the marker\n"
+);
+  printf("      one (1).\n");
+  printf("    - Otherwise, the edge is assigned the marker zero (0).\n");
+  printf(
+"  The boundary marker associated with each point in an output .node file is\n"
+);
+  printf("  chosen as follows:\n");
+  printf(
+"    - If a point is assigned a nonzero boundary marker in the input file,\n");
+  printf(
+"      then it is assigned the same marker in the output .node file.\n");
+  printf(
+"    - Otherwise, if the point lies on a PSLG segment (including the\n");
+  printf(
+"      segment's endpoints) with a nonzero boundary marker, then the point\n");
+  printf(
+"      is assigned the same marker.  If the point lies on several such\n");
+  printf("      segments, one of the markers is chosen arbitrarily.\n");
+  printf(
+"    - Otherwise, if the point occurs on a boundary of the triangulation,\n");
+  printf("      then the point is assigned the marker one (1).\n");
+  printf("    - Otherwise, the point is assigned the marker zero (0).\n");
+  printf("\n");
+  printf(
+"  If you want Triangle to determine for you which points and edges are on\n");
+  printf(
+"  the boundary, assign them the boundary marker zero (or use no markers at\n"
+);
+  printf(
+"  all) in your input files.  Alternatively, you can mark some of them and\n");
+  printf("  leave others marked zero, allowing Triangle to label them.\n\n");
+  printf("Triangulation Iteration Numbers:\n\n");
+  printf(
+"  Because Triangle can read and refine its own triangulations, input\n");
+  printf(
+"  and output files have iteration numbers.  For instance, Triangle might\n");
+  printf(
+"  read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
+  printf(
+"  triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
+  printf("  mesh.4.poly.  Files with no iteration number are treated as if\n");
+  printf(
+"  their iteration number is zero; hence, Triangle might read the file\n");
+  printf(
+"  points.node, triangulate it, and produce the files points.1.node and\n");
+  printf("  points.1.ele.\n\n");
+  printf(
+"  Iteration numbers allow you to create a sequence of successively finer\n");
+  printf(
+"  meshes suitable for multigrid methods.  They also allow you to produce a\n"
+);
+  printf(
+"  sequence of meshes using error estimate-driven mesh refinement.\n");
+  printf("\n");
+  printf(
+"  If you're not using refinement or quality meshing, and you don't like\n");
+  printf(
+"  iteration numbers, use the -I switch to disable them.  This switch will\n");
+  printf(
+"  also disable output of .node and .poly files to prevent your input files\n"
+);
+  printf(
+"  from being overwritten.  (If the input is a .poly file that contains its\n"
+);
+  printf("  own points, a .node file will be written.)\n\n");
+  printf("Examples of How to Use Triangle:\n\n");
+  printf(
+"  `triangle dots' will read points from dots.node, and write their Delaunay\n"
+);
+  printf(
+"  triangulation to dots.1.node and dots.1.ele.  (dots.1.node will be\n");
+  printf(
+"  identical to dots.node.)  `triangle -I dots' writes the triangulation to\n"
+);
+  printf(
+"  dots.ele instead.  (No additional .node file is needed, so none is\n");
+  printf("  written.)\n\n");
+  printf(
+"  `triangle -pe object.1' will read a PSLG from object.1.poly (and possibly\n"
+);
+  printf(
+"  object.1.node, if the points are omitted from object.1.poly) and write\n");
+  printf("  their constrained Delaunay triangulation to object.2.node and\n");
+  printf(
+"  object.2.ele.  The segments will be copied to object.2.poly, and all\n");
+  printf("  edges will be written to object.2.edge.\n\n");
+  printf(
+"  `triangle -pq31.5a.1 object' will read a PSLG from object.poly (and\n");
+  printf(
+"  possibly object.node), generate a mesh whose angles are all greater than\n"
+);
+  printf(
+"  31.5 degrees and whose triangles all have area smaller than 0.1, and\n");
+  printf(
+"  write the mesh to object.1.node and object.1.ele.  Each segment may have\n"
+);
+  printf(
+"  been broken up into multiple edges; the resulting constrained edges are\n");
+  printf("  written to object.1.poly.\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, one boundary marker.\n");
+  printf("    8 2 0 1\n");
+  printf("    # Outer box has these vertices:\n");
+  printf("     1   0 0   0\n");
+  printf("     2   0 3   0\n");
+  printf("     3   3 0   0\n");
+  printf("     4   3 3   33     # A special marker for this point.\n");
+  printf("    # Inner square has these vertices:\n");
+  printf("     5   1 1   0\n");
+  printf("     6   1 2   0\n");
+  printf("     7   2 1   0\n");
+  printf("     8   2 2   0\n");
+  printf("    # Five segments with boundary markers.\n");
+  printf("    5 1\n");
+  printf("     1   1 2   5      # Left side of outer box.\n");
+  printf("     2   5 7   0      # Segments 2 through 5 enclose the hole.\n");
+  printf("     3   7 8   0\n");
+  printf("     4   8 6   10\n");
+  printf("     5   6 5   0\n");
+  printf("    # One hole in the middle of the inner square.\n");
+  printf("    1\n");
+  printf("     1   1.5 1.5\n\n");
+  printf(
+"  Note that some segments are missing from the outer square, so one must\n");
+  printf(
+"  use the `-c' switch.  After `triangle -pqc box.poly', here is the output\n"
+);
+  printf(
+"  file `box.1.node', with twelve points.  The last four points were added\n");
+  printf(
+"  to meet the angle constraint.  Points 1, 2, and 9 have markers from\n");
+  printf(
+"  segment 1.  Points 6 and 8 have markers from segment 4.  All the other\n");
+  printf(
+"  points but 4 have been marked to indicate that they lie on a boundary.\n");
+  printf("\n");
+  printf("    12  2  0  1\n");
+  printf("       1    0   0      5\n");
+  printf("       2    0   3      5\n");
+  printf("       3    3   0      1\n");
+  printf("       4    3   3     33\n");
+  printf("       5    1   1      1\n");
+  printf("       6    1   2     10\n");
+  printf("       7    2   1      1\n");
+  printf("       8    2   2     10\n");
+  printf("       9    0   1.5    5\n");
+  printf("      10    1.5   0    1\n");
+  printf("      11    3   1.5    1\n");
+  printf("      12    1.5   3    1\n");
+  printf("    # Generated by triangle -pqc box.poly\n\n");
+  printf("  Here is the output file `box.1.ele', with twelve triangles.\n\n");
+  printf("    12  3  0\n");
+  printf("       1     5   6   9\n");
+  printf("       2    10   3   7\n");
+  printf("       3     6   8  12\n");
+  printf("       4     9   1   5\n");
+  printf("       5     6   2   9\n");
+  printf("       6     7   3  11\n");
+  printf("       7    11   4   8\n");
+  printf("       8     7   5  10\n");
+  printf("       9    12   2   6\n");
+  printf("      10     8   7  11\n");
+  printf("      11     5   1  10\n");
+  printf("      12     8   4  12\n");
+  printf("    # Generated by triangle -pqc box.poly\n\n");
+  printf(
+"  Here is the output file `box.1.poly'.  Note that segments have been added\n"
+);
+  printf(
+"  to represent the convex hull, and some segments have been split by newly\n"
+);
+  printf(
+"  added points.  Note also that <# of points> is set to zero to indicate\n");
+  printf("  that the points should be read from the .node file.\n\n");
+  printf("    0  2  0  1\n");
+  printf("    12  1\n");
+  printf("       1     1   9     5\n");
+  printf("       2     5   7     1\n");
+  printf("       3     8   7     1\n");
+  printf("       4     6   8    10\n");
+  printf("       5     5   6     1\n");
+  printf("       6     3  10     1\n");
+  printf("       7     4  11     1\n");
+  printf("       8     2  12     1\n");
+  printf("       9     9   2     5\n");
+  printf("      10    10   1     1\n");
+  printf("      11    11   3     1\n");
+  printf("      12    12   4     1\n");
+  printf("    1\n");
+  printf("       1   1.5 1.5\n");
+  printf("    # Generated by triangle -pqc box.poly\n\n");
+  printf("Refinement and Area Constraints:\n\n");
+  printf(
+"  The -r switch causes a mesh (.node and .ele files) to be read and\n");
+  printf(
+"  refined.  If the -p switch is also used, a .poly file is read and used to\n"
+);
+  printf(
+"  specify edges that are constrained and cannot be eliminated (although\n");
+  printf(
+"  they can be divided into smaller edges) by the refinement process.\n");
+  printf("\n");
+  printf(
+"  When you refine a mesh, you generally want to impose tighter quality\n");
+  printf(
+"  constraints.  One way to accomplish this is to use -q with a larger\n");
+  printf(
+"  angle, or -a followed by a smaller area than you used to generate the\n");
+  printf(
+"  mesh you are refining.  Another way to do this is to create an .area\n");
+  printf(
+"  file, which specifies a maximum area for each triangle, and use the -a\n");
+  printf(
+"  switch (without a number following).  Each triangle's area constraint is\n"
+);
+  printf(
+"  applied to that triangle.  Area constraints tend to diffuse as the mesh\n");
+  printf(
+"  is refined, so if there are large variations in area constraint between\n");
+  printf("  adjacent triangles, you may not get the results you want.\n\n");
+  printf(
+"  If you are refining a mesh composed of linear (three-node) elements, the\n"
+);
+  printf(
+"  output mesh will contain all the nodes present in the input mesh, in the\n"
+);
+  printf(
+"  same order, with new nodes added at the end of the .node file.  However,\n"
+);
+  printf(
+"  there is no guarantee that each output element is contained in a single\n");
+  printf(
+"  input element.  Often, output elements will overlap two input elements,\n");
+  printf(
+"  and input edges are not present in the output mesh.  Hence, a sequence of\n"
+);
+  printf(
+"  refined meshes will form a hierarchy of nodes, but not a hierarchy of\n");
+  printf(
+"  elements.  If you a refining a mesh of higher-order elements, the\n");
+  printf(
+"  hierarchical property applies only to the nodes at the corners of an\n");
+  printf("  element; other nodes may not be present in the refined mesh.\n\n");
+  printf(
+"  It is important to understand that maximum area constraints in .poly\n");
+  printf(
+"  files are handled differently from those in .area files.  A maximum area\n"
+);
+  printf(
+"  in a .poly file applies to the whole (segment-bounded) region in which a\n"
+);
+  printf(
+"  point falls, whereas a maximum area in an .area file applies to only one\n"
+);
+  printf(
+"  triangle.  Area constraints in .poly files are used only when a mesh is\n");
+  printf(
+"  first generated, whereas area constraints in .area files are used only to\n"
+);
+  printf(
+"  refine an existing mesh, and are typically based on a posteriori error\n");
+  printf(
+"  estimates resulting from a finite element simulation on that mesh.\n");
+  printf("\n");
+  printf(
+"  `triangle -rq25 object.1' will read object.1.node and object.1.ele, then\n"
+);
+  printf(
+"  refine the triangulation to enforce a 25 degree minimum angle, and then\n");
+  printf(
+"  write the refined triangulation to object.2.node and object.2.ele.\n");
+  printf("\n");
+  printf(
+"  `triangle -rpaa6.2 z.3' will read z.3.node, z.3.ele, z.3.poly, and\n");
+  printf(
+"  z.3.area.  After reconstructing the mesh and its segments, Triangle will\n"
+);
+  printf(
+"  refine the mesh so that no triangle has area greater than 6.2, and\n");
+  printf(
+"  furthermore the triangles satisfy the maximum area constraints in\n");
+  printf(
+"  z.3.area.  The output is written to z.4.node, z.4.ele, and z.4.poly.\n");
+  printf("\n");
+  printf(
+"  The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
+  printf(
+"  x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
+  printf("  suitable for multigrid.\n\n");
+  printf("Convex Hulls and Mesh Boundaries:\n\n");
+  printf(
+"  If the input is a point set (rather than a PSLG), Triangle produces its\n");
+  printf(
+"  convex hull as a by-product in the output .poly file if you use the -c\n");
+  printf(
+"  switch.  There are faster algorithms for finding a two-dimensional convex\n"
+);
+  printf(
+"  hull than triangulation, of course, but this one comes for free.  If the\n"
+);
+  printf(
+"  input is an unconstrained mesh (you are using the -r switch but not the\n");
+  printf(
+"  -p switch), Triangle produces a list of its boundary edges (including\n");
+  printf("  hole boundaries) as a by-product if you use the -c switch.\n\n");
+  printf("Voronoi Diagrams:\n\n");
+  printf(
+"  The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
+  printf(
+"  .v.edge.  For example, `triangle -v points' will read points.node,\n");
+  printf(
+"  produce its Delaunay triangulation in points.1.node and points.1.ele,\n");
+  printf(
+"  and produce its Voronoi diagram in points.1.v.node and points.1.v.edge.\n");
+  printf(
+"  The .v.node file contains a list of all Voronoi vertices, and the .v.edge\n"
+);
+  printf(
+"  file contains a list of all Voronoi edges, some of which may be infinite\n"
+);
+  printf(
+"  rays.  (The choice of filenames makes it easy to run the set of Voronoi\n");
+  printf("  vertices through Triangle, if so desired.)\n\n");
+  printf(
+"  This implementation does not use exact arithmetic to compute the Voronoi\n"
+);
+  printf(
+"  vertices, and does not check whether neighboring vertices are identical.\n"
+);
+  printf(
+"  Be forewarned that if the Delaunay triangulation is degenerate or\n");
+  printf(
+"  near-degenerate, the Voronoi diagram may have duplicate points, crossing\n"
+);
+  printf(
+"  edges, or infinite rays whose direction vector is zero.  Also, if you\n");
+  printf(
+"  generate a constrained (as opposed to conforming) Delaunay triangulation,\n"
+);
+  printf(
+"  or if the triangulation has holes, the corresponding Voronoi diagram is\n");
+  printf("  likely to have crossing edges and unlikely to make sense.\n\n");
+  printf("Mesh Topology:\n\n");
+  printf(
+"  You may wish to know which triangles are adjacent to a certain Delaunay\n");
+  printf(
+"  edge in an .edge file, which Voronoi regions are adjacent to a certain\n");
+  printf(
+"  Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to\n"
+);
+  printf(
+"  each other.  All of this information can be found by cross-referencing\n");
+  printf(
+"  output files with the recollection that the Delaunay triangulation and\n");
+  printf("  the Voronoi diagrams are planar duals.\n\n");
+  printf(
+"  Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
+  printf(
+"  the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
+  printf(
+"  wise from the Voronoi edge.  Triangle j of an .ele file is the dual of\n");
+  printf(
+"  vertex j of the corresponding .v.node file; and Voronoi region k is the\n");
+  printf("  dual of point k of the corresponding .node file.\n\n");
+  printf(
+"  Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
+  printf(
+"  vertices of the corresponding Voronoi edge; their dual triangles are on\n");
+  printf(
+"  the left and right of the Delaunay edge, respectively.  To find the\n");
+  printf(
+"  Voronoi regions adjacent to a Voronoi edge, look at the endpoints of the\n"
+);
+  printf(
+"  corresponding Delaunay edge; their dual regions are on the right and left\n"
+);
+  printf(
+"  of the Voronoi edge, respectively.  To find which Voronoi regions are\n");
+  printf("  adjacent to each other, just read the list of Delaunay edges.\n");
+  printf("\n");
+  printf("Statistics:\n");
+  printf("\n");
+  printf(
+"  After generating a mesh, Triangle prints a count of the number of points,\n"
+);
+  printf(
+"  triangles, edges, boundary edges, and segments in the output mesh.  If\n");
+  printf(
+"  you've forgotten the statistics for an existing mesh, the -rNEP switches\n"
+);
+  printf(
+"  (or -rpNEP if you've got a .poly file for the existing mesh) will\n");
+  printf("  regenerate these statistics without writing any output.\n\n");
+  printf(
+"  The -V switch produces extended statistics, including a rough estimate\n");
+  printf(
+"  of memory use and a histogram of triangle aspect ratios and angles in the\n"
+);
+  printf("  mesh.\n\n");
+  printf("Exact Arithmetic:\n\n");
+  printf(
+"  Triangle uses adaptive exact arithmetic to perform what computational\n");
+  printf(
+"  geometers call the `orientation' and `incircle' tests.  If the floating-\n"
+);
+  printf(
+"  point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
+  printf(
+"  most workstations do), and does not use extended precision internal\n");
+  printf(
+"  registers, then your output is guaranteed to be an absolutely true\n");
+  printf("  Delaunay or conforming Delaunay triangulation, roundoff error\n");
+  printf(
+"  notwithstanding.  The word `adaptive' implies that these arithmetic\n");
+  printf(
+"  routines compute the result only to the precision necessary to guarantee\n"
+);
+  printf(
+"  correctness, so they are usually nearly as fast as their approximate\n");
+  printf(
+"  counterparts.  The exact tests can be disabled with the -X switch.  On\n");
+  printf(
+"  most inputs, this switch will reduce the computation time by about eight\n"
+);
+  printf(
+"  percent - it's not worth the risk.  There are rare difficult inputs\n");
+  printf(
+"  (having many collinear and cocircular points), however, for which the\n");
+  printf(
+"  difference could be a factor of two.  These are precisely the inputs most\n"
+);
+  printf("  likely to cause errors if you use the -X switch.\n\n");
+  printf(
+"  Unfortunately, these routines don't solve every numerical problem.  Exact\n"
+);
+  printf(
+"  arithmetic is not used to compute the positions of points, because the\n");
+  printf(
+"  bit complexity of point coordinates would grow without bound.  Hence,\n");
+  printf(
+"  segment intersections aren't computed exactly; in very unusual cases,\n");
+  printf(
+"  roundoff error in computing an intersection point might actually lead to\n"
+);
+  printf(
+"  an inverted triangle and an invalid triangulation.  (This is one reason\n");
+  printf(
+"  to compute your own intersection points in your .poly files.)  Similarly,\n"
+);
+  printf(
+"  exact arithmetic is not used to compute the vertices of the Voronoi\n");
+  printf("  diagram.\n\n");
+  printf(
+"  Underflow and overflow can also cause difficulties; the exact arithmetic\n"
+);
+  printf(
+"  routines do not ameliorate out-of-bounds exponents, which can arise\n");
+  printf(
+"  during the orientation and incircle tests.  As a rule of thumb, you\n");
+  printf(
+"  should ensure that your input values are within a range such that their\n");
+  printf(
+"  third powers can be taken without underflow or overflow.  Underflow can\n");
+  printf(
+"  silently prevent the tests from being performed exactly, while overflow\n");
+  printf("  will typically cause a floating exception.\n\n");
+  printf("Calling Triangle from Another Program:\n\n");
+  printf("  Read the file triangle.h for details.\n\n");
+  printf("Troubleshooting:\n\n");
+  printf("  Please read this section before mailing me bugs.\n\n");
+  printf("  `My output mesh has no triangles!'\n\n");
+  printf(
+"    If you're using a PSLG, you've probably failed to specify a proper set\n"
+);
+  printf(
+"    of bounding segments, or forgotten to use the -c switch.  Or you may\n");
+  printf(
+"    have placed a hole badly.  To test these possibilities, try again with\n"
+);
+  printf(
+"    the -c and -O switches.  Alternatively, all your input points may be\n");
+  printf(
+"    collinear, in which case you can hardly expect to triangulate them.\n");
+  printf("\n");
+  printf("  `Triangle doesn't terminate, or just crashes.'\n");
+  printf("\n");
+  printf(
+"    Bad things can happen when triangles get so small that the distance\n");
+  printf(
+"    between their vertices isn't much larger than the precision of your\n");
+  printf(
+"    machine's arithmetic.  If you've compiled Triangle for single-precision\n"
+);
+  printf(
+"    arithmetic, you might do better by recompiling it for double-precision.\n"
+);
+  printf(
+"    Then again, you might just have to settle for more lenient constraints\n"
+);
+  printf(
+"    on the minimum angle and the maximum area than you had planned.\n");
+  printf("\n");
+  printf(
+"    You can minimize precision problems by ensuring that the origin lies\n");
+  printf(
+"    inside your point set, or even inside the densest part of your\n");
+  printf(
+"    mesh.  On the other hand, if you're triangulating an object whose x\n");
+  printf(
+"    coordinates all fall between 6247133 and 6247134, you're not leaving\n");
+  printf("    much floating-point precision for Triangle to work with.\n\n");
+  printf(
+"    Precision problems can occur covertly if the input PSLG contains two\n");
+  printf(
+"    segments that meet (or intersect) at a very small angle, or if such an\n"
+);
+  printf(
+"    angle is introduced by the -c switch, which may occur if a point lies\n");
+  printf(
+"    ever-so-slightly inside the convex hull, and is connected by a PSLG\n");
+  printf(
+"    segment to a point on the convex hull.  If you don't realize that a\n");
+  printf(
+"    small angle is being formed, you might never discover why Triangle is\n");
+  printf(
+"    crashing.  To check for this possibility, use the -S switch (with an\n");
+  printf(
+"    appropriate limit on the number of Steiner points, found by trial-and-\n"
+);
+  printf(
+"    error) to stop Triangle early, and view the output .poly file with\n");
+  printf(
+"    Show Me (described below).  Look carefully for small angles between\n");
+  printf(
+"    segments; zoom in closely, as such segments might look like a single\n");
+  printf("    segment from a distance.\n\n");
+  printf(
+"    If some of the input values are too large, Triangle may suffer a\n");
+  printf(
+"    floating exception due to overflow when attempting to perform an\n");
+  printf(
+"    orientation or incircle test.  (Read the section on exact arithmetic\n");
+  printf(
+"    above.)  Again, I recommend compiling Triangle for double (rather\n");
+  printf("    than single) precision arithmetic.\n\n");
+  printf(
+"  `The numbering of the output points doesn't match the input points.'\n");
+  printf("\n");
+  printf(
+"    You may have eaten some of your input points with a hole, or by placing\n"
+);
+  printf("    them outside the area enclosed by segments.\n\n");
+  printf(
+"  `Triangle executes without incident, but when I look at the resulting\n");
+  printf(
+"  mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
+  printf("\n");
+  printf(
+"    If you select the -X switch, Triangle's divide-and-conquer Delaunay\n");
+  printf(
+"    triangulation algorithm occasionally makes mistakes due to floating-\n");
+  printf(
+"    point roundoff error.  Although these errors are rare, don't use the -X\n"
+);
+  printf("    switch.  If you still have problems, please report the bug.\n");
+  printf("\n");
+  printf(
+"  Strange things can happen if you've taken liberties with your PSLG.  Do\n");
+  printf(
+"  you have a point lying in the middle of a segment?  Triangle sometimes\n");
+  printf(
+"  copes poorly with that sort of thing.  Do you want to lay out a collinear\n"
+);
+  printf(
+"  row of evenly spaced, segment-connected points?  Have you simply defined\n"
+);
+  printf(
+"  one long segment connecting the leftmost point to the rightmost point,\n");
+  printf(
+"  and a bunch of points lying along it?  This method occasionally works,\n");
+  printf(
+"  especially with horizontal and vertical lines, but often it doesn't, and\n"
+);
+  printf(
+"  you'll have to connect each adjacent pair of points with a separate\n");
+  printf("  segment.  If you don't like it, tough.\n\n");
+  printf(
+"  Furthermore, if you have segments that intersect other than at their\n");
+  printf(
+"  endpoints, try not to let the intersections fall extremely close to PSLG\n"
+);
+  printf("  points or each other.\n\n");
+  printf(
+"  If you have problems refining a triangulation not produced by Triangle:\n");
+  printf(
+"  Are you sure the triangulation is geometrically valid?  Is it formatted\n");
+  printf(
+"  correctly for Triangle?  Are the triangles all listed so the first three\n"
+);
+  printf("  points are their corners in counterclockwise order?\n\n");
+  printf("Show Me:\n\n");
+  printf(
+"  Triangle comes with a separate program named `Show Me', whose primary\n");
+  printf(
+"  purpose is to draw meshes on your screen or in PostScript.  Its secondary\n"
+);
+  printf(
+"  purpose is to check the validity of your input files, and do so more\n");
+  printf(
+"  thoroughly than Triangle does.  Show Me requires that you have the X\n");
+  printf(
+"  Windows system.  If you didn't receive Show Me with Triangle, complain to\n"
+);
+  printf("  whomever you obtained Triangle from, then send me mail.\n\n");
+  printf("Triangle 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/triangle.html\n");
+  printf("\n");
+  printf("A Brief Plea:\n");
+  printf("\n");
+  printf(
+"  If you use Triangle, and especially if you use it to accomplish real\n");
+  printf(
+"  work, I would like very much to hear from you.  A short letter or email\n");
+  printf(
+"  (to jrs@cs.cmu.edu) describing how you use Triangle will mean a lot to\n");
+  printf(
+"  me.  The more people I know are using this program, the more easily I can\n"
+);
+  printf(
+"  justify spending time on improvements and on the three-dimensional\n");
+  printf(
+"  successor to Triangle, which in turn will benefit you.  Also, I can put\n");
+  printf(
+"  you on a list to receive email whenever a new version of Triangle is\n");
+  printf("  available.\n\n");
+  printf(
+"  If you use a mesh generated by Triangle in a publication, please include\n"
+);
+  printf("  an acknowledgment as well.\n\n");
+  printf("Research credit:\n\n");
+  printf(
+"  Of course, I can take credit for only a fraction of the ideas that made\n");
+  printf(
+"  this mesh generator possible.  Triangle owes its existence to the efforts\n"
+);
+  printf(
+"  of many fine computational geometers and other researchers, including\n");
+  printf(
+"  Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David\n");
+  printf(
+"  Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.\n");
+  printf(
+"  Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,\n");
+  printf(
+"  Isaac Saias, Bruce J. Schachter, Micha Sharir, Jorge Stolfi, Christopher\n"
+);
+  printf(
+"  J. Van Wyk, David F. Watson, and Binhai Zhu.  See the comments at the\n");
+  printf("  beginning of the source code for references.\n\n");
+  exit(0);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  internalerror()   Ask the user to send me the defective product.  Exit.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void internalerror()
+{
+  printf("  Please report this bug to jrs@cs.cmu.edu\n");
+  printf("  Include the message above, your input data set, and the exact\n");
+  printf("    command line you used to run Triangle.\n");
+  exit(1);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  parsecommandline()   Read the command line, identify switches, and set   */
+/*                       up options and file names.                          */
+/*                                                                           */
+/*  The effects of this routine are felt entirely through global variables.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void parsecommandline(argc, argv)
+int argc;
+char **argv;
+{
+#ifdef TRILIBRARY
+#define STARTINDEX 0
+#else /* not TRILIBRARY */
+#define STARTINDEX 1
+  int increment;
+  int meshnumber;
+#endif /* not TRILIBRARY */
+  int i, j, k;
+  char workstring[FILENAMESIZE];
+
+  poly = refine = quality = vararea = fixedarea = regionattrib = convex = 0;
+  firstnumber = 1;
+  edgesout = voronoi = neighbors = geomview = 0;
+  nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0;
+  noholes = noexact = 0;
+  incremental = sweepline = 0;
+  dwyer = 1;
+  splitseg = 0;
+  docheck = 0;
+  nobisect = 0;
+  steiner = -1;
+  order = 1;
+  minangle = 0.0;
+  maxarea = -1.0;
+  quiet = verbose = 0;
+#ifndef TRILIBRARY
+  innodefilename[0] = '\0';
+#endif /* not TRILIBRARY */
+
+  for (i = STARTINDEX; i < argc; i++) {
+#ifndef TRILIBRARY
+    if (argv[i][0] == '-') {
+#endif /* not TRILIBRARY */
+      for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
+        if (argv[i][j] == 'p') {
+          poly = 1;
+	}
+#ifndef CDT_ONLY
+        if (argv[i][j] == 'r') {
+          refine = 1;
+	}
+        if (argv[i][j] == 'q') {
+          quality = 1;
+          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+              (argv[i][j + 1] == '.')) {
+            k = 0;
+            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+                   (argv[i][j + 1] == '.')) {
+              j++;
+              workstring[k] = argv[i][j];
+              k++;
+            }
+            workstring[k] = '\0';
+            minangle = (REAL) strtod(workstring, (char **) NULL);
+	  } else {
+            minangle = 20.0;
+	  }
+	}
+        if (argv[i][j] == 'a') {
+          quality = 1;
+          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+              (argv[i][j + 1] == '.')) {
+            fixedarea = 1;
+            k = 0;
+            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+                   (argv[i][j + 1] == '.')) {
+              j++;
+              workstring[k] = argv[i][j];
+              k++;
+            }
+            workstring[k] = '\0';
+            maxarea = (REAL) strtod(workstring, (char **) NULL);
+            if (maxarea <= 0.0) {
+              printf("Error:  Maximum area must be greater than zero.\n");
+              exit(1);
+	    }
+	  } else {
+            vararea = 1;
+	  }
+	}
+#endif /* not CDT_ONLY */
+        if (argv[i][j] == 'A') {
+          regionattrib = 1;
+        }
+        if (argv[i][j] == 'c') {
+          convex = 1;
+        }
+        if (argv[i][j] == 'z') {
+          firstnumber = 0;
+        }
+        if (argv[i][j] == 'e') {
+          edgesout = 1;
+	}
+        if (argv[i][j] == 'v') {
+          voronoi = 1;
+	}
+        if (argv[i][j] == 'n') {
+          neighbors = 1;
+	}
+        if (argv[i][j] == 'g') {
+          geomview = 1;
+	}
+        if (argv[i][j] == 'B') {
+          nobound = 1;
+	}
+        if (argv[i][j] == 'P') {
+          nopolywritten = 1;
+	}
+        if (argv[i][j] == 'N') {
+          nonodewritten = 1;
+	}
+        if (argv[i][j] == 'E') {
+          noelewritten = 1;
+	}
+#ifndef TRILIBRARY
+        if (argv[i][j] == 'I') {
+          noiterationnum = 1;
+	}
+#endif /* not TRILIBRARY */
+        if (argv[i][j] == 'O') {
+          noholes = 1;
+	}
+        if (argv[i][j] == 'X') {
+          noexact = 1;
+	}
+        if (argv[i][j] == 'o') {
+          if (argv[i][j + 1] == '2') {
+            j++;
+            order = 2;
+          }
+	}
+#ifndef CDT_ONLY
+        if (argv[i][j] == 'Y') {
+          nobisect++;
+	}
+        if (argv[i][j] == 'S') {
+          steiner = 0;
+          while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
+            j++;
+            steiner = steiner * 10 + (int) (argv[i][j] - '0');
+          }
+        }
+#endif /* not CDT_ONLY */
+#ifndef REDUCED
+        if (argv[i][j] == 'i') {
+          incremental = 1;
+        }
+        if (argv[i][j] == 'F') {
+          sweepline = 1;
+        }
+#endif /* not REDUCED */
+        if (argv[i][j] == 'l') {
+          dwyer = 0;
+        }
+#ifndef REDUCED
+#ifndef CDT_ONLY
+        if (argv[i][j] == 's') {
+          splitseg = 1;
+        }
+#endif /* not CDT_ONLY */
+        if (argv[i][j] == 'C') {
+          docheck = 1;
+        }
+#endif /* not REDUCED */
+        if (argv[i][j] == 'Q') {
+          quiet = 1;
+        }
+        if (argv[i][j] == 'V') {
+          verbose++;
+        }
+#ifndef TRILIBRARY
+        if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
+            (argv[i][j] == '?')) {
+          info();
+	}
+#endif /* not TRILIBRARY */
+      }
+#ifndef TRILIBRARY
+    } else {
+      strncpy(innodefilename, argv[i], FILENAMESIZE - 1);
+      innodefilename[FILENAMESIZE - 1] = '\0';
+    }
+#endif /* not TRILIBRARY */
+  }
+#ifndef TRILIBRARY
+  if (innodefilename[0] == '\0') {
+    syntax();
+  }
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".node")) {
+    innodefilename[strlen(innodefilename) - 5] = '\0';
+  }
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".poly")) {
+    innodefilename[strlen(innodefilename) - 5] = '\0';
+    poly = 1;
+  }
+#ifndef CDT_ONLY
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 4], ".ele")) {
+    innodefilename[strlen(innodefilename) - 4] = '\0';
+    refine = 1;
+  }
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".area")) {
+    innodefilename[strlen(innodefilename) - 5] = '\0';
+    refine = 1;
+    quality = 1;
+    vararea = 1;
+  }
+#endif /* not CDT_ONLY */
+#endif /* not TRILIBRARY */
+  steinerleft = steiner;
+  useshelles = poly || refine || quality || convex;
+  goodangle = cos(minangle * PI / 180.0);
+  goodangle *= goodangle;
+  if (refine && noiterationnum) {
+    printf(
+      "Error:  You cannot use the -I switch when refining a triangulation.\n");
+    exit(1);
+  }
+  /* Be careful not to allocate space for element area constraints that */
+  /*   will never be assigned any value (other than the default -1.0).  */
+  if (!refine && !poly) {
+    vararea = 0;
+  }
+  /* Be careful not to add an extra attribute to each element unless the */
+  /*   input supports it (PSLG in, but not refining a preexisting mesh). */
+  if (refine || !poly) {
+    regionattrib = 0;
+  }
+
+#ifndef TRILIBRARY
+  strcpy(inpolyfilename, innodefilename);
+  strcpy(inelefilename, innodefilename);
+  strcpy(areafilename, innodefilename);
+  increment = 0;
+  strcpy(workstring, innodefilename);
+  j = 1;
+  while (workstring[j] != '\0') {
+    if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
+      increment = j + 1;
+    }
+    j++;
+  }
+  meshnumber = 0;
+  if (increment > 0) {
+    j = increment;
+    do {
+      if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
+        meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
+      } else {
+        increment = 0;
+      }
+      j++;
+    } while (workstring[j] != '\0');
+  }
+  if (noiterationnum) {
+    strcpy(outnodefilename, innodefilename);
+    strcpy(outelefilename, innodefilename);
+    strcpy(edgefilename, innodefilename);
+    strcpy(vnodefilename, innodefilename);
+    strcpy(vedgefilename, innodefilename);
+    strcpy(neighborfilename, innodefilename);
+    strcpy(offfilename, innodefilename);
+    strcat(outnodefilename, ".node");
+    strcat(outelefilename, ".ele");
+    strcat(edgefilename, ".edge");
+    strcat(vnodefilename, ".v.node");
+    strcat(vedgefilename, ".v.edge");
+    strcat(neighborfilename, ".neigh");
+    strcat(offfilename, ".off");
+  } else if (increment == 0) {
+    strcpy(outnodefilename, innodefilename);
+    strcpy(outpolyfilename, innodefilename);
+    strcpy(outelefilename, innodefilename);
+    strcpy(edgefilename, innodefilename);
+    strcpy(vnodefilename, innodefilename);
+    strcpy(vedgefilename, innodefilename);
+    strcpy(neighborfilename, innodefilename);
+    strcpy(offfilename, innodefilename);
+    strcat(outnodefilename, ".1.node");
+    strcat(outpolyfilename, ".1.poly");
+    strcat(outelefilename, ".1.ele");
+    strcat(edgefilename, ".1.edge");
+    strcat(vnodefilename, ".1.v.node");
+    strcat(vedgefilename, ".1.v.edge");
+    strcat(neighborfilename, ".1.neigh");
+    strcat(offfilename, ".1.off");
+  } else {
+    workstring[increment] = '%';
+    workstring[increment + 1] = 'd';
+    workstring[increment + 2] = '\0';
+    sprintf(outnodefilename, workstring, meshnumber + 1);
+    strcpy(outpolyfilename, outnodefilename);
+    strcpy(outelefilename, outnodefilename);
+    strcpy(edgefilename, outnodefilename);
+    strcpy(vnodefilename, outnodefilename);
+    strcpy(vedgefilename, outnodefilename);
+    strcpy(neighborfilename, outnodefilename);
+    strcpy(offfilename, outnodefilename);
+    strcat(outnodefilename, ".node");
+    strcat(outpolyfilename, ".poly");
+    strcat(outelefilename, ".ele");
+    strcat(edgefilename, ".edge");
+    strcat(vnodefilename, ".v.node");
+    strcat(vedgefilename, ".v.edge");
+    strcat(neighborfilename, ".neigh");
+    strcat(offfilename, ".off");
+  }
+  strcat(innodefilename, ".node");
+  strcat(inpolyfilename, ".poly");
+  strcat(inelefilename, ".ele");
+  strcat(areafilename, ".area");
+#endif /* not TRILIBRARY */
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* User interaction routines begin here                      *********/
+
+/********* Debugging routines begin here                             *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  printtriangle()   Print out the details of a triangle/edge handle.       */
+/*                                                                           */
+/*  I originally wrote this procedure to simplify debugging; it can be       */
+/*  called directly from the debugger, and presents information about a      */
+/*  triangle/edge handle in digestible form.  It's also used when the        */
+/*  highest level of verbosity (`-VVV') is specified.                        */
+/*                                                                           */
+/*****************************************************************************/
+
+void printtriangle(t)
+struct triedge *t;
+{
+  struct triedge printtri;
+  struct edge printsh;
+  point printpoint;
+
+  printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
+         t->orient);
+  decode(t->tri[0], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [0] = Outer space\n");
+  } else {
+    printf("    [0] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  decode(t->tri[1], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [1] = Outer space\n");
+  } else {
+    printf("    [1] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  decode(t->tri[2], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [2] = Outer space\n");
+  } else {
+    printf("    [2] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  org(*t, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
+  else
+    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
+           (t->orient + 1) % 3 + 3, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  dest(*t, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Dest  [%d] = NULL\n", (t->orient + 2) % 3 + 3);
+  else
+    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
+           (t->orient + 2) % 3 + 3, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  apex(*t, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Apex  [%d] = NULL\n", t->orient + 3);
+  else
+    printf("    Apex  [%d] = x%lx  (%.12g, %.12g)\n",
+           t->orient + 3, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  if (useshelles) {
+    sdecode(t->tri[6], printsh);
+    if (printsh.sh != dummysh) {
+      printf("    [6] = x%lx  %d\n", (unsigned long) printsh.sh,
+             printsh.shorient);
+    }
+    sdecode(t->tri[7], printsh);
+    if (printsh.sh != dummysh) {
+      printf("    [7] = x%lx  %d\n", (unsigned long) printsh.sh,
+             printsh.shorient);
+    }
+    sdecode(t->tri[8], printsh);
+    if (printsh.sh != dummysh) {
+      printf("    [8] = x%lx  %d\n", (unsigned long) printsh.sh,
+             printsh.shorient);
+    }
+  }
+  if (vararea) {
+    printf("    Area constraint:  %.4g\n", areabound(*t));
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  printshelle()   Print out the details of a shell edge handle.            */
+/*                                                                           */
+/*  I originally wrote this procedure to simplify debugging; it can be       */
+/*  called directly from the debugger, and presents information about a      */
+/*  shell edge handle in digestible form.  It's also used when the highest   */
+/*  level of verbosity (`-VVV') is specified.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+void printshelle(s)
+struct edge *s;
+{
+  struct edge printsh;
+  struct triedge printtri;
+  point printpoint;
+
+  printf("shell edge x%lx with orientation %d and mark %d:\n",
+         (unsigned long) s->sh, s->shorient, mark(*s));
+  sdecode(s->sh[0], printsh);
+  if (printsh.sh == dummysh) {
+    printf("    [0] = No shell\n");
+  } else {
+    printf("    [0] = x%lx  %d\n", (unsigned long) printsh.sh,
+           printsh.shorient);
+  }
+  sdecode(s->sh[1], printsh);
+  if (printsh.sh == dummysh) {
+    printf("    [1] = No shell\n");
+  } else {
+    printf("    [1] = x%lx  %d\n", (unsigned long) printsh.sh,
+           printsh.shorient);
+  }
+  sorg(*s, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Origin[%d] = NULL\n", 2 + s->shorient);
+  else
+    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
+           2 + s->shorient, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  sdest(*s, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Dest  [%d] = NULL\n", 3 - s->shorient);
+  else
+    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
+           3 - s->shorient, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  decode(s->sh[4], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [4] = Outer space\n");
+  } else {
+    printf("    [4] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  decode(s->sh[5], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [5] = Outer space\n");
+  } else {
+    printf("    [5] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Debugging routines end here                               *********/
+
+/********* Memory management routines begin here                     *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  poolinit()   Initialize a pool of memory for allocation of items.        */
+/*                                                                           */
+/*  This routine initializes the machinery for allocating items.  A `pool'   */
+/*  is created whose records have size at least `bytecount'.  Items will be  */
+/*  allocated in `itemcount'-item blocks.  Each item is assumed to be a      */
+/*  collection of words, and either pointers or floating-point values are    */
+/*  assumed to be the "primary" word type.  (The "primary" word type is used */
+/*  to determine alignment of items.)  If `alignment' isn't zero, all items  */
+/*  will be `alignment'-byte aligned in memory.  `alignment' must be either  */
+/*  a multiple or a factor of the primary word size; powers of two are safe. */
+/*  `alignment' is normally used to create a few unused bits at the bottom   */
+/*  of each item's pointer, in which information may be stored.              */
+/*                                                                           */
+/*  Don't change this routine unless you understand it.                      */
+/*                                                                           */
+/*****************************************************************************/
+
+void poolinit(pool, bytecount, itemcount, wtype, alignment)
+struct memorypool *pool;
+int bytecount;
+int itemcount;
+enum wordtype wtype;
+int alignment;
+{
+  int wordsize;
+
+  /* Initialize values in the pool. */
+  pool->itemwordtype = wtype;
+  wordsize = (pool->itemwordtype == POINTER) ? sizeof(VOID *) : sizeof(REAL);
+  /* Find the proper alignment, which must be at least as large as:   */
+  /*   - The parameter `alignment'.                                   */
+  /*   - The primary word type, to avoid unaligned accesses.          */
+  /*   - sizeof(VOID *), so the stack of dead items can be maintained */
+  /*       without unaligned accesses.                                */
+  if (alignment > wordsize) {
+    pool->alignbytes = alignment;
+  } else {
+    pool->alignbytes = wordsize;
+  }
+  if (sizeof(VOID *) > pool->alignbytes) {
+    pool->alignbytes = sizeof(VOID *);
+  }
+  pool->itemwords = ((bytecount + pool->alignbytes - 1) / pool->alignbytes)
+                  * (pool->alignbytes / wordsize);
+  pool->itembytes = pool->itemwords * wordsize;
+  pool->itemsperblock = itemcount;
+
+  /* Allocate a block of items.  Space for `itemsperblock' items and one    */
+  /*   pointer (to point to the next block) are allocated, as well as space */
+  /*   to ensure alignment of the items.                                    */
+  pool->firstblock = (VOID **) malloc(pool->itemsperblock * pool->itembytes
+                                      + sizeof(VOID *) + pool->alignbytes);
+  if (pool->firstblock == (VOID **) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  /* Set the next block pointer to NULL. */
+  *(pool->firstblock) = (VOID *) NULL;
+  poolrestart(pool);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  poolrestart()   Deallocate all items in a pool.                          */
+/*                                                                           */
+/*  The pool is returned to its starting state, except that no memory is     */
+/*  freed to the operating system.  Rather, the previously allocated blocks  */
+/*  are ready to be reused.                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void poolrestart(pool)
+struct memorypool *pool;
+{
+  unsigned long alignptr;
+
+  pool->items = 0;
+  pool->maxitems = 0;
+
+  /* Set the currently active block. */
+  pool->nowblock = pool->firstblock;
+  /* Find the first item in the pool.  Increment by the size of (VOID *). */
+  alignptr = (unsigned long) (pool->nowblock + 1);
+  /* Align the item on an `alignbytes'-byte boundary. */
+  pool->nextitem = (VOID *)
+    (alignptr + (unsigned long) pool->alignbytes
+     - (alignptr % (unsigned long) pool->alignbytes));
+  /* There are lots of unallocated items left in this block. */
+  pool->unallocateditems = pool->itemsperblock;
+  /* The stack of deallocated items is empty. */
+  pool->deaditemstack = (VOID *) NULL;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pooldeinit()   Free to the operating system all memory taken by a pool.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void pooldeinit(pool)
+struct memorypool *pool;
+{
+  while (pool->firstblock != (VOID **) NULL) {
+    pool->nowblock = (VOID **) *(pool->firstblock);
+    free(pool->firstblock);
+    pool->firstblock = pool->nowblock;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  poolalloc()   Allocate space for an item.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+VOID *poolalloc(pool)
+struct memorypool *pool;
+{
+  VOID *newitem;
+  VOID **newblock;
+  unsigned long alignptr;
+
+  /* First check the linked list of dead items.  If the list is not   */
+  /*   empty, allocate an item from the list rather than a fresh one. */
+  if (pool->deaditemstack != (VOID *) NULL) {
+    newitem = pool->deaditemstack;               /* Take first item in list. */
+    pool->deaditemstack = * (VOID **) pool->deaditemstack;
+  } else {
+    /* Check if there are any free items left in the current block. */
+    if (pool->unallocateditems == 0) {
+      /* Check if another block must be allocated. */
+      if (*(pool->nowblock) == (VOID *) NULL) {
+        /* Allocate a new block of items, pointed to by the previous block. */
+        newblock = (VOID **) malloc(pool->itemsperblock * pool->itembytes
+                                    + sizeof(VOID *) + pool->alignbytes);
+        if (newblock == (VOID **) NULL) {
+          printf("Error:  Out of memory.\n");
+          exit(1);
+        }
+        *(pool->nowblock) = (VOID *) newblock;
+        /* The next block pointer is NULL. */
+        *newblock = (VOID *) NULL;
+      }
+      /* Move to the new block. */
+      pool->nowblock = (VOID **) *(pool->nowblock);
+      /* Find the first item in the block.    */
+      /*   Increment by the size of (VOID *). */
+      alignptr = (unsigned long) (pool->nowblock + 1);
+      /* Align the item on an `alignbytes'-byte boundary. */
+      pool->nextitem = (VOID *)
+        (alignptr + (unsigned long) pool->alignbytes
+         - (alignptr % (unsigned long) pool->alignbytes));
+      /* There are lots of unallocated items left in this block. */
+      pool->unallocateditems = pool->itemsperblock;
+    }
+    /* Allocate a new item. */
+    newitem = pool->nextitem;
+    /* Advance `nextitem' pointer to next free item in block. */
+    if (pool->itemwordtype == POINTER) {
+      pool->nextitem = (VOID *) ((VOID **) pool->nextitem + pool->itemwords);
+    } else {
+      pool->nextitem = (VOID *) ((REAL *) pool->nextitem + pool->itemwords);
+    }
+    pool->unallocateditems--;
+    pool->maxitems++;
+  }
+  pool->items++;
+  return newitem;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pooldealloc()   Deallocate space for an item.                            */
+/*                                                                           */
+/*  The deallocated space is stored in a queue for later reuse.              */
+/*                                                                           */
+/*****************************************************************************/
+
+void pooldealloc(pool, dyingitem)
+struct memorypool *pool;
+VOID *dyingitem;
+{
+  /* Push freshly killed item onto stack. */
+  *((VOID **) dyingitem) = pool->deaditemstack;
+  pool->deaditemstack = dyingitem;
+  pool->items--;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  traversalinit()   Prepare to traverse the entire list of items.          */
+/*                                                                           */
+/*  This routine is used in conjunction with traverse().                     */
+/*                                                                           */
+/*****************************************************************************/
+
+void traversalinit(pool)
+struct memorypool *pool;
+{
+  unsigned long alignptr;
+
+  /* Begin the traversal in the first block. */
+  pool->pathblock = pool->firstblock;
+  /* Find the first item in the block.  Increment by the size of (VOID *). */
+  alignptr = (unsigned long) (pool->pathblock + 1);
+  /* Align with item on an `alignbytes'-byte boundary. */
+  pool->pathitem = (VOID *)
+    (alignptr + (unsigned long) pool->alignbytes
+     - (alignptr % (unsigned long) pool->alignbytes));
+  /* Set the number of items left in the current block. */
+  pool->pathitemsleft = pool->itemsperblock;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  traverse()   Find the next item in the list.                             */
+/*                                                                           */
+/*  This routine is used in conjunction with traversalinit().  Be forewarned */
+/*  that this routine successively returns all items in the list, including  */
+/*  deallocated ones on the deaditemqueue.  It's up to you to figure out     */
+/*  which ones are actually dead.  Why?  I don't want to allocate extra      */
+/*  space just to demarcate dead items.  It can usually be done more         */
+/*  space-efficiently by a routine that knows something about the structure  */
+/*  of the item.                                                             */
+/*                                                                           */
+/*****************************************************************************/
+
+VOID *traverse(pool)
+struct memorypool *pool;
+{
+  VOID *newitem;
+  unsigned long alignptr;
+
+  /* Stop upon exhausting the list of items. */
+  if (pool->pathitem == pool->nextitem) {
+    return (VOID *) NULL;
+  }
+  /* Check whether any untraversed items remain in the current block. */
+  if (pool->pathitemsleft == 0) {
+    /* Find the next block. */
+    pool->pathblock = (VOID **) *(pool->pathblock);
+    /* Find the first item in the block.  Increment by the size of (VOID *). */
+    alignptr = (unsigned long) (pool->pathblock + 1);
+    /* Align with item on an `alignbytes'-byte boundary. */
+    pool->pathitem = (VOID *)
+      (alignptr + (unsigned long) pool->alignbytes
+       - (alignptr % (unsigned long) pool->alignbytes));
+    /* Set the number of items left in the current block. */
+    pool->pathitemsleft = pool->itemsperblock;
+  }
+  newitem = pool->pathitem;
+  /* Find the next item in the block. */
+  if (pool->itemwordtype == POINTER) {
+    pool->pathitem = (VOID *) ((VOID **) pool->pathitem + pool->itemwords);
+  } else {
+    pool->pathitem = (VOID *) ((REAL *) pool->pathitem + pool->itemwords);
+  }
+  pool->pathitemsleft--;
+  return newitem;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  dummyinit()   Initialize the triangle that fills "outer space" and the   */
+/*                omnipresent shell edge.                                    */
+/*                                                                           */
+/*  The triangle that fills "outer space", called `dummytri', is pointed to  */
+/*  by every triangle and shell edge on a boundary (be it outer or inner) of */
+/*  the triangulation.  Also, `dummytri' points to one of the triangles on   */
+/*  the convex hull (until the holes and concavities are carved), making it  */
+/*  possible to find a starting triangle for point location.                 */
+/*                                                                           */
+/*  The omnipresent shell edge, `dummysh', is pointed to by every triangle   */
+/*  or shell edge that doesn't have a full complement of real shell edges    */
+/*  to point to.                                                             */
+/*                                                                           */
+/*****************************************************************************/
+
+void dummyinit(trianglewords, shellewords)
+int trianglewords;
+int shellewords;
+{
+  unsigned long alignptr;
+
+  /* `triwords' and `shwords' are used by the mesh manipulation primitives */
+  /*   to extract orientations of triangles and shell edges from pointers. */
+  triwords = trianglewords;       /* Initialize `triwords' once and for all. */
+  shwords = shellewords;           /* Initialize `shwords' once and for all. */
+
+  /* Set up `dummytri', the `triangle' that occupies "outer space". */
+  dummytribase = (triangle *) malloc(triwords * sizeof(triangle)
+                                     + triangles.alignbytes);
+  if (dummytribase == (triangle *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
+  alignptr = (unsigned long) dummytribase;
+  dummytri = (triangle *)
+    (alignptr + (unsigned long) triangles.alignbytes
+     - (alignptr % (unsigned long) triangles.alignbytes));
+  /* Initialize the three adjoining triangles to be "outer space".  These  */
+  /*   will eventually be changed by various bonding operations, but their */
+  /*   values don't really matter, as long as they can legally be          */
+  /*   dereferenced.                                                       */
+  dummytri[0] = (triangle) dummytri;
+  dummytri[1] = (triangle) dummytri;
+  dummytri[2] = (triangle) dummytri;
+  /* Three NULL vertex points. */
+  dummytri[3] = (triangle) NULL;
+  dummytri[4] = (triangle) NULL;
+  dummytri[5] = (triangle) NULL;
+
+  if (useshelles) {
+    /* Set up `dummysh', the omnipresent "shell edge" pointed to by any      */
+    /*   triangle side or shell edge end that isn't attached to a real shell */
+    /*   edge.                                                               */
+    dummyshbase = (shelle *) malloc(shwords * sizeof(shelle)
+                                    + shelles.alignbytes);
+    if (dummyshbase == (shelle *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+    /* Align `dummysh' on a `shelles.alignbytes'-byte boundary. */
+    alignptr = (unsigned long) dummyshbase;
+    dummysh = (shelle *)
+      (alignptr + (unsigned long) shelles.alignbytes
+       - (alignptr % (unsigned long) shelles.alignbytes));
+    /* Initialize the two adjoining shell edges to be the omnipresent shell */
+    /*   edge.  These will eventually be changed by various bonding         */
+    /*   operations, but their values don't really matter, as long as they  */
+    /*   can legally be dereferenced.                                       */
+    dummysh[0] = (shelle) dummysh;
+    dummysh[1] = (shelle) dummysh;
+    /* Two NULL vertex points. */
+    dummysh[2] = (shelle) NULL;
+    dummysh[3] = (shelle) NULL;
+    /* Initialize the two adjoining triangles to be "outer space". */
+    dummysh[4] = (shelle) dummytri;
+    dummysh[5] = (shelle) dummytri;
+    /* Set the boundary marker to zero. */
+    * (int *) (dummysh + 6) = 0;
+
+    /* Initialize the three adjoining shell edges of `dummytri' to be */
+    /*   the omnipresent shell edge.                                  */
+    dummytri[6] = (triangle) dummysh;
+    dummytri[7] = (triangle) dummysh;
+    dummytri[8] = (triangle) dummysh;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  initializepointpool()   Calculate the size of the point data structure   */
+/*                          and initialize its memory pool.                  */
+/*                                                                           */
+/*  This routine also computes the `pointmarkindex' and `point2triindex'     */
+/*  indices used to find values within each point.                           */
+/*                                                                           */
+/*****************************************************************************/
+
+void initializepointpool()
+{
+  int pointsize;
+
+  /* The index within each point at which the boundary marker is found.  */
+  /*   Ensure the point marker is aligned to a sizeof(int)-byte address. */
+  pointmarkindex = ((mesh_dim + nextras) * sizeof(REAL) + sizeof(int) - 1)
+                 / sizeof(int);
+  pointsize = (pointmarkindex + 1) * sizeof(int);
+  if (poly) {
+    /* The index within each point at which a triangle pointer is found.   */
+    /*   Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
+    point2triindex = (pointsize + sizeof(triangle) - 1) / sizeof(triangle);
+    pointsize = (point2triindex + 1) * sizeof(triangle);
+  }
+  /* Initialize the pool of points. */
+  poolinit(&points, pointsize, POINTPERBLOCK,
+           (sizeof(REAL) >= sizeof(triangle)) ? FLOATINGPOINT : POINTER, 0);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  initializetrisegpools()   Calculate the sizes of the triangle and shell  */
+/*                            edge data structures and initialize their      */
+/*                            memory pools.                                  */
+/*                                                                           */
+/*  This routine also computes the `highorderindex', `elemattribindex', and  */
+/*  `areaboundindex' indices used to find values within each triangle.       */
+/*                                                                           */
+/*****************************************************************************/
+
+void initializetrisegpools()
+{
+  int trisize;
+
+  /* The index within each triangle at which the extra nodes (above three)  */
+  /*   associated with high order elements are found.  There are three      */
+  /*   pointers to other triangles, three pointers to corners, and possibly */
+  /*   three pointers to shell edges before the extra nodes.                */
+  highorderindex = 6 + (useshelles * 3);
+  /* The number of bytes occupied by a triangle. */
+  trisize = ((order + 1) * (order + 2) / 2 + (highorderindex - 3)) *
+            sizeof(triangle);
+  /* The index within each triangle at which its attributes are found, */
+  /*   where the index is measured in REALs.                           */
+  elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
+  /* The index within each triangle at which the maximum area constraint  */
+  /*   is found, where the index is measured in REALs.  Note that if the  */
+  /*   `regionattrib' flag is set, an additional attribute will be added. */
+  areaboundindex = elemattribindex + eextras + regionattrib;
+  /* If triangle attributes or an area bound are needed, increase the number */
+  /*   of bytes occupied by a triangle.                                      */
+  if (vararea) {
+    trisize = (areaboundindex + 1) * sizeof(REAL);
+  } else if (eextras + regionattrib > 0) {
+    trisize = areaboundindex * sizeof(REAL);
+  }
+  /* If a Voronoi diagram or triangle neighbor graph is requested, make    */
+  /*   sure there's room to store an integer index in each triangle.  This */
+  /*   integer index can occupy the same space as the shell edges or       */
+  /*   attributes or area constraint or extra nodes.                       */
+  if ((voronoi || neighbors) &&
+      (trisize < 6 * sizeof(triangle) + sizeof(int))) {
+    trisize = 6 * sizeof(triangle) + sizeof(int);
+  }
+  /* Having determined the memory size of a triangle, initialize the pool. */
+  poolinit(&triangles, trisize, TRIPERBLOCK, POINTER, 4);
+
+  if (useshelles) {
+    /* Initialize the pool of shell edges. */
+    poolinit(&shelles, 6 * sizeof(triangle) + sizeof(int), SHELLEPERBLOCK,
+             POINTER, 4);
+
+    /* Initialize the "outer space" triangle and omnipresent shell edge. */
+    dummyinit(triangles.itemwords, shelles.itemwords);
+  } else {
+    /* Initialize the "outer space" triangle. */
+    dummyinit(triangles.itemwords, 0);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangledealloc()   Deallocate space for a triangle, marking it dead.    */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangledealloc(dyingtriangle)
+triangle *dyingtriangle;
+{
+  /* Set triangle's vertices to NULL.  This makes it possible to        */
+  /*   detect dead triangles when traversing the list of all triangles. */
+  dyingtriangle[3] = (triangle) NULL;
+  dyingtriangle[4] = (triangle) NULL;
+  dyingtriangle[5] = (triangle) NULL;
+  pooldealloc(&triangles, (VOID *) dyingtriangle);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangletraverse()   Traverse the triangles, skipping dead ones.         */
+/*                                                                           */
+/*****************************************************************************/
+
+triangle *triangletraverse()
+{
+  triangle *newtriangle;
+
+  do {
+    newtriangle = (triangle *) traverse(&triangles);
+    if (newtriangle == (triangle *) NULL) {
+      return (triangle *) NULL;
+    }
+  } while (newtriangle[3] == (triangle) NULL);            /* Skip dead ones. */
+  return newtriangle;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  shelledealloc()   Deallocate space for a shell edge, marking it dead.    */
+/*                                                                           */
+/*****************************************************************************/
+
+void shelledealloc(dyingshelle)
+shelle *dyingshelle;
+{
+  /* Set shell edge's vertices to NULL.  This makes it possible to */
+  /*   detect dead shells when traversing the list of all shells.  */
+  dyingshelle[2] = (shelle) NULL;
+  dyingshelle[3] = (shelle) NULL;
+  pooldealloc(&shelles, (VOID *) dyingshelle);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  shelletraverse()   Traverse the shell edges, skipping dead ones.         */
+/*                                                                           */
+/*****************************************************************************/
+
+shelle *shelletraverse()
+{
+  shelle *newshelle;
+
+  do {
+    newshelle = (shelle *) traverse(&shelles);
+    if (newshelle == (shelle *) NULL) {
+      return (shelle *) NULL;
+    }
+  } while (newshelle[2] == (shelle) NULL);                /* Skip dead ones. */
+  return newshelle;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointdealloc()   Deallocate space for a point, marking it dead.          */
+/*                                                                           */
+/*****************************************************************************/
+
+void pointdealloc(dyingpoint)
+point dyingpoint;
+{
+  /* Mark the point as dead.  This makes it possible to detect dead points */
+  /*   when traversing the list of all points.                             */
+  setpointmark(dyingpoint, DEADPOINT);
+  pooldealloc(&points, (VOID *) dyingpoint);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointtraverse()   Traverse the points, skipping dead ones.               */
+/*                                                                           */
+/*****************************************************************************/
+
+point pointtraverse()
+{
+  point newpoint;
+
+  do {
+    newpoint = (point) traverse(&points);
+    if (newpoint == (point) NULL) {
+      return (point) NULL;
+    }
+  } while (pointmark(newpoint) == DEADPOINT);             /* Skip dead ones. */
+  return newpoint;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  badsegmentdealloc()   Deallocate space for a bad segment, marking it     */
+/*                        dead.                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void badsegmentdealloc(dyingseg)
+struct edge *dyingseg;
+{
+  /* Set segment's orientation to -1.  This makes it possible to      */
+  /*   detect dead segments when traversing the list of all segments. */
+  dyingseg->shorient = -1;
+  pooldealloc(&badsegments, (VOID *) dyingseg);
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  badsegmenttraverse()   Traverse the bad segments, skipping dead ones.    */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+struct edge *badsegmenttraverse()
+{
+  struct edge *newseg;
+
+  do {
+    newseg = (struct edge *) traverse(&badsegments);
+    if (newseg == (struct edge *) NULL) {
+      return (struct edge *) NULL;
+    }
+  } while (newseg->shorient == -1);                       /* Skip dead ones. */
+  return newseg;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  getpoint()   Get a specific point, by number, from the list.             */
+/*                                                                           */
+/*  The first point is number 'firstnumber'.                                 */
+/*                                                                           */
+/*  Note that this takes O(n) time (with a small constant, if POINTPERBLOCK  */
+/*  is large).  I don't care to take the trouble to make it work in constant */
+/*  time.                                                                    */
+/*                                                                           */
+/*****************************************************************************/
+
+point getpoint(number)
+int number;
+{
+  VOID **getblock;
+  point foundpoint;
+  unsigned long alignptr;
+  int current;
+
+  getblock = points.firstblock;
+  current = firstnumber;
+  /* Find the right block. */
+  while (current + points.itemsperblock <= number) {
+    getblock = (VOID **) *getblock;
+    current += points.itemsperblock;
+  }
+  /* Now find the right point. */
+  alignptr = (unsigned long) (getblock + 1);
+  foundpoint = (point) (alignptr + (unsigned long) points.alignbytes
+                        - (alignptr % (unsigned long) points.alignbytes));
+  while (current < number) {
+    foundpoint += points.itemwords;
+    current++;
+  }
+  return foundpoint;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangledeinit()   Free all remaining allocated memory.                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangledeinit()
+{
+  pooldeinit(&triangles);
+  free(dummytribase);
+  if (useshelles) {
+    pooldeinit(&shelles);
+    free(dummyshbase);
+  }
+  pooldeinit(&points);
+#ifndef CDT_ONLY
+  if (quality) {
+    pooldeinit(&badsegments);
+    if ((minangle > 0.0) || vararea || fixedarea) {
+      pooldeinit(&badtriangles);
+    }
+  }
+#endif /* not CDT_ONLY */
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Memory management routines end here                       *********/
+
+/********* Constructors begin here                                   *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  maketriangle()   Create a new triangle with orientation zero.            */
+/*                                                                           */
+/*****************************************************************************/
+
+void maketriangle(newtriedge)
+struct triedge *newtriedge;
+{
+  int i;
+
+  newtriedge->tri = (triangle *) poolalloc(&triangles);
+  /* Initialize the three adjoining triangles to be "outer space". */
+  newtriedge->tri[0] = (triangle) dummytri;
+  newtriedge->tri[1] = (triangle) dummytri;
+  newtriedge->tri[2] = (triangle) dummytri;
+  /* Three NULL vertex points. */
+  newtriedge->tri[3] = (triangle) NULL;
+  newtriedge->tri[4] = (triangle) NULL;
+  newtriedge->tri[5] = (triangle) NULL;
+  /* Initialize the three adjoining shell edges to be the omnipresent */
+  /*   shell edge.                                                    */
+  if (useshelles) {
+    newtriedge->tri[6] = (triangle) dummysh;
+    newtriedge->tri[7] = (triangle) dummysh;
+    newtriedge->tri[8] = (triangle) dummysh;
+  }
+  for (i = 0; i < eextras; i++) {
+    setelemattribute(*newtriedge, i, 0.0);
+  }
+  if (vararea) {
+    setareabound(*newtriedge, -1.0);
+  }
+
+  newtriedge->orient = 0;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  makeshelle()   Create a new shell edge with orientation zero.            */
+/*                                                                           */
+/*****************************************************************************/
+
+void makeshelle(newedge)
+struct edge *newedge;
+{
+  newedge->sh = (shelle *) poolalloc(&shelles);
+  /* Initialize the two adjoining shell edges to be the omnipresent */
+  /*   shell edge.                                                  */
+  newedge->sh[0] = (shelle) dummysh;
+  newedge->sh[1] = (shelle) dummysh;
+  /* Two NULL vertex points. */
+  newedge->sh[2] = (shelle) NULL;
+  newedge->sh[3] = (shelle) NULL;
+  /* Initialize the two adjoining triangles to be "outer space". */
+  newedge->sh[4] = (shelle) dummytri;
+  newedge->sh[5] = (shelle) dummytri;
+  /* Set the boundary marker to zero. */
+  setmark(*newedge, 0);
+
+  newedge->shorient = 0;
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Constructors end here                                     *********/
+
+/********* Determinant evaluation routines begin here                *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/* The adaptive exact arithmetic geometric predicates implemented herein are */
+/*   described in detail in my Technical Report CMU-CS-96-140.  The complete */
+/*   reference is given in the header.                                       */
+
+/* Which of the following two methods of finding the absolute values is      */
+/*   fastest is compiler-dependent.  A few compilers can inline and optimize */
+/*   the fabs() call; but most will incur the overhead of a function call,   */
+/*   which is disastrously slow.  A faster way on IEEE machines might be to  */
+/*   mask the appropriate bit, but that's difficult to do in C.              */
+
+#define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
+/* #define Absolute(a)  fabs(a) */
+
+/* Many of the operations are broken up into two pieces, a main part that    */
+/*   performs an approximate operation, and a "tail" that computes the       */
+/*   roundoff error of that operation.                                       */
+/*                                                                           */
+/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(),    */
+/*   Split(), and Two_Product() are all implemented as described in the      */
+/*   reference.  Each of these macros requires certain variables to be       */
+/*   defined in the calling routine.  The variables `bvirt', `c', `abig',    */
+/*   `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because   */
+/*   they store the result of an operation that may incur roundoff error.    */
+/*   The input parameter `x' (or the highest numbered `x_' parameter) must   */
+/*   also be declared `INEXACT'.                                             */
+
+#define Fast_Two_Sum_Tail(a, b, x, y) \
+  bvirt = x - a; \
+  y = b - bvirt
+
+#define Fast_Two_Sum(a, b, x, y) \
+  x = (REAL) (a + b); \
+  Fast_Two_Sum_Tail(a, b, x, y)
+
+#define Two_Sum_Tail(a, b, x, y) \
+  bvirt = (REAL) (x - a); \
+  avirt = x - bvirt; \
+  bround = b - bvirt; \
+  around = a - avirt; \
+  y = around + bround
+
+#define Two_Sum(a, b, x, y) \
+  x = (REAL) (a + b); \
+  Two_Sum_Tail(a, b, x, y)
+
+#define Two_Diff_Tail(a, b, x, y) \
+  bvirt = (REAL) (a - x); \
+  avirt = x + bvirt; \
+  bround = bvirt - b; \
+  around = a - avirt; \
+  y = around + bround
+
+#define Two_Diff(a, b, x, y) \
+  x = (REAL) (a - b); \
+  Two_Diff_Tail(a, b, x, y)
+
+#define Split(a, ahi, alo) \
+  c = (REAL) (splitter * a); \
+  abig = (REAL) (c - a); \
+  ahi = c - abig; \
+  alo = a - ahi
+
+#define Two_Product_Tail(a, b, x, y) \
+  Split(a, ahi, alo); \
+  Split(b, bhi, blo); \
+  err1 = x - (ahi * bhi); \
+  err2 = err1 - (alo * bhi); \
+  err3 = err2 - (ahi * blo); \
+  y = (alo * blo) - err3
+
+#define Two_Product(a, b, x, y) \
+  x = (REAL) (a * b); \
+  Two_Product_Tail(a, b, x, y)
+
+/* Two_Product_Presplit() is Two_Product() where one of the inputs has       */
+/*   already been split.  Avoids redundant splitting.                        */
+
+#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
+  x = (REAL) (a * b); \
+  Split(a, ahi, alo); \
+  err1 = x - (ahi * bhi); \
+  err2 = err1 - (alo * bhi); \
+  err3 = err2 - (ahi * blo); \
+  y = (alo * blo) - err3
+
+/* Square() can be done more quickly than Two_Product().                     */
+
+#define Square_Tail(a, x, y) \
+  Split(a, ahi, alo); \
+  err1 = x - (ahi * ahi); \
+  err3 = err1 - ((ahi + ahi) * alo); \
+  y = (alo * alo) - err3
+
+#define Square(a, x, y) \
+  x = (REAL) (a * a); \
+  Square_Tail(a, x, y)
+
+/* Macros for summing expansions of various fixed lengths.  These are all    */
+/*   unrolled versions of Expansion_Sum().                                   */
+
+#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
+  Two_Sum(a0, b , _i, x0); \
+  Two_Sum(a1, _i, x2, x1)
+
+#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
+  Two_Diff(a0, b , _i, x0); \
+  Two_Sum( a1, _i, x2, x1)
+
+#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
+  Two_One_Sum(a1, a0, b0, _j, _0, x0); \
+  Two_One_Sum(_j, _0, b1, x3, x2, x1)
+
+#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
+  Two_One_Diff(a1, a0, b0, _j, _0, x0); \
+  Two_One_Diff(_j, _0, b1, x3, x2, x1)
+
+/*****************************************************************************/
+/*                                                                           */
+/*  exactinit()   Initialize the variables used for exact arithmetic.        */
+/*                                                                           */
+/*  `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in   */
+/*  floating-point arithmetic.  `epsilon' bounds the relative roundoff       */
+/*  error.  It is used for floating-point error analysis.                    */
+/*                                                                           */
+/*  `splitter' is used to split floating-point numbers into two half-        */
+/*  length significands for exact multiplication.                            */
+/*                                                                           */
+/*  I imagine that a highly optimizing compiler might be too smart for its   */
+/*  own good, and somehow cause this routine to fail, if it pretends that    */
+/*  floating-point arithmetic is too much like real arithmetic.              */
+/*                                                                           */
+/*  Don't change this routine unless you fully understand it.                */
+/*                                                                           */
+/*****************************************************************************/
+
+void exactinit()
+{
+  REAL half;
+  REAL check, lastcheck;
+  int every_other;
+
+  every_other = 1;
+  half = 0.5;
+  epsilon = 1.0;
+  splitter = 1.0;
+  check = 1.0;
+  /* Repeatedly divide `epsilon' by two until it is too small to add to      */
+  /*   one without causing roundoff.  (Also check if the sum is equal to     */
+  /*   the previous sum, for machines that round up instead of using exact   */
+  /*   rounding.  Not that these routines will work on such machines anyway. */
+  do {
+    lastcheck = check;
+    epsilon *= half;
+    if (every_other) {
+      splitter *= 2.0;
+    }
+    every_other = !every_other;
+    check = 1.0 + epsilon;
+  } while ((check != 1.0) && (check != lastcheck));
+  splitter += 1.0;
+  if (verbose > 1) {
+    printf("Floating point roundoff is of magnitude %.17g\n", epsilon);
+    printf("Floating point splitter is %.17g\n", splitter);
+  }
+  /* Error bounds for orientation and incircle tests. */
+  resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
+  ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
+  ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
+  ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
+  iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
+  iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
+  iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  fast_expansion_sum_zeroelim()   Sum two expansions, eliminating zero     */
+/*                                  components from the output expansion.    */
+/*                                                                           */
+/*  Sets h = e + f.  See my Robust Predicates paper for details.             */
+/*                                                                           */
+/*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
+/*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
+/*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
+/*  properties.                                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+int fast_expansion_sum_zeroelim(elen, e, flen, f, h)  /* h cannot be e or f. */
+int elen;
+REAL *e;
+int flen;
+REAL *f;
+REAL *h;
+{
+  REAL Q;
+  INEXACT REAL Qnew;
+  INEXACT REAL hh;
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  int eindex, findex, hindex;
+  REAL enow, fnow;
+
+  enow = e[0];
+  fnow = f[0];
+  eindex = findex = 0;
+  if ((fnow > enow) == (fnow > -enow)) {
+    Q = enow;
+    enow = e[++eindex];
+  } else {
+    Q = fnow;
+    fnow = f[++findex];
+  }
+  hindex = 0;
+  if ((eindex < elen) && (findex < flen)) {
+    if ((fnow > enow) == (fnow > -enow)) {
+      Fast_Two_Sum(enow, Q, Qnew, hh);
+      enow = e[++eindex];
+    } else {
+      Fast_Two_Sum(fnow, Q, Qnew, hh);
+      fnow = f[++findex];
+    }
+    Q = Qnew;
+    if (hh != 0.0) {
+      h[hindex++] = hh;
+    }
+    while ((eindex < elen) && (findex < flen)) {
+      if ((fnow > enow) == (fnow > -enow)) {
+        Two_Sum(Q, enow, Qnew, hh);
+        enow = e[++eindex];
+      } else {
+        Two_Sum(Q, fnow, Qnew, hh);
+        fnow = f[++findex];
+      }
+      Q = Qnew;
+      if (hh != 0.0) {
+        h[hindex++] = hh;
+      }
+    }
+  }
+  while (eindex < elen) {
+    Two_Sum(Q, enow, Qnew, hh);
+    enow = e[++eindex];
+    Q = Qnew;
+    if (hh != 0.0) {
+      h[hindex++] = hh;
+    }
+  }
+  while (findex < flen) {
+    Two_Sum(Q, fnow, Qnew, hh);
+    fnow = f[++findex];
+    Q = Qnew;
+    if (hh != 0.0) {
+      h[hindex++] = hh;
+    }
+  }
+  if ((Q != 0.0) || (hindex == 0)) {
+    h[hindex++] = Q;
+  }
+  return hindex;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  scale_expansion_zeroelim()   Multiply an expansion by a scalar,          */
+/*                               eliminating zero components from the        */
+/*                               output expansion.                           */
+/*                                                                           */
+/*  Sets h = be.  See my Robust Predicates paper for details.                */
+/*                                                                           */
+/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
+/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
+/*  properties as well.  (That is, if e has one of these properties, so      */
+/*  will h.)                                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+int scale_expansion_zeroelim(elen, e, b, h)   /* e and h cannot be the same. */
+int elen;
+REAL *e;
+REAL b;
+REAL *h;
+{
+  INEXACT REAL Q, sum;
+  REAL hh;
+  INEXACT REAL product1;
+  REAL product0;
+  int eindex, hindex;
+  REAL enow;
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  INEXACT REAL c;
+  INEXACT REAL abig;
+  REAL ahi, alo, bhi, blo;
+  REAL err1, err2, err3;
+
+  Split(b, bhi, blo);
+  Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
+  hindex = 0;
+  if (hh != 0) {
+    h[hindex++] = hh;
+  }
+  for (eindex = 1; eindex < elen; eindex++) {
+    enow = e[eindex];
+    Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
+    Two_Sum(Q, product0, sum, hh);
+    if (hh != 0) {
+      h[hindex++] = hh;
+    }
+    Fast_Two_Sum(product1, sum, Q, hh);
+    if (hh != 0) {
+      h[hindex++] = hh;
+    }
+  }
+  if ((Q != 0.0) || (hindex == 0)) {
+    h[hindex++] = Q;
+  }
+  return hindex;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  estimate()   Produce a one-word estimate of an expansion's value.        */
+/*                                                                           */
+/*  See my Robust Predicates paper for details.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+REAL estimate(elen, e)
+int elen;
+REAL *e;
+{
+  REAL Q;
+  int eindex;
+
+  Q = e[0];
+  for (eindex = 1; eindex < elen; eindex++) {
+    Q += e[eindex];
+  }
+  return Q;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  counterclockwise()   Return a positive value if the points pa, pb, and   */
+/*                       pc occur in counterclockwise order; a negative      */
+/*                       value if they occur in clockwise order; and zero    */
+/*                       if they are collinear.  The result is also a rough  */
+/*                       approximation of twice the signed area of the       */
+/*                       triangle defined by the three points.               */
+/*                                                                           */
+/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
+/*  result returned is the determinant of a matrix.  This determinant is     */
+/*  computed adaptively, in the sense that exact arithmetic is used only to  */
+/*  the degree it is needed to ensure that the returned value has the        */
+/*  correct sign.  Hence, this function is usually quite fast, but will run  */
+/*  more slowly when the input points are collinear or nearly so.            */
+/*                                                                           */
+/*  See my Robust Predicates paper for details.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+REAL counterclockwiseadapt(pa, pb, pc, detsum)
+point pa;
+point pb;
+point pc;
+REAL detsum;
+{
+  INEXACT REAL acx, acy, bcx, bcy;
+  REAL acxtail, acytail, bcxtail, bcytail;
+  INEXACT REAL detleft, detright;
+  REAL detlefttail, detrighttail;
+  REAL det, errbound;
+  REAL B[4], C1[8], C2[12], D[16];
+  INEXACT REAL B3;
+  int C1length, C2length, Dlength;
+  REAL u[4];
+  INEXACT REAL u3;
+  INEXACT REAL s1, t1;
+  REAL s0, t0;
+
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  INEXACT REAL c;
+  INEXACT REAL abig;
+  REAL ahi, alo, bhi, blo;
+  REAL err1, err2, err3;
+  INEXACT REAL _i, _j;
+  REAL _0;
+
+  acx = (REAL) (pa[0] - pc[0]);
+  bcx = (REAL) (pb[0] - pc[0]);
+  acy = (REAL) (pa[1] - pc[1]);
+  bcy = (REAL) (pb[1] - pc[1]);
+
+  Two_Product(acx, bcy, detleft, detlefttail);
+  Two_Product(acy, bcx, detright, detrighttail);
+
+  Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
+               B3, B[2], B[1], B[0]);
+  B[3] = B3;
+
+  det = estimate(4, B);
+  errbound = ccwerrboundB * detsum;
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
+  Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
+  Two_Diff_Tail(pa[1], pc[1], acy, acytail);
+  Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
+
+  if ((acxtail == 0.0) && (acytail == 0.0)
+      && (bcxtail == 0.0) && (bcytail == 0.0)) {
+    return det;
+  }
+
+  errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
+  det += (acx * bcytail + bcy * acxtail)
+       - (acy * bcxtail + bcx * acytail);
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  Two_Product(acxtail, bcy, s1, s0);
+  Two_Product(acytail, bcx, t1, t0);
+  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
+  u[3] = u3;
+  C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
+
+  Two_Product(acx, bcytail, s1, s0);
+  Two_Product(acy, bcxtail, t1, t0);
+  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
+  u[3] = u3;
+  C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
+
+  Two_Product(acxtail, bcytail, s1, s0);
+  Two_Product(acytail, bcxtail, t1, t0);
+  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
+  u[3] = u3;
+  Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
+
+  return(D[Dlength - 1]);
+}
+
+REAL counterclockwise(pa, pb, pc)
+point pa;
+point pb;
+point pc;
+{
+  REAL detleft, detright, det;
+  REAL detsum, errbound;
+
+  counterclockcount++;
+
+  detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
+  detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
+  det = detleft - detright;
+
+  if (noexact) {
+    return det;
+  }
+
+  if (detleft > 0.0) {
+    if (detright <= 0.0) {
+      return det;
+    } else {
+      detsum = detleft + detright;
+    }
+  } else if (detleft < 0.0) {
+    if (detright >= 0.0) {
+      return det;
+    } else {
+      detsum = -detleft - detright;
+    }
+  } else {
+    return det;
+  }
+
+  errbound = ccwerrboundA * detsum;
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  return counterclockwiseadapt(pa, pb, pc, detsum);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  incircle()   Return a positive value if the point pd lies inside the     */
+/*               circle passing through pa, pb, and pc; a negative value if  */
+/*               it lies outside; and zero if the four points are cocircular.*/
+/*               The points pa, pb, and pc must be in counterclockwise       */
+/*               order, or the sign of the result will be reversed.          */
+/*                                                                           */
+/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
+/*  result returned is the determinant of a matrix.  This determinant is     */
+/*  computed adaptively, in the sense that exact arithmetic is used only to  */
+/*  the degree it is needed to ensure that the returned value has the        */
+/*  correct sign.  Hence, this function is usually quite fast, but will run  */
+/*  more slowly when the input points are cocircular or nearly so.           */
+/*                                                                           */
+/*  See my Robust Predicates paper for details.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+REAL incircleadapt(pa, pb, pc, pd, permanent)
+point pa;
+point pb;
+point pc;
+point pd;
+REAL permanent;
+{
+  INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
+  REAL det, errbound;
+
+  INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
+  REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
+  REAL bc[4], ca[4], ab[4];
+  INEXACT REAL bc3, ca3, ab3;
+  REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
+  int axbclen, axxbclen, aybclen, ayybclen, alen;
+  REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
+  int bxcalen, bxxcalen, bycalen, byycalen, blen;
+  REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
+  int cxablen, cxxablen, cyablen, cyyablen, clen;
+  REAL abdet[64];
+  int ablen;
+  REAL fin1[1152], fin2[1152];
+  REAL *finnow, *finother, *finswap;
+  int finlength;
+
+  REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
+  INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
+  REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
+  REAL aa[4], bb[4], cc[4];
+  INEXACT REAL aa3, bb3, cc3;
+  INEXACT REAL ti1, tj1;
+  REAL ti0, tj0;
+  REAL u[4], v[4];
+  INEXACT REAL u3, v3;
+  REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
+  REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
+  int temp8len, temp16alen, temp16blen, temp16clen;
+  int temp32alen, temp32blen, temp48len, temp64len;
+  REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
+  int axtbblen, axtcclen, aytbblen, aytcclen;
+  REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
+  int bxtaalen, bxtcclen, bytaalen, bytcclen;
+  REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
+  int cxtaalen, cxtbblen, cytaalen, cytbblen;
+  REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
+  int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
+  REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
+  int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
+  REAL axtbctt[8], aytbctt[8], bxtcatt[8];
+  REAL bytcatt[8], cxtabtt[8], cytabtt[8];
+  int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
+  REAL abt[8], bct[8], cat[8];
+  int abtlen, bctlen, catlen;
+  REAL abtt[4], bctt[4], catt[4];
+  int abttlen, bcttlen, cattlen;
+  INEXACT REAL abtt3, bctt3, catt3;
+  REAL negate;
+
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  INEXACT REAL c;
+  INEXACT REAL abig;
+  REAL ahi, alo, bhi, blo;
+  REAL err1, err2, err3;
+  INEXACT REAL _i, _j;
+  REAL _0;
+
+  adx = (REAL) (pa[0] - pd[0]);
+  bdx = (REAL) (pb[0] - pd[0]);
+  cdx = (REAL) (pc[0] - pd[0]);
+  ady = (REAL) (pa[1] - pd[1]);
+  bdy = (REAL) (pb[1] - pd[1]);
+  cdy = (REAL) (pc[1] - pd[1]);
+
+  Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
+  Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
+  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
+  bc[3] = bc3;
+  axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
+  axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
+  aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
+  ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
+  alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
+
+  Two_Product(cdx, ady, cdxady1, cdxady0);
+  Two_Product(adx, cdy, adxcdy1, adxcdy0);
+  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
+  ca[3] = ca3;
+  bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
+  bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
+  bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
+  byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
+  blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
+
+  Two_Product(adx, bdy, adxbdy1, adxbdy0);
+  Two_Product(bdx, ady, bdxady1, bdxady0);
+  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
+  ab[3] = ab3;
+  cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
+  cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
+  cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
+  cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
+  clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
+
+  ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
+  finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
+
+  det = estimate(finlength, fin1);
+  errbound = iccerrboundB * permanent;
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
+  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
+  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
+  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
+  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
+  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
+  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
+      && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
+    return det;
+  }
+
+  errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
+  det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
+                                     - (bdy * cdxtail + cdx * bdytail))
+          + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
+       + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
+                                     - (cdy * adxtail + adx * cdytail))
+          + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
+       + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
+                                     - (ady * bdxtail + bdx * adytail))
+          + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  finnow = fin1;
+  finother = fin2;
+
+  if ((bdxtail != 0.0) || (bdytail != 0.0)
+      || (cdxtail != 0.0) || (cdytail != 0.0)) {
+    Square(adx, adxadx1, adxadx0);
+    Square(ady, adyady1, adyady0);
+    Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
+    aa[3] = aa3;
+  }
+  if ((cdxtail != 0.0) || (cdytail != 0.0)
+      || (adxtail != 0.0) || (adytail != 0.0)) {
+    Square(bdx, bdxbdx1, bdxbdx0);
+    Square(bdy, bdybdy1, bdybdy0);
+    Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
+    bb[3] = bb3;
+  }
+  if ((adxtail != 0.0) || (adytail != 0.0)
+      || (bdxtail != 0.0) || (bdytail != 0.0)) {
+    Square(cdx, cdxcdx1, cdxcdx0);
+    Square(cdy, cdycdy1, cdycdy0);
+    Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
+    cc[3] = cc3;
+  }
+
+  if (adxtail != 0.0) {
+    axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
+    temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
+                                          temp16a);
+
+    axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
+    temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
+
+    axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
+    temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (adytail != 0.0) {
+    aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
+    temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
+                                          temp16a);
+
+    aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
+    temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
+
+    aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
+    temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (bdxtail != 0.0) {
+    bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
+    temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
+                                          temp16a);
+
+    bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
+    temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
+
+    bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
+    temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (bdytail != 0.0) {
+    bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
+    temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
+                                          temp16a);
+
+    bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
+    temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
+
+    bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
+    temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (cdxtail != 0.0) {
+    cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
+    temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
+                                          temp16a);
+
+    cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
+    temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
+
+    cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
+    temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (cdytail != 0.0) {
+    cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
+    temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
+                                          temp16a);
+
+    cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
+    temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
+
+    cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
+    temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+
+  if ((adxtail != 0.0) || (adytail != 0.0)) {
+    if ((bdxtail != 0.0) || (bdytail != 0.0)
+        || (cdxtail != 0.0) || (cdytail != 0.0)) {
+      Two_Product(bdxtail, cdy, ti1, ti0);
+      Two_Product(bdx, cdytail, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
+      u[3] = u3;
+      negate = -bdy;
+      Two_Product(cdxtail, negate, ti1, ti0);
+      negate = -bdytail;
+      Two_Product(cdx, negate, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
+      v[3] = v3;
+      bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
+
+      Two_Product(bdxtail, cdytail, ti1, ti0);
+      Two_Product(cdxtail, bdytail, tj1, tj0);
+      Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
+      bctt[3] = bctt3;
+      bcttlen = 4;
+    } else {
+      bct[0] = 0.0;
+      bctlen = 1;
+      bctt[0] = 0.0;
+      bcttlen = 1;
+    }
+
+    if (adxtail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
+      axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
+      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+      if (bdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+      if (cdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+
+      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
+                                            temp32a);
+      axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
+      temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+    if (adytail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
+      aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
+      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+
+
+      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
+                                            temp32a);
+      aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
+      temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+  }
+  if ((bdxtail != 0.0) || (bdytail != 0.0)) {
+    if ((cdxtail != 0.0) || (cdytail != 0.0)
+        || (adxtail != 0.0) || (adytail != 0.0)) {
+      Two_Product(cdxtail, ady, ti1, ti0);
+      Two_Product(cdx, adytail, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
+      u[3] = u3;
+      negate = -cdy;
+      Two_Product(adxtail, negate, ti1, ti0);
+      negate = -cdytail;
+      Two_Product(adx, negate, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
+      v[3] = v3;
+      catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
+
+      Two_Product(cdxtail, adytail, ti1, ti0);
+      Two_Product(adxtail, cdytail, tj1, tj0);
+      Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
+      catt[3] = catt3;
+      cattlen = 4;
+    } else {
+      cat[0] = 0.0;
+      catlen = 1;
+      catt[0] = 0.0;
+      cattlen = 1;
+    }
+
+    if (bdxtail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
+      bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
+      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+      if (cdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+      if (adytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+
+      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
+                                            temp32a);
+      bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
+      temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+    if (bdytail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
+      bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
+      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+
+
+      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
+                                            temp32a);
+      bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
+      temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+  }
+  if ((cdxtail != 0.0) || (cdytail != 0.0)) {
+    if ((adxtail != 0.0) || (adytail != 0.0)
+        || (bdxtail != 0.0) || (bdytail != 0.0)) {
+      Two_Product(adxtail, bdy, ti1, ti0);
+      Two_Product(adx, bdytail, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
+      u[3] = u3;
+      negate = -ady;
+      Two_Product(bdxtail, negate, ti1, ti0);
+      negate = -adytail;
+      Two_Product(bdx, negate, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
+      v[3] = v3;
+      abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
+
+      Two_Product(adxtail, bdytail, ti1, ti0);
+      Two_Product(bdxtail, adytail, tj1, tj0);
+      Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
+      abtt[3] = abtt3;
+      abttlen = 4;
+    } else {
+      abt[0] = 0.0;
+      abtlen = 1;
+      abtt[0] = 0.0;
+      abttlen = 1;
+    }
+
+    if (cdxtail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
+      cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
+      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+      if (adytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+      if (bdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+
+      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
+                                            temp32a);
+      cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
+      temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+    if (cdytail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
+      cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
+      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+
+
+      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
+                                            temp32a);
+      cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
+      temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+  }
+
+  return finnow[finlength - 1];
+}
+
+REAL incircle(pa, pb, pc, pd)
+point pa;
+point pb;
+point pc;
+point pd;
+{
+  REAL adx, bdx, cdx, ady, bdy, cdy;
+  REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
+  REAL alift, blift, clift;
+  REAL det;
+  REAL permanent, errbound;
+
+  incirclecount++;
+
+  adx = pa[0] - pd[0];
+  bdx = pb[0] - pd[0];
+  cdx = pc[0] - pd[0];
+  ady = pa[1] - pd[1];
+  bdy = pb[1] - pd[1];
+  cdy = pc[1] - pd[1];
+
+  bdxcdy = bdx * cdy;
+  cdxbdy = cdx * bdy;
+  alift = adx * adx + ady * ady;
+
+  cdxady = cdx * ady;
+  adxcdy = adx * cdy;
+  blift = bdx * bdx + bdy * bdy;
+
+  adxbdy = adx * bdy;
+  bdxady = bdx * ady;
+  clift = cdx * cdx + cdy * cdy;
+
+  det = alift * (bdxcdy - cdxbdy)
+      + blift * (cdxady - adxcdy)
+      + clift * (adxbdy - bdxady);
+
+  if (noexact) {
+    return det;
+  }
+
+  permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
+            + (Absolute(cdxady) + Absolute(adxcdy)) * blift
+            + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
+  errbound = iccerrboundA * permanent;
+  if ((det > errbound) || (-det > errbound)) {
+    return det;
+  }
+
+  return incircleadapt(pa, pb, pc, pd, permanent);
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Determinant evaluation routines end here                  *********/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangleinit()   Initialize some variables.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangleinit()
+{
+  points.maxitems = triangles.maxitems = shelles.maxitems = viri.maxitems =
+    badsegments.maxitems = badtriangles.maxitems = splaynodes.maxitems = 0l;
+  points.itembytes = triangles.itembytes = shelles.itembytes = viri.itembytes =
+    badsegments.itembytes = badtriangles.itembytes = splaynodes.itembytes = 0;
+  recenttri.tri = (triangle *) NULL;    /* No triangle has been visited yet. */
+  samples = 1;            /* Point location should take at least one sample. */
+  checksegments = 0;      /* There are no segments in the triangulation yet. */
+  incirclecount = counterclockcount = hyperbolacount = 0;
+  circumcentercount = circletopcount = 0;
+  randomseed = 1;
+
+  exactinit();                     /* Initialize exact arithmetic constants. */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  randomnation()   Generate a random number between 0 and `choices' - 1.   */
+/*                                                                           */
+/*  This is a simple linear congruential random number generator.  Hence, it */
+/*  is a bad random number generator, but good enough for most randomized    */
+/*  geometric algorithms.                                                    */
+/*                                                                           */
+/*****************************************************************************/
+
+unsigned long randomnation(choices)
+unsigned int choices;
+{
+  randomseed = (randomseed * 1366l + 150889l) % 714025l;
+  return randomseed / (714025l / choices + 1);
+}
+
+/********* Mesh quality testing routines begin here                  *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  checkmesh()   Test the mesh for topological consistency.                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+void checkmesh()
+{
+  struct triedge triangleloop;
+  struct triedge oppotri, oppooppotri;
+  point triorg, tridest, triapex;
+  point oppoorg, oppodest;
+  int horrors;
+  int saveexact;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  /* Temporarily turn on exact arithmetic if it's off. */
+  saveexact = noexact;
+  noexact = 0;
+  if (!quiet) {
+    printf("  Checking consistency of mesh...\n");
+  }
+  horrors = 0;
+  /* Run through the list of triangles, checking each one. */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* Check all three edges of the triangle. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      org(triangleloop, triorg);
+      dest(triangleloop, tridest);
+      if (triangleloop.orient == 0) {       /* Only test for inversion once. */
+        /* Test if the triangle is flat or inverted. */
+        apex(triangleloop, triapex);
+        if (counterclockwise(triorg, tridest, triapex) <= 0.0) {
+          printf("  !! !! Inverted ");
+          printtriangle(&triangleloop);
+          horrors++;
+        }
+      }
+      /* Find the neighboring triangle on this edge. */
+      sym(triangleloop, oppotri);
+      if (oppotri.tri != dummytri) {
+        /* Check that the triangle's neighbor knows it's a neighbor. */
+        sym(oppotri, oppooppotri);
+        if ((triangleloop.tri != oppooppotri.tri)
+            || (triangleloop.orient != oppooppotri.orient)) {
+          printf("  !! !! Asymmetric triangle-triangle bond:\n");
+          if (triangleloop.tri == oppooppotri.tri) {
+            printf("   (Right triangle, wrong orientation)\n");
+          }
+          printf("    First ");
+          printtriangle(&triangleloop);
+          printf("    Second (nonreciprocating) ");
+          printtriangle(&oppotri);
+          horrors++;
+        }
+        /* Check that both triangles agree on the identities */
+        /*   of their shared vertices.                       */
+        org(oppotri, oppoorg);
+        dest(oppotri, oppodest);
+        if ((triorg != oppodest) || (tridest != oppoorg)) {
+          printf("  !! !! Mismatched edge coordinates between two triangles:\n"
+                 );
+          printf("    First mismatched ");
+          printtriangle(&triangleloop);
+          printf("    Second mismatched ");
+          printtriangle(&oppotri);
+          horrors++;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+  if (horrors == 0) {
+    if (!quiet) {
+      printf("  In my studied opinion, the mesh appears to be consistent.\n");
+    }
+  } else if (horrors == 1) {
+    printf("  !! !! !! !! Precisely one festering wound discovered.\n");
+  } else {
+    printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
+  }
+  /* Restore the status of exact arithmetic. */
+  noexact = saveexact;
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  checkdelaunay()   Ensure that the mesh is (constrained) Delaunay.        */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+void checkdelaunay()
+{
+  struct triedge triangleloop;
+  struct triedge oppotri;
+  struct edge opposhelle;
+  point triorg, tridest, triapex;
+  point oppoapex;
+  int shouldbedelaunay;
+  int horrors;
+  int saveexact;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  /* Temporarily turn on exact arithmetic if it's off. */
+  saveexact = noexact;
+  noexact = 0;
+  if (!quiet) {
+    printf("  Checking Delaunay property of mesh...\n");
+  }
+  horrors = 0;
+  /* Run through the list of triangles, checking each one. */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* Check all three edges of the triangle. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      org(triangleloop, triorg);
+      dest(triangleloop, tridest);
+      apex(triangleloop, triapex);
+      sym(triangleloop, oppotri);
+      apex(oppotri, oppoapex);
+      /* Only test that the edge is locally Delaunay if there is an   */
+      /*   adjoining triangle whose pointer is larger (to ensure that */
+      /*   each pair isn't tested twice).                             */
+      shouldbedelaunay = (oppotri.tri != dummytri)
+            && (triapex != (point) NULL) && (oppoapex != (point) NULL)
+            && (triangleloop.tri < oppotri.tri);
+      if (checksegments && shouldbedelaunay) {
+        /* If a shell edge separates the triangles, then the edge is */
+        /*   constrained, so no local Delaunay test should be done.  */
+        tspivot(triangleloop, opposhelle);
+        if (opposhelle.sh != dummysh){
+          shouldbedelaunay = 0;
+        }
+      }
+      if (shouldbedelaunay) {
+        if (incircle(triorg, tridest, triapex, oppoapex) > 0.0) {
+          printf("  !! !! Non-Delaunay pair of triangles:\n");
+          printf("    First non-Delaunay ");
+          printtriangle(&triangleloop);
+          printf("    Second non-Delaunay ");
+          printtriangle(&oppotri);
+          horrors++;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+  if (horrors == 0) {
+    if (!quiet) {
+      printf(
+  "  By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
+    }
+  } else if (horrors == 1) {
+    printf(
+         "  !! !! !! !! Precisely one terrifying transgression identified.\n");
+  } else {
+    printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
+  }
+  /* Restore the status of exact arithmetic. */
+  noexact = saveexact;
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  enqueuebadtri()   Add a bad triangle to the end of a queue.              */
+/*                                                                           */
+/*  The queue is actually a set of 64 queues.  I use multiple queues to give */
+/*  priority to smaller angles.  I originally implemented a heap, but the    */
+/*  queues are (to my surprise) much faster.                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void enqueuebadtri(instri, angle, insapex, insorg, insdest)
+struct triedge *instri;
+REAL angle;
+point insapex;
+point insorg;
+point insdest;
+{
+  struct badface *newface;
+  int queuenumber;
+
+  if (verbose > 2) {
+    printf("  Queueing bad triangle:\n");
+    printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", insorg[0],
+           insorg[1], insdest[0], insdest[1], insapex[0], insapex[1]);
+  }
+  /* Allocate space for the bad triangle. */
+  newface = (struct badface *) poolalloc(&badtriangles);
+  triedgecopy(*instri, newface->badfacetri);
+  newface->key = angle;
+  newface->faceapex = insapex;
+  newface->faceorg = insorg;
+  newface->facedest = insdest;
+  newface->nextface = (struct badface *) NULL;
+  /* Determine the appropriate queue to put the bad triangle into. */
+  if (angle > 0.6) {
+    queuenumber = (int) (160.0 * (angle - 0.6));
+    if (queuenumber > 63) {
+      queuenumber = 63;
+    }
+  } else {
+    /* It's not a bad angle; put the triangle in the lowest-priority queue. */
+    queuenumber = 0;
+  }
+  /* Add the triangle to the end of a queue. */
+  *queuetail[queuenumber] = newface;
+  /* Maintain a pointer to the NULL pointer at the end of the queue. */
+  queuetail[queuenumber] = &newface->nextface;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  dequeuebadtri()   Remove a triangle from the front of the queue.         */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+struct badface *dequeuebadtri()
+{
+  struct badface *result;
+  int queuenumber;
+
+  /* Look for a nonempty queue. */
+  for (queuenumber = 63; queuenumber >= 0; queuenumber--) {
+    result = queuefront[queuenumber];
+    if (result != (struct badface *) NULL) {
+      /* Remove the triangle from the queue. */
+      queuefront[queuenumber] = result->nextface;
+      /* Maintain a pointer to the NULL pointer at the end of the queue. */
+      if (queuefront[queuenumber] == (struct badface *) NULL) {
+        queuetail[queuenumber] = &queuefront[queuenumber];
+      }
+      return result;
+    }
+  }
+  return (struct badface *) NULL;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  checkedge4encroach()   Check a segment to see if it is encroached; add   */
+/*                         it to the list if it is.                          */
+/*                                                                           */
+/*  An encroached segment is an unflippable edge that has a point in its     */
+/*  diametral circle (that is, it faces an angle greater than 90 degrees).   */
+/*  This definition is due to Ruppert.                                       */
+/*                                                                           */
+/*  Returns a nonzero value if the edge is encroached.                       */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+int checkedge4encroach(testedge)
+struct edge *testedge;
+{
+  struct triedge neighbortri;
+  struct edge testsym;
+  struct edge *badedge;
+  int addtolist;
+  int sides;
+  point eorg, edest, eapex;
+  triangle ptr;                     /* Temporary variable used by stpivot(). */
+
+  addtolist = 0;
+  sides = 0;
+
+  sorg(*testedge, eorg);
+  sdest(*testedge, edest);
+  /* Check one neighbor of the shell edge. */
+  stpivot(*testedge, neighbortri);
+  /* Does the neighbor exist, or is this a boundary edge? */
+  if (neighbortri.tri != dummytri) {
+    sides++;
+    /* Find a vertex opposite this edge. */
+    apex(neighbortri, eapex);
+    /* Check whether the vertex is inside the diametral circle of the  */
+    /*   shell edge.  Pythagoras' Theorem is used to check whether the */
+    /*   angle at the vertex is greater than 90 degrees.               */
+    if (eapex[0] * (eorg[0] + edest[0]) + eapex[1] * (eorg[1] + edest[1]) >
+        eapex[0] * eapex[0] + eorg[0] * edest[0] +
+        eapex[1] * eapex[1] + eorg[1] * edest[1]) {
+      addtolist = 1;
+    }
+  }
+  /* Check the other neighbor of the shell edge. */
+  ssym(*testedge, testsym);
+  stpivot(testsym, neighbortri);
+  /* Does the neighbor exist, or is this a boundary edge? */
+  if (neighbortri.tri != dummytri) {
+    sides++;
+    /* Find the other vertex opposite this edge. */
+    apex(neighbortri, eapex);
+    /* Check whether the vertex is inside the diametral circle of the  */
+    /*   shell edge.  Pythagoras' Theorem is used to check whether the */
+    /*   angle at the vertex is greater than 90 degrees.               */
+    if (eapex[0] * (eorg[0] + edest[0]) +
+        eapex[1] * (eorg[1] + edest[1]) >
+        eapex[0] * eapex[0] + eorg[0] * edest[0] +
+        eapex[1] * eapex[1] + eorg[1] * edest[1]) {
+      addtolist += 2;
+    }
+  }
+
+  if (addtolist && (!nobisect || ((nobisect == 1) && (sides == 2)))) {
+    if (verbose > 2) {
+      printf("  Queueing encroached segment (%.12g, %.12g) (%.12g, %.12g).\n",
+             eorg[0], eorg[1], edest[0], edest[1]);
+    }
+    /* Add the shell edge to the list of encroached segments. */
+    /*   Be sure to get the orientation right.                */
+    badedge = (struct edge *) poolalloc(&badsegments);
+    if (addtolist == 1) {
+      shellecopy(*testedge, *badedge);
+    } else {
+      shellecopy(testsym, *badedge);
+    }
+  }
+  return addtolist;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  testtriangle()   Test a face for quality measures.                       */
+/*                                                                           */
+/*  Tests a triangle to see if it satisfies the minimum angle condition and  */
+/*  the maximum area condition.  Triangles that aren't up to spec are added  */
+/*  to the bad triangle queue.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void testtriangle(testtri)
+struct triedge *testtri;
+{
+  struct triedge sametesttri;
+  struct edge edge1, edge2;
+  point torg, tdest, tapex;
+  point anglevertex;
+  REAL dxod, dyod, dxda, dyda, dxao, dyao;
+  REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
+  REAL apexlen, orglen, destlen;
+  REAL angle;
+  REAL area;
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  org(*testtri, torg);
+  dest(*testtri, tdest);
+  apex(*testtri, tapex);
+  dxod = torg[0] - tdest[0];
+  dyod = torg[1] - tdest[1];
+  dxda = tdest[0] - tapex[0];
+  dyda = tdest[1] - tapex[1];
+  dxao = tapex[0] - torg[0];
+  dyao = tapex[1] - torg[1];
+  dxod2 = dxod * dxod;
+  dyod2 = dyod * dyod;
+  dxda2 = dxda * dxda;
+  dyda2 = dyda * dyda;
+  dxao2 = dxao * dxao;
+  dyao2 = dyao * dyao;
+  /* Find the lengths of the triangle's three edges. */
+  apexlen = dxod2 + dyod2;
+  orglen = dxda2 + dyda2;
+  destlen = dxao2 + dyao2;
+  if ((apexlen < orglen) && (apexlen < destlen)) {
+    /* The edge opposite the apex is shortest. */
+    /* Find the square of the cosine of the angle at the apex. */
+    angle = dxda * dxao + dyda * dyao;
+    angle = angle * angle / (orglen * destlen);
+    anglevertex = tapex;
+    lnext(*testtri, sametesttri);
+    tspivot(sametesttri, edge1);
+    lnextself(sametesttri);
+    tspivot(sametesttri, edge2);
+  } else if (orglen < destlen) {
+    /* The edge opposite the origin is shortest. */
+    /* Find the square of the cosine of the angle at the origin. */
+    angle = dxod * dxao + dyod * dyao;
+    angle = angle * angle / (apexlen * destlen);
+    anglevertex = torg;
+    tspivot(*testtri, edge1);
+    lprev(*testtri, sametesttri);
+    tspivot(sametesttri, edge2);
+  } else {
+    /* The edge opposite the destination is shortest. */
+    /* Find the square of the cosine of the angle at the destination. */
+    angle = dxod * dxda + dyod * dyda;
+    angle = angle * angle / (apexlen * orglen);
+    anglevertex = tdest;
+    tspivot(*testtri, edge1);
+    lnext(*testtri, sametesttri);
+    tspivot(sametesttri, edge2);
+  }
+  /* Check if both edges that form the angle are segments. */
+  if ((edge1.sh != dummysh) && (edge2.sh != dummysh)) {
+    /* The angle is a segment intersection. */
+    if ((angle > 0.9924) && !quiet) {                  /* Roughly 5 degrees. */
+      if (angle > 1.0) {
+        /* Beware of a floating exception in acos(). */
+        angle = 1.0;
+      }
+      /* Find the actual angle in degrees, for printing. */
+      angle = acos(sqrt(angle)) * (180.0 / PI);
+      printf(
+      "Warning:  Small angle (%.4g degrees) between segments at point\n",
+             angle);
+      printf("  (%.12g, %.12g)\n", anglevertex[0], anglevertex[1]);
+    }
+    /* Don't add this bad triangle to the list; there's nothing that */
+    /*   can be done about a small angle between two segments.       */
+    angle = 0.0;
+  }
+  /* Check whether the angle is smaller than permitted. */
+  if (angle > goodangle) {
+    /* Add this triangle to the list of bad triangles. */
+    enqueuebadtri(testtri, angle, tapex, torg, tdest);
+    return;
+  }
+  if (vararea || fixedarea) {
+    /* Check whether the area is larger than permitted. */
+    area = 0.5 * (dxod * dyda - dyod * dxda);
+    if (fixedarea && (area > maxarea)) {
+      /* Add this triangle to the list of bad triangles. */
+      enqueuebadtri(testtri, angle, tapex, torg, tdest);
+    } else if (vararea) {
+      /* Nonpositive area constraints are treated as unconstrained. */
+      if ((area > areabound(*testtri)) && (areabound(*testtri) > 0.0)) {
+        /* Add this triangle to the list of bad triangles. */
+        enqueuebadtri(testtri, angle, tapex, torg, tdest);
+      }
+    }
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh quality testing routines end here                    *********/
+
+/********* Point location routines begin here                        *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  makepointmap()   Construct a mapping from points to triangles to improve  */
+/*                  the speed of point location for segment insertion.       */
+/*                                                                           */
+/*  Traverses all the triangles, and provides each corner of each triangle   */
+/*  with a pointer to that triangle.  Of course, pointers will be            */
+/*  overwritten by other pointers because (almost) each point is a corner    */
+/*  of several triangles, but in the end every point will point to some      */
+/*  triangle that contains it.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+void makepointmap()
+{
+  struct triedge triangleloop;
+  point triorg;
+
+  if (verbose) {
+    printf("    Constructing mapping from points to triangles.\n");
+  }
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* Check all three points of the triangle. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      org(triangleloop, triorg);
+      setpoint2tri(triorg, encode(triangleloop));
+    }
+    triangleloop.tri = triangletraverse();
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  preciselocate()   Find a triangle or edge containing a given point.      */
+/*                                                                           */
+/*  Begins its search from `searchtri'.  It is important that `searchtri'    */
+/*  be a handle with the property that `searchpoint' is strictly to the left */
+/*  of the edge denoted by `searchtri', or is collinear with that edge and   */
+/*  does not intersect that edge.  (In particular, `searchpoint' should not  */
+/*  be the origin or destination of that edge.)                              */
+/*                                                                           */
+/*  These conditions are imposed because preciselocate() is normally used in */
+/*  one of two situations:                                                   */
+/*                                                                           */
+/*  (1)  To try to find the location to insert a new point.  Normally, we    */
+/*       know an edge that the point is strictly to the left of.  In the     */
+/*       incremental Delaunay algorithm, that edge is a bounding box edge.   */
+/*       In Ruppert's Delaunay refinement algorithm for quality meshing,     */
+/*       that edge is the shortest edge of the triangle whose circumcenter   */
+/*       is being inserted.                                                  */
+/*                                                                           */
+/*  (2)  To try to find an existing point.  In this case, any edge on the    */
+/*       convex hull is a good starting edge.  The possibility that the      */
+/*       vertex one seeks is an endpoint of the starting edge must be        */
+/*       screened out before preciselocate() is called.                      */
+/*                                                                           */
+/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
+/*                                                                           */
+/*  This implementation differs from that given by Guibas and Stolfi.  It    */
+/*  walks from triangle to triangle, crossing an edge only if `searchpoint'  */
+/*  is on the other side of the line containing that edge.  After entering   */
+/*  a triangle, there are two edges by which one can leave that triangle.    */
+/*  If both edges are valid (`searchpoint' is on the other side of both      */
+/*  edges), one of the two is chosen by drawing a line perpendicular to      */
+/*  the entry edge (whose endpoints are `forg' and `fdest') passing through  */
+/*  `fapex'.  Depending on which side of this perpendicular `searchpoint'    */
+/*  falls on, an exit edge is chosen.                                        */
+/*                                                                           */
+/*  This implementation is empirically faster than the Guibas and Stolfi     */
+/*  point location routine (which I originally used), which tends to spiral  */
+/*  in toward its target.                                                    */
+/*                                                                           */
+/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
+/*  is a handle whose origin is the existing vertex.                         */
+/*                                                                           */
+/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
+/*  handle whose primary edge is the edge on which the point lies.           */
+/*                                                                           */
+/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
+/*  `searchtri' is a handle on the triangle that contains the point.         */
+/*                                                                           */
+/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
+/*  handle whose primary edge the point is to the right of.  This might      */
+/*  occur when the circumcenter of a triangle falls just slightly outside    */
+/*  the mesh due to floating-point roundoff error.  It also occurs when      */
+/*  seeking a hole or region point that a foolish user has placed outside    */
+/*  the mesh.                                                                */
+/*                                                                           */
+/*  WARNING:  This routine is designed for convex triangulations, and will   */
+/*  not generally work after the holes and concavities have been carved.     */
+/*  However, it can still be used to find the circumcenter of a triangle, as */
+/*  long as the search is begun from the triangle in question.               */
+/*                                                                           */
+/*****************************************************************************/
+
+enum locateresult preciselocate(searchpoint, searchtri)
+point searchpoint;
+struct triedge *searchtri;
+{
+  struct triedge backtracktri;
+  point forg, fdest, fapex;
+  point swappoint;
+  REAL orgorient, destorient;
+  int moveleft;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose > 2) {
+    printf("  Searching for point (%.12g, %.12g).\n",
+           searchpoint[0], searchpoint[1]);
+  }
+  /* Where are we? */
+  org(*searchtri, forg);
+  dest(*searchtri, fdest);
+  apex(*searchtri, fapex);
+  while (1) {
+    if (verbose > 2) {
+      printf("    At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+             forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
+    }
+    /* Check whether the apex is the point we seek. */
+    if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
+      lprevself(*searchtri);
+      return ONVERTEX;
+    }
+    /* Does the point lie on the other side of the line defined by the */
+    /*   triangle edge opposite the triangle's destination?            */
+    destorient = counterclockwise(forg, fapex, searchpoint);
+    /* Does the point lie on the other side of the line defined by the */
+    /*   triangle edge opposite the triangle's origin?                 */
+    orgorient = counterclockwise(fapex, fdest, searchpoint);
+    if (destorient > 0.0) {
+      if (orgorient > 0.0) {
+        /* Move left if the inner product of (fapex - searchpoint) and  */
+        /*   (fdest - forg) is positive.  This is equivalent to drawing */
+        /*   a line perpendicular to the line (forg, fdest) passing     */
+        /*   through `fapex', and determining which side of this line   */
+        /*   `searchpoint' falls on.                                    */
+        moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
+                   (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
+      } else {
+        moveleft = 1;
+      }
+    } else {
+      if (orgorient > 0.0) {
+        moveleft = 0;
+      } else {
+        /* The point we seek must be on the boundary of or inside this */
+        /*   triangle.                                                 */
+        if (destorient == 0.0) {
+          lprevself(*searchtri);
+          return ONEDGE;
+        }
+        if (orgorient == 0.0) {
+          lnextself(*searchtri);
+          return ONEDGE;
+        }
+        return INTRIANGLE;
+      }
+    }
+
+    /* Move to another triangle.  Leave a trace `backtracktri' in case */
+    /*   floating-point roundoff or some such bogey causes us to walk  */
+    /*   off a boundary of the triangulation.  We can just bounce off  */
+    /*   the boundary as if it were an elastic band.                   */
+    if (moveleft) {
+      lprev(*searchtri, backtracktri);
+      fdest = fapex;
+    } else {
+      lnext(*searchtri, backtracktri);
+      forg = fapex;
+    }
+    sym(backtracktri, *searchtri);
+
+    /* Check for walking off the edge. */
+    if (searchtri->tri == dummytri) {
+      /* Turn around. */
+      triedgecopy(backtracktri, *searchtri);
+      swappoint = forg;
+      forg = fdest;
+      fdest = swappoint;
+      apex(*searchtri, fapex);
+      /* Check if the point really is beyond the triangulation boundary. */
+      destorient = counterclockwise(forg, fapex, searchpoint);
+      orgorient = counterclockwise(fapex, fdest, searchpoint);
+      if ((orgorient < 0.0) && (destorient < 0.0)) {
+        return OUTSIDE;
+      }
+    } else {
+      apex(*searchtri, fapex);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  locate()   Find a triangle or edge containing a given point.             */
+/*                                                                           */
+/*  Searching begins from one of:  the input `searchtri', a recently         */
+/*  encountered triangle `recenttri', or from a triangle chosen from a       */
+/*  random sample.  The choice is made by determining which triangle's       */
+/*  origin is closest to the point we are searcing for.  Normally,           */
+/*  `searchtri' should be a handle on the convex hull of the triangulation.  */
+/*                                                                           */
+/*  Details on the random sampling method can be found in the Mucke, Saias,  */
+/*  and Zhu paper cited in the header of this code.                          */
+/*                                                                           */
+/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
+/*                                                                           */
+/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
+/*  is a handle whose origin is the existing vertex.                         */
+/*                                                                           */
+/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
+/*  handle whose primary edge is the edge on which the point lies.           */
+/*                                                                           */
+/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
+/*  `searchtri' is a handle on the triangle that contains the point.         */
+/*                                                                           */
+/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
+/*  handle whose primary edge the point is to the right of.  This might      */
+/*  occur when the circumcenter of a triangle falls just slightly outside    */
+/*  the mesh due to floating-point roundoff error.  It also occurs when      */
+/*  seeking a hole or region point that a foolish user has placed outside    */
+/*  the mesh.                                                                */
+/*                                                                           */
+/*  WARNING:  This routine is designed for convex triangulations, and will   */
+/*  not generally work after the holes and concavities have been carved.     */
+/*                                                                           */
+/*****************************************************************************/
+
+enum locateresult locate(searchpoint, searchtri)
+point searchpoint;
+struct triedge *searchtri;
+{
+  VOID **sampleblock;
+  triangle *firsttri;
+  struct triedge sampletri;
+  point torg, tdest;
+  unsigned long alignptr;
+  REAL searchdist, dist;
+  REAL ahead;
+  long sampleblocks, samplesperblock, samplenum;
+  long triblocks;
+  long i, j;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose > 2) {
+    printf("  Randomly sampling for a triangle near point (%.12g, %.12g).\n",
+           searchpoint[0], searchpoint[1]);
+  }
+  /* Record the distance from the suggested starting triangle to the */
+  /*   point we seek.                                                */
+  org(*searchtri, torg);
+  searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
+             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
+  if (verbose > 2) {
+    printf("    Boundary triangle has origin (%.12g, %.12g).\n",
+           torg[0], torg[1]);
+  }
+
+  /* If a recently encountered triangle has been recorded and has not been */
+  /*   deallocated, test it as a good starting point.                      */
+  if (recenttri.tri != (triangle *) NULL) {
+    if (recenttri.tri[3] != (triangle) NULL) {
+      org(recenttri, torg);
+      if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
+        triedgecopy(recenttri, *searchtri);
+        return ONVERTEX;
+      }
+      dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
+           + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
+      if (dist < searchdist) {
+        triedgecopy(recenttri, *searchtri);
+        searchdist = dist;
+        if (verbose > 2) {
+          printf("    Choosing recent triangle with origin (%.12g, %.12g).\n",
+                 torg[0], torg[1]);
+        }
+      }
+    }
+  }
+
+  /* The number of random samples taken is proportional to the cube root of */
+  /*   the number of triangles in the mesh.  The next bit of code assumes   */
+  /*   that the number of triangles increases monotonically.                */
+  while (SAMPLEFACTOR * samples * samples * samples < triangles.items) {
+    samples++;
+  }
+  triblocks = (triangles.maxitems + TRIPERBLOCK - 1) / TRIPERBLOCK;
+  samplesperblock = 1 + (samples / triblocks);
+  sampleblocks = samples / samplesperblock;
+  sampleblock = triangles.firstblock;
+  sampletri.orient = 0;
+  for (i = 0; i < sampleblocks; i++) {
+    alignptr = (unsigned long) (sampleblock + 1);
+    firsttri = (triangle *) (alignptr + (unsigned long) triangles.alignbytes
+                          - (alignptr % (unsigned long) triangles.alignbytes));
+    for (j = 0; j < samplesperblock; j++) {
+      if (i == triblocks - 1) {
+        samplenum = randomnation((int)
+                                 (triangles.maxitems - (i * TRIPERBLOCK)));
+      } else {
+        samplenum = randomnation(TRIPERBLOCK);
+      }
+      sampletri.tri = (triangle *)
+                      (firsttri + (samplenum * triangles.itemwords));
+      if (sampletri.tri[3] != (triangle) NULL) {
+        org(sampletri, torg);
+        dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
+             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
+        if (dist < searchdist) {
+          triedgecopy(sampletri, *searchtri);
+          searchdist = dist;
+          if (verbose > 2) {
+            printf("    Choosing triangle with origin (%.12g, %.12g).\n",
+                   torg[0], torg[1]);
+          }
+        }
+      }
+    }
+    sampleblock = (VOID **) *sampleblock;
+  }
+  /* Where are we? */
+  org(*searchtri, torg);
+  dest(*searchtri, tdest);
+  /* Check the starting triangle's vertices. */
+  if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
+    return ONVERTEX;
+  }
+  if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
+    lnextself(*searchtri);
+    return ONVERTEX;
+  }
+  /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
+  ahead = counterclockwise(torg, tdest, searchpoint);
+  if (ahead < 0.0) {
+    /* Turn around so that `searchpoint' is to the left of the */
+    /*   edge specified by `searchtri'.                        */
+    symself(*searchtri);
+  } else if (ahead == 0.0) {
+    /* Check if `searchpoint' is between `torg' and `tdest'. */
+    if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0]))
+        && ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
+      return ONEDGE;
+    }
+  }
+  return preciselocate(searchpoint, searchtri);
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Point location routines end here                          *********/
+
+/********* Mesh transformation routines begin here                   *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  insertshelle()   Create a new shell edge and insert it between two       */
+/*                   triangles.                                              */
+/*                                                                           */
+/*  The new shell edge is inserted at the edge described by the handle       */
+/*  `tri'.  Its vertices are properly initialized.  The marker `shellemark'  */
+/*  is applied to the shell edge and, if appropriate, its vertices.          */
+/*                                                                           */
+/*****************************************************************************/
+
+void insertshelle(tri, shellemark)
+struct triedge *tri;          /* Edge at which to insert the new shell edge. */
+int shellemark;                            /* Marker for the new shell edge. */
+{
+  struct triedge oppotri;
+  struct edge newshelle;
+  point triorg, tridest;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  /* Mark points if possible. */
+  org(*tri, triorg);
+  dest(*tri, tridest);
+  if (pointmark(triorg) == 0) {
+    setpointmark(triorg, shellemark);
+  }
+  if (pointmark(tridest) == 0) {
+    setpointmark(tridest, shellemark);
+  }
+  /* Check if there's already a shell edge here. */
+  tspivot(*tri, newshelle);
+  if (newshelle.sh == dummysh) {
+    /* Make new shell edge and initialize its vertices. */
+    makeshelle(&newshelle);
+    setsorg(newshelle, tridest);
+    setsdest(newshelle, triorg);
+    /* Bond new shell edge to the two triangles it is sandwiched between. */
+    /*   Note that the facing triangle `oppotri' might be equal to        */
+    /*   `dummytri' (outer space), but the new shell edge is bonded to it */
+    /*   all the same.                                                    */
+    tsbond(*tri, newshelle);
+    sym(*tri, oppotri);
+    ssymself(newshelle);
+    tsbond(oppotri, newshelle);
+    setmark(newshelle, shellemark);
+    if (verbose > 2) {
+      printf("  Inserting new ");
+      printshelle(&newshelle);
+    }
+  } else {
+    if (mark(newshelle) == 0) {
+      setmark(newshelle, shellemark);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  Terminology                                                              */
+/*                                                                           */
+/*  A "local transformation" replaces a small set of triangles with another  */
+/*  set of triangles.  This may or may not involve inserting or deleting a   */
+/*  point.                                                                   */
+/*                                                                           */
+/*  The term "casing" is used to describe the set of triangles that are      */
+/*  attached to the triangles being transformed, but are not transformed     */
+/*  themselves.  Think of the casing as a fixed hollow structure inside      */
+/*  which all the action happens.  A "casing" is only defined relative to    */
+/*  a single transformation; each occurrence of a transformation will        */
+/*  involve a different casing.                                              */
+/*                                                                           */
+/*  A "shell" is similar to a "casing".  The term "shell" describes the set  */
+/*  of shell edges (if any) that are attached to the triangles being         */
+/*  transformed.  However, I sometimes use "shell" to refer to a single      */
+/*  shell edge, so don't get confused.                                       */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  flip()   Transform two triangles to two different triangles by flipping  */
+/*           an edge within a quadrilateral.                                 */
+/*                                                                           */
+/*  Imagine the original triangles, abc and bad, oriented so that the        */
+/*  shared edge ab lies in a horizontal plane, with the point b on the left  */
+/*  and the point a on the right.  The point c lies below the edge, and the  */
+/*  point d lies above the edge.  The `flipedge' handle holds the edge ab    */
+/*  of triangle abc, and is directed left, from vertex a to vertex b.        */
+/*                                                                           */
+/*  The triangles abc and bad are deleted and replaced by the triangles cdb  */
+/*  and dca.  The triangles that represent abc and bad are NOT deallocated;  */
+/*  they are reused for dca and cdb, respectively.  Hence, any handles that  */
+/*  may have held the original triangles are still valid, although not       */
+/*  directed as they were before.                                            */
+/*                                                                           */
+/*  Upon completion of this routine, the `flipedge' handle holds the edge    */
+/*  dc of triangle dca, and is directed down, from vertex d to vertex c.     */
+/*  (Hence, the two triangles have rotated counterclockwise.)                */
+/*                                                                           */
+/*  WARNING:  This transformation is geometrically valid only if the         */
+/*  quadrilateral adbc is convex.  Furthermore, this transformation is       */
+/*  valid only if there is not a shell edge between the triangles abc and    */
+/*  bad.  This routine does not check either of these preconditions, and     */
+/*  it is the responsibility of the calling routine to ensure that they are  */
+/*  met.  If they are not, the streets shall be filled with wailing and      */
+/*  gnashing of teeth.                                                       */
+/*                                                                           */
+/*****************************************************************************/
+
+void flip(flipedge)
+struct triedge *flipedge;                    /* Handle for the triangle abc. */
+{
+  struct triedge botleft, botright;
+  struct triedge topleft, topright;
+  struct triedge top;
+  struct triedge botlcasing, botrcasing;
+  struct triedge toplcasing, toprcasing;
+  struct edge botlshelle, botrshelle;
+  struct edge toplshelle, toprshelle;
+  point leftpoint, rightpoint, botpoint;
+  point farpoint;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  /* Identify the vertices of the quadrilateral. */
+  org(*flipedge, rightpoint);
+  dest(*flipedge, leftpoint);
+  apex(*flipedge, botpoint);
+  sym(*flipedge, top);
+#ifdef SELF_CHECK
+  if (top.tri == dummytri) {
+    printf("Internal error in flip():  Attempt to flip on boundary.\n");
+    lnextself(*flipedge);
+    return;
+  }
+  if (checksegments) {
+    tspivot(*flipedge, toplshelle);
+    if (toplshelle.sh != dummysh) {
+      printf("Internal error in flip():  Attempt to flip a segment.\n");
+      lnextself(*flipedge);
+      return;
+    }
+  }
+#endif /* SELF_CHECK */
+  apex(top, farpoint);
+
+  /* Identify the casing of the quadrilateral. */
+  lprev(top, topleft);
+  sym(topleft, toplcasing);
+  lnext(top, topright);
+  sym(topright, toprcasing);
+  lnext(*flipedge, botleft);
+  sym(botleft, botlcasing);
+  lprev(*flipedge, botright);
+  sym(botright, botrcasing);
+  /* Rotate the quadrilateral one-quarter turn counterclockwise. */
+  bond(topleft, botlcasing);
+  bond(botleft, botrcasing);
+  bond(botright, toprcasing);
+  bond(topright, toplcasing);
+
+  if (checksegments) {
+    /* Check for shell edges and rebond them to the quadrilateral. */
+    tspivot(topleft, toplshelle);
+    tspivot(botleft, botlshelle);
+    tspivot(botright, botrshelle);
+    tspivot(topright, toprshelle);
+    if (toplshelle.sh == dummysh) {
+      tsdissolve(topright);
+    } else {
+      tsbond(topright, toplshelle);
+    }
+    if (botlshelle.sh == dummysh) {
+      tsdissolve(topleft);
+    } else {
+      tsbond(topleft, botlshelle);
+    }
+    if (botrshelle.sh == dummysh) {
+      tsdissolve(botleft);
+    } else {
+      tsbond(botleft, botrshelle);
+    }
+    if (toprshelle.sh == dummysh) {
+      tsdissolve(botright);
+    } else {
+      tsbond(botright, toprshelle);
+    }
+  }
+
+  /* New point assignments for the rotated quadrilateral. */
+  setorg(*flipedge, farpoint);
+  setdest(*flipedge, botpoint);
+  setapex(*flipedge, rightpoint);
+  setorg(top, botpoint);
+  setdest(top, farpoint);
+  setapex(top, leftpoint);
+  if (verbose > 2) {
+    printf("  Edge flip results in left ");
+    lnextself(topleft);
+    printtriangle(&topleft);
+    printf("  and right ");
+    printtriangle(flipedge);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  insertsite()   Insert a vertex into a Delaunay triangulation,            */
+/*                 performing flips as necessary to maintain the Delaunay    */
+/*                 property.                                                 */
+/*                                                                           */
+/*  The point `insertpoint' is located.  If `searchtri.tri' is not NULL,     */
+/*  the search for the containing triangle begins from `searchtri'.  If      */
+/*  `searchtri.tri' is NULL, a full point location procedure is called.      */
+/*  If `insertpoint' is found inside a triangle, the triangle is split into  */
+/*  three; if `insertpoint' lies on an edge, the edge is split in two,       */
+/*  thereby splitting the two adjacent triangles into four.  Edge flips are  */
+/*  used to restore the Delaunay property.  If `insertpoint' lies on an      */
+/*  existing vertex, no action is taken, and the value DUPLICATEPOINT is     */
+/*  returned.  On return, `searchtri' is set to a handle whose origin is the */
+/*  existing vertex.                                                         */
+/*                                                                           */
+/*  Normally, the parameter `splitedge' is set to NULL, implying that no     */
+/*  segment should be split.  In this case, if `insertpoint' is found to     */
+/*  lie on a segment, no action is taken, and the value VIOLATINGPOINT is    */
+/*  returned.  On return, `searchtri' is set to a handle whose primary edge  */
+/*  is the violated segment.                                                 */
+/*                                                                           */
+/*  If the calling routine wishes to split a segment by inserting a point in */
+/*  it, the parameter `splitedge' should be that segment.  In this case,     */
+/*  `searchtri' MUST be the triangle handle reached by pivoting from that    */
+/*  segment; no point location is done.                                      */
+/*                                                                           */
+/*  `segmentflaws' and `triflaws' are flags that indicate whether or not     */
+/*  there should be checks for the creation of encroached segments or bad    */
+/*  quality faces.  If a newly inserted point encroaches upon segments,      */
+/*  these segments are added to the list of segments to be split if          */
+/*  `segmentflaws' is set.  If bad triangles are created, these are added    */
+/*  to the queue if `triflaws' is set.                                       */
+/*                                                                           */
+/*  If a duplicate point or violated segment does not prevent the point      */
+/*  from being inserted, the return value will be ENCROACHINGPOINT if the    */
+/*  point encroaches upon a segment (and checking is enabled), or            */
+/*  SUCCESSFULPOINT otherwise.  In either case, `searchtri' is set to a      */
+/*  handle whose origin is the newly inserted vertex.                        */
+/*                                                                           */
+/*  insertsite() does not use flip() for reasons of speed; some              */
+/*  information can be reused from edge flip to edge flip, like the          */
+/*  locations of shell edges.                                                */
+/*                                                                           */
+/*****************************************************************************/
+
+enum insertsiteresult insertsite(insertpoint, searchtri, splitedge,
+                                 segmentflaws, triflaws)
+point insertpoint;
+struct triedge *searchtri;
+struct edge *splitedge;
+int segmentflaws;
+int triflaws;
+{
+  struct triedge horiz;
+  struct triedge top;
+  struct triedge botleft, botright;
+  struct triedge topleft, topright;
+  struct triedge newbotleft, newbotright;
+  struct triedge newtopright;
+  struct triedge botlcasing, botrcasing;
+  struct triedge toplcasing, toprcasing;
+  struct triedge testtri;
+  struct edge botlshelle, botrshelle;
+  struct edge toplshelle, toprshelle;
+  struct edge brokenshelle;
+  struct edge checkshelle;
+  struct edge rightedge;
+  struct edge newedge;
+  struct edge *encroached;
+  point first;
+  point leftpoint, rightpoint, botpoint, toppoint, farpoint;
+  REAL attrib;
+  REAL area;
+  enum insertsiteresult success;
+  enum locateresult intersect;
+  int doflip;
+  int mirrorflag;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;         /* Temporary variable used by spivot() and tspivot(). */
+
+  if (verbose > 1) {
+    printf("  Inserting (%.12g, %.12g).\n", insertpoint[0], insertpoint[1]);
+  }
+  if (splitedge == (struct edge *) NULL) {
+    /* Find the location of the point to be inserted.  Check if a good */
+    /*   starting triangle has already been provided by the caller.    */
+    if (searchtri->tri == (triangle *) NULL) {
+      /* Find a boundary triangle. */
+      horiz.tri = dummytri;
+      horiz.orient = 0;
+      symself(horiz);
+      /* Search for a triangle containing `insertpoint'. */
+      intersect = locate(insertpoint, &horiz);
+    } else {
+      /* Start searching from the triangle provided by the caller. */
+      triedgecopy(*searchtri, horiz);
+      intersect = preciselocate(insertpoint, &horiz);
+    }
+  } else {
+    /* The calling routine provides the edge in which the point is inserted. */
+    triedgecopy(*searchtri, horiz);
+    intersect = ONEDGE;
+  }
+  if (intersect == ONVERTEX) {
+    /* There's already a vertex there.  Return in `searchtri' a triangle */
+    /*   whose origin is the existing vertex.                            */
+    triedgecopy(horiz, *searchtri);
+    triedgecopy(horiz, recenttri);
+    return DUPLICATEPOINT;
+  }
+  if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
+    /* The vertex falls on an edge or boundary. */
+    if (checksegments && (splitedge == (struct edge *) NULL)) {
+      /* Check whether the vertex falls on a shell edge. */
+      tspivot(horiz, brokenshelle);
+      if (brokenshelle.sh != dummysh) {
+        /* The vertex falls on a shell edge. */
+        if (segmentflaws) {
+          if (nobisect == 0) {
+            /* Add the shell edge to the list of encroached segments. */
+            encroached = (struct edge *) poolalloc(&badsegments);
+            shellecopy(brokenshelle, *encroached);
+          } else if ((nobisect == 1) && (intersect == ONEDGE)) {
+            /* This segment may be split only if it is an internal boundary. */
+            sym(horiz, testtri);
+            if (testtri.tri != dummytri) {
+              /* Add the shell edge to the list of encroached segments. */
+              encroached = (struct edge *) poolalloc(&badsegments);
+              shellecopy(brokenshelle, *encroached);
+            }
+          }
+        }
+        /* Return a handle whose primary edge contains the point, */
+        /*   which has not been inserted.                         */
+        triedgecopy(horiz, *searchtri);
+        triedgecopy(horiz, recenttri);
+        return VIOLATINGPOINT;
+      }
+    }
+    /* Insert the point on an edge, dividing one triangle into two (if */
+    /*   the edge lies on a boundary) or two triangles into four.      */
+    lprev(horiz, botright);
+    sym(botright, botrcasing);
+    sym(horiz, topright);
+    /* Is there a second triangle?  (Or does this edge lie on a boundary?) */
+    mirrorflag = topright.tri != dummytri;
+    if (mirrorflag) {
+      lnextself(topright);
+      sym(topright, toprcasing);
+      maketriangle(&newtopright);
+    } else {
+      /* Splitting the boundary edge increases the number of boundary edges. */
+      hullsize++;
+    }
+    maketriangle(&newbotright);
+
+    /* Set the vertices of changed and new triangles. */
+    org(horiz, rightpoint);
+    dest(horiz, leftpoint);
+    apex(horiz, botpoint);
+    setorg(newbotright, botpoint);
+    setdest(newbotright, rightpoint);
+    setapex(newbotright, insertpoint);
+    setorg(horiz, insertpoint);
+    for (i = 0; i < eextras; i++) {
+      /* Set the element attributes of a new triangle. */
+      setelemattribute(newbotright, i, elemattribute(botright, i));
+    }
+    if (vararea) {
+      /* Set the area constraint of a new triangle. */
+      setareabound(newbotright, areabound(botright));
+    }
+    if (mirrorflag) {
+      dest(topright, toppoint);
+      setorg(newtopright, rightpoint);
+      setdest(newtopright, toppoint);
+      setapex(newtopright, insertpoint);
+      setorg(topright, insertpoint);
+      for (i = 0; i < eextras; i++) {
+        /* Set the element attributes of another new triangle. */
+        setelemattribute(newtopright, i, elemattribute(topright, i));
+      }
+      if (vararea) {
+        /* Set the area constraint of another new triangle. */
+        setareabound(newtopright, areabound(topright));
+      }
+    }
+
+    /* There may be shell edges that need to be bonded */
+    /*   to the new triangle(s).                       */
+    if (checksegments) {
+      tspivot(botright, botrshelle);
+      if (botrshelle.sh != dummysh) {
+        tsdissolve(botright);
+        tsbond(newbotright, botrshelle);
+      }
+      if (mirrorflag) {
+        tspivot(topright, toprshelle);
+        if (toprshelle.sh != dummysh) {
+          tsdissolve(topright);
+          tsbond(newtopright, toprshelle);
+        }
+      }
+    }
+
+    /* Bond the new triangle(s) to the surrounding triangles. */
+    bond(newbotright, botrcasing);
+    lprevself(newbotright);
+    bond(newbotright, botright);
+    lprevself(newbotright);
+    if (mirrorflag) {
+      bond(newtopright, toprcasing);
+      lnextself(newtopright);
+      bond(newtopright, topright);
+      lnextself(newtopright);
+      bond(newtopright, newbotright);
+    }
+
+    if (splitedge != (struct edge *) NULL) {
+      /* Split the shell edge into two. */
+      setsdest(*splitedge, insertpoint);
+      ssymself(*splitedge);
+      spivot(*splitedge, rightedge);
+      insertshelle(&newbotright, mark(*splitedge));
+      tspivot(newbotright, newedge);
+      sbond(*splitedge, newedge);
+      ssymself(newedge);
+      sbond(newedge, rightedge);
+      ssymself(*splitedge);
+    }
+
+#ifdef SELF_CHECK
+    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle prior to edge point insertion (bottom).\n");
+    }
+    if (mirrorflag) {
+      if (counterclockwise(leftpoint, rightpoint, toppoint) < 0.0) {
+        printf("Internal error in insertsite():\n");
+        printf("  Clockwise triangle prior to edge point insertion (top).\n");
+      }
+      if (counterclockwise(rightpoint, toppoint, insertpoint) < 0.0) {
+        printf("Internal error in insertsite():\n");
+        printf("  Clockwise triangle after edge point insertion (top right).\n"
+               );
+      }
+      if (counterclockwise(toppoint, leftpoint, insertpoint) < 0.0) {
+        printf("Internal error in insertsite():\n");
+        printf("  Clockwise triangle after edge point insertion (top left).\n"
+               );
+      }
+    }
+    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after edge point insertion (bottom left).\n"
+             );
+    }
+    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf(
+        "  Clockwise triangle after edge point insertion (bottom right).\n");
+    }
+#endif /* SELF_CHECK */
+    if (verbose > 2) {
+      printf("  Updating bottom left ");
+      printtriangle(&botright);
+      if (mirrorflag) {
+        printf("  Updating top left ");
+        printtriangle(&topright);
+        printf("  Creating top right ");
+        printtriangle(&newtopright);
+      }
+      printf("  Creating bottom right ");
+      printtriangle(&newbotright);
+    }
+
+    /* Position `horiz' on the first edge to check for */
+    /*   the Delaunay property.                        */
+    lnextself(horiz);
+  } else {
+    /* Insert the point in a triangle, splitting it into three. */
+    lnext(horiz, botleft);
+    lprev(horiz, botright);
+    sym(botleft, botlcasing);
+    sym(botright, botrcasing);
+    maketriangle(&newbotleft);
+    maketriangle(&newbotright);
+
+    /* Set the vertices of changed and new triangles. */
+    org(horiz, rightpoint);
+    dest(horiz, leftpoint);
+    apex(horiz, botpoint);
+    setorg(newbotleft, leftpoint);
+    setdest(newbotleft, botpoint);
+    setapex(newbotleft, insertpoint);
+    setorg(newbotright, botpoint);
+    setdest(newbotright, rightpoint);
+    setapex(newbotright, insertpoint);
+    setapex(horiz, insertpoint);
+    for (i = 0; i < eextras; i++) {
+      /* Set the element attributes of the new triangles. */
+      attrib = elemattribute(horiz, i);
+      setelemattribute(newbotleft, i, attrib);
+      setelemattribute(newbotright, i, attrib);
+    }
+    if (vararea) {
+      /* Set the area constraint of the new triangles. */
+      area = areabound(horiz);
+      setareabound(newbotleft, area);
+      setareabound(newbotright, area);
+    }
+
+    /* There may be shell edges that need to be bonded */
+    /*   to the new triangles.                         */
+    if (checksegments) {
+      tspivot(botleft, botlshelle);
+      if (botlshelle.sh != dummysh) {
+        tsdissolve(botleft);
+        tsbond(newbotleft, botlshelle);
+      }
+      tspivot(botright, botrshelle);
+      if (botrshelle.sh != dummysh) {
+        tsdissolve(botright);
+        tsbond(newbotright, botrshelle);
+      }
+    }
+
+    /* Bond the new triangles to the surrounding triangles. */
+    bond(newbotleft, botlcasing);
+    bond(newbotright, botrcasing);
+    lnextself(newbotleft);
+    lprevself(newbotright);
+    bond(newbotleft, newbotright);
+    lnextself(newbotleft);
+    bond(botleft, newbotleft);
+    lprevself(newbotright);
+    bond(botright, newbotright);
+
+#ifdef SELF_CHECK
+    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle prior to point insertion.\n");
+    }
+    if (counterclockwise(rightpoint, leftpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after point insertion (top).\n");
+    }
+    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after point insertion (left).\n");
+    }
+    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after point insertion (right).\n");
+    }
+#endif /* SELF_CHECK */
+    if (verbose > 2) {
+      printf("  Updating top ");
+      printtriangle(&horiz);
+      printf("  Creating left ");
+      printtriangle(&newbotleft);
+      printf("  Creating right ");
+      printtriangle(&newbotright);
+    }
+  }
+
+  /* The insertion is successful by default, unless an encroached */
+  /*   edge is found.                                             */
+  success = SUCCESSFULPOINT;
+  /* Circle around the newly inserted vertex, checking each edge opposite */
+  /*   it for the Delaunay property.  Non-Delaunay edges are flipped.     */
+  /*   `horiz' is always the edge being checked.  `first' marks where to  */
+  /*   stop circling.                                                     */
+  org(horiz, first);
+  rightpoint = first;
+  dest(horiz, leftpoint);
+  /* Circle until finished. */
+  while (1) {
+    /* By default, the edge will be flipped. */
+    doflip = 1;
+    if (checksegments) {
+      /* Check for a segment, which cannot be flipped. */
+      tspivot(horiz, checkshelle);
+      if (checkshelle.sh != dummysh) {
+        /* The edge is a segment and cannot be flipped. */
+        doflip = 0;
+#ifndef CDT_ONLY
+        if (segmentflaws) {
+          /* Does the new point encroach upon this segment? */
+          if (checkedge4encroach(&checkshelle)) {
+            success = ENCROACHINGPOINT;
+          }
+        }
+#endif /* not CDT_ONLY */
+      }
+    }
+    if (doflip) {
+      /* Check if the edge is a boundary edge. */
+      sym(horiz, top);
+      if (top.tri == dummytri) {
+        /* The edge is a boundary edge and cannot be flipped. */
+        doflip = 0;
+      } else {
+        /* Find the point on the other side of the edge. */
+        apex(top, farpoint);
+        /* In the incremental Delaunay triangulation algorithm, any of    */
+        /*   `leftpoint', `rightpoint', and `farpoint' could be vertices  */
+        /*   of the triangular bounding box.  These vertices must be      */
+        /*   treated as if they are infinitely distant, even though their */
+        /*   "coordinates" are not.                                       */
+        if ((leftpoint == infpoint1) || (leftpoint == infpoint2)
+                   || (leftpoint == infpoint3)) {
+          /* `leftpoint' is infinitely distant.  Check the convexity of */
+          /*   the boundary of the triangulation.  'farpoint' might be  */
+          /*   infinite as well, but trust me, this same condition      */
+          /*   should be applied.                                       */
+          doflip = counterclockwise(insertpoint, rightpoint, farpoint) > 0.0;
+        } else if ((rightpoint == infpoint1) || (rightpoint == infpoint2)
+                   || (rightpoint == infpoint3)) {
+          /* `rightpoint' is infinitely distant.  Check the convexity of */
+          /*   the boundary of the triangulation.  'farpoint' might be  */
+          /*   infinite as well, but trust me, this same condition      */
+          /*   should be applied.                                       */
+          doflip = counterclockwise(farpoint, leftpoint, insertpoint) > 0.0;
+        } else if ((farpoint == infpoint1) || (farpoint == infpoint2)
+            || (farpoint == infpoint3)) {
+          /* `farpoint' is infinitely distant and cannot be inside */
+          /*   the circumcircle of the triangle `horiz'.           */
+          doflip = 0;
+        } else {
+          /* Test whether the edge is locally Delaunay. */
+          doflip = incircle(leftpoint, insertpoint, rightpoint, farpoint)
+                   > 0.0;
+        }
+        if (doflip) {
+          /* We made it!  Flip the edge `horiz' by rotating its containing */
+          /*   quadrilateral (the two triangles adjacent to `horiz').      */
+          /* Identify the casing of the quadrilateral. */
+          lprev(top, topleft);
+          sym(topleft, toplcasing);
+          lnext(top, topright);
+          sym(topright, toprcasing);
+          lnext(horiz, botleft);
+          sym(botleft, botlcasing);
+          lprev(horiz, botright);
+          sym(botright, botrcasing);
+          /* Rotate the quadrilateral one-quarter turn counterclockwise. */
+          bond(topleft, botlcasing);
+          bond(botleft, botrcasing);
+          bond(botright, toprcasing);
+          bond(topright, toplcasing);
+          if (checksegments) {
+            /* Check for shell edges and rebond them to the quadrilateral. */
+            tspivot(topleft, toplshelle);
+            tspivot(botleft, botlshelle);
+            tspivot(botright, botrshelle);
+            tspivot(topright, toprshelle);
+            if (toplshelle.sh == dummysh) {
+              tsdissolve(topright);
+            } else {
+              tsbond(topright, toplshelle);
+            }
+            if (botlshelle.sh == dummysh) {
+              tsdissolve(topleft);
+            } else {
+              tsbond(topleft, botlshelle);
+            }
+            if (botrshelle.sh == dummysh) {
+              tsdissolve(botleft);
+            } else {
+              tsbond(botleft, botrshelle);
+            }
+            if (toprshelle.sh == dummysh) {
+              tsdissolve(botright);
+            } else {
+              tsbond(botright, toprshelle);
+            }
+          }
+          /* New point assignments for the rotated quadrilateral. */
+          setorg(horiz, farpoint);
+          setdest(horiz, insertpoint);
+          setapex(horiz, rightpoint);
+          setorg(top, insertpoint);
+          setdest(top, farpoint);
+          setapex(top, leftpoint);
+          for (i = 0; i < eextras; i++) {
+            /* Take the average of the two triangles' attributes. */
+            attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
+            setelemattribute(top, i, attrib);
+            setelemattribute(horiz, i, attrib);
+          }
+          if (vararea) {
+            if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
+              area = -1.0;
+            } else {
+              /* Take the average of the two triangles' area constraints.    */
+              /*   This prevents small area constraints from migrating a     */
+              /*   long, long way from their original location due to flips. */
+              area = 0.5 * (areabound(top) + areabound(horiz));
+            }
+            setareabound(top, area);
+            setareabound(horiz, area);
+          }
+#ifdef SELF_CHECK
+          if (insertpoint != (point) NULL) {
+            if (counterclockwise(leftpoint, insertpoint, rightpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle prior to edge flip (bottom).\n");
+            }
+            /* The following test has been removed because constrainededge() */
+            /*   sometimes generates inverted triangles that insertsite()    */
+            /*   removes.                                                    */
+/*
+            if (counterclockwise(rightpoint, farpoint, leftpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle prior to edge flip (top).\n");
+            }
+*/
+            if (counterclockwise(farpoint, leftpoint, insertpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle after edge flip (left).\n");
+            }
+            if (counterclockwise(insertpoint, rightpoint, farpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle after edge flip (right).\n");
+            }
+          }
+#endif /* SELF_CHECK */
+          if (verbose > 2) {
+            printf("  Edge flip results in left ");
+            lnextself(topleft);
+            printtriangle(&topleft);
+            printf("  and right ");
+            printtriangle(&horiz);
+          }
+          /* On the next iterations, consider the two edges that were  */
+          /*   exposed (this is, are now visible to the newly inserted */
+          /*   point) by the edge flip.                                */
+          lprevself(horiz);
+          leftpoint = farpoint;
+        }
+      }
+    }
+    if (!doflip) {
+      /* The handle `horiz' is accepted as locally Delaunay. */
+#ifndef CDT_ONLY
+      if (triflaws) {
+        /* Check the triangle `horiz' for quality. */
+        testtriangle(&horiz);
+      }
+#endif /* not CDT_ONLY */
+      /* Look for the next edge around the newly inserted point. */
+      lnextself(horiz);
+      sym(horiz, testtri);
+      /* Check for finishing a complete revolution about the new point, or */
+      /*   falling off the edge of the triangulation.  The latter will     */
+      /*   happen when a point is inserted at a boundary.                  */
+      if ((leftpoint == first) || (testtri.tri == dummytri)) {
+        /* We're done.  Return a triangle whose origin is the new point. */
+        lnext(horiz, *searchtri);
+        lnext(horiz, recenttri);
+        return success;
+      }
+      /* Finish finding the next edge around the newly inserted point. */
+      lnext(testtri, horiz);
+      rightpoint = leftpoint;
+      dest(horiz, leftpoint);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangulatepolygon()   Find the Delaunay triangulation of a polygon that */
+/*                         has a certain "nice" shape.  This includes the    */
+/*                         polygons that result from deletion of a point or  */
+/*                         insertion of a segment.                           */
+/*                                                                           */
+/*  This is a conceptually difficult routine.  The starting assumption is    */
+/*  that we have a polygon with n sides.  n - 1 of these sides are currently */
+/*  represented as edges in the mesh.  One side, called the "base", need not */
+/*  be.                                                                      */
+/*                                                                           */
+/*  Inside the polygon is a structure I call a "fan", consisting of n - 1    */
+/*  triangles that share a common origin.  For each of these triangles, the  */
+/*  edge opposite the origin is one of the sides of the polygon.  The        */
+/*  primary edge of each triangle is the edge directed from the origin to    */
+/*  the destination; note that this is not the same edge that is a side of   */
+/*  the polygon.  `firstedge' is the primary edge of the first triangle.     */
+/*  From there, the triangles follow in counterclockwise order about the     */
+/*  polygon, until `lastedge', the primary edge of the last triangle.        */
+/*  `firstedge' and `lastedge' are probably connected to other triangles     */
+/*  beyond the extremes of the fan, but their identity is not important, as  */
+/*  long as the fan remains connected to them.                               */
+/*                                                                           */
+/*  Imagine the polygon oriented so that its base is at the bottom.  This    */
+/*  puts `firstedge' on the far right, and `lastedge' on the far left.       */
+/*  The right vertex of the base is the destination of `firstedge', and the  */
+/*  left vertex of the base is the apex of `lastedge'.                       */
+/*                                                                           */
+/*  The challenge now is to find the right sequence of edge flips to         */
+/*  transform the fan into a Delaunay triangulation of the polygon.  Each    */
+/*  edge flip effectively removes one triangle from the fan, committing it   */
+/*  to the polygon.  The resulting polygon has one fewer edge.  If `doflip'  */
+/*  is set, the final flip will be performed, resulting in a fan of one      */
+/*  (useless?) triangle.  If `doflip' is not set, the final flip is not      */
+/*  performed, resulting in a fan of two triangles, and an unfinished        */
+/*  triangular polygon that is not yet filled out with a single triangle.    */
+/*  On completion of the routine, `lastedge' is the last remaining triangle, */
+/*  or the leftmost of the last two.                                         */
+/*                                                                           */
+/*  Although the flips are performed in the order described above, the       */
+/*  decisions about what flips to perform are made in precisely the reverse  */
+/*  order.  The recursive triangulatepolygon() procedure makes a decision,   */
+/*  uses up to two recursive calls to triangulate the "subproblems"          */
+/*  (polygons with fewer edges), and then performs an edge flip.             */
+/*                                                                           */
+/*  The "decision" it makes is which vertex of the polygon should be         */
+/*  connected to the base.  This decision is made by testing every possible  */
+/*  vertex.  Once the best vertex is found, the two edges that connect this  */
+/*  vertex to the base become the bases for two smaller polygons.  These     */
+/*  are triangulated recursively.  Unfortunately, this approach can take     */
+/*  O(n^2) time not only in the worst case, but in many common cases.  It's  */
+/*  rarely a big deal for point deletion, where n is rarely larger than ten, */
+/*  but it could be a big deal for segment insertion, especially if there's  */
+/*  a lot of long segments that each cut many triangles.  I ought to code    */
+/*  a faster algorithm some time.                                            */
+/*                                                                           */
+/*  The `edgecount' parameter is the number of sides of the polygon,         */
+/*  including its base.  `triflaws' is a flag that determines whether the    */
+/*  new triangles should be tested for quality, and enqueued if they are     */
+/*  bad.                                                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangulatepolygon(firstedge, lastedge, edgecount, doflip, triflaws)
+struct triedge *firstedge;
+struct triedge *lastedge;
+int edgecount;
+int doflip;
+int triflaws;
+{
+  struct triedge testtri;
+  struct triedge besttri;
+  struct triedge tempedge;
+  point leftbasepoint, rightbasepoint;
+  point testpoint;
+  point bestpoint;
+  int bestnumber;
+  int i;
+  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
+
+  /* Identify the base vertices. */
+  apex(*lastedge, leftbasepoint);
+  dest(*firstedge, rightbasepoint);
+  if (verbose > 2) {
+    printf("  Triangulating interior polygon at edge\n");
+    printf("    (%.12g, %.12g) (%.12g, %.12g)\n", leftbasepoint[0],
+           leftbasepoint[1], rightbasepoint[0], rightbasepoint[1]);
+  }
+  /* Find the best vertex to connect the base to. */
+  onext(*firstedge, besttri);
+  dest(besttri, bestpoint);
+  triedgecopy(besttri, testtri);
+  bestnumber = 1;
+  for (i = 2; i <= edgecount - 2; i++) {
+    onextself(testtri);
+    dest(testtri, testpoint);
+    /* Is this a better vertex? */
+    if (incircle(leftbasepoint, rightbasepoint, bestpoint, testpoint) > 0.0) {
+      triedgecopy(testtri, besttri);
+      bestpoint = testpoint;
+      bestnumber = i;
+    }
+  }
+  if (verbose > 2) {
+    printf("    Connecting edge to (%.12g, %.12g)\n", bestpoint[0],
+           bestpoint[1]);
+  }
+  if (bestnumber > 1) {
+    /* Recursively triangulate the smaller polygon on the right. */
+    oprev(besttri, tempedge);
+    triangulatepolygon(firstedge, &tempedge, bestnumber + 1, 1, triflaws);
+  }
+  if (bestnumber < edgecount - 2) {
+    /* Recursively triangulate the smaller polygon on the left. */
+    sym(besttri, tempedge);
+    triangulatepolygon(&besttri, lastedge, edgecount - bestnumber, 1,
+                       triflaws);
+    /* Find `besttri' again; it may have been lost to edge flips. */
+    sym(tempedge, besttri);
+  }
+  if (doflip) {
+    /* Do one final edge flip. */
+    flip(&besttri);
+#ifndef CDT_ONLY
+    if (triflaws) {
+      /* Check the quality of the newly committed triangle. */
+      sym(besttri, testtri);
+      testtriangle(&testtri);
+    }
+#endif /* not CDT_ONLY */
+  }
+  /* Return the base triangle. */
+  triedgecopy(besttri, *lastedge);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  deletesite()   Delete a vertex from a Delaunay triangulation, ensuring   */
+/*                 that the triangulation remains Delaunay.                  */
+/*                                                                           */
+/*  The origin of `deltri' is deleted.  The union of the triangles adjacent  */
+/*  to this point is a polygon, for which the Delaunay triangulation is      */
+/*  found.  Two triangles are removed from the mesh.                         */
+/*                                                                           */
+/*  Only interior points that do not lie on segments (shell edges) or        */
+/*  boundaries may be deleted.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void deletesite(deltri)
+struct triedge *deltri;
+{
+  struct triedge countingtri;
+  struct triedge firstedge, lastedge;
+  struct triedge deltriright;
+  struct triedge lefttri, righttri;
+  struct triedge leftcasing, rightcasing;
+  struct edge leftshelle, rightshelle;
+  point delpoint;
+  point neworg;
+  int edgecount;
+  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  org(*deltri, delpoint);
+  if (verbose > 1) {
+    printf("  Deleting (%.12g, %.12g).\n", delpoint[0], delpoint[1]);
+  }
+  pointdealloc(delpoint);
+
+  /* Count the degree of the point being deleted. */
+  onext(*deltri, countingtri);
+  edgecount = 1;
+  while (!triedgeequal(*deltri, countingtri)) {
+#ifdef SELF_CHECK
+    if (countingtri.tri == dummytri) {
+      printf("Internal error in deletesite():\n");
+      printf("  Attempt to delete boundary point.\n");
+      internalerror();
+    }
+#endif /* SELF_CHECK */
+    edgecount++;
+    onextself(countingtri);
+  }
+
+#ifdef SELF_CHECK
+  if (edgecount < 3) {
+    printf("Internal error in deletesite():\n  Point has degree %d.\n",
+           edgecount);
+    internalerror();
+  }
+#endif /* SELF_CHECK */
+  if (edgecount > 3) {
+    /* Triangulate the polygon defined by the union of all triangles */
+    /*   adjacent to the point being deleted.  Check the quality of  */
+    /*   the resulting triangles.                                    */
+    onext(*deltri, firstedge);
+    oprev(*deltri, lastedge);
+    triangulatepolygon(&firstedge, &lastedge, edgecount, 0, !nobisect);
+  }
+  /* Splice out two triangles. */
+  lprev(*deltri, deltriright);
+  dnext(*deltri, lefttri);
+  sym(lefttri, leftcasing);
+  oprev(deltriright, righttri);
+  sym(righttri, rightcasing);
+  bond(*deltri, leftcasing);
+  bond(deltriright, rightcasing);
+  tspivot(lefttri, leftshelle);
+  if (leftshelle.sh != dummysh) {
+    tsbond(*deltri, leftshelle);
+  }
+  tspivot(righttri, rightshelle);
+  if (rightshelle.sh != dummysh) {
+    tsbond(deltriright, rightshelle);
+  }
+
+  /* Set the new origin of `deltri' and check its quality. */
+  org(lefttri, neworg);
+  setorg(*deltri, neworg);
+  if (!nobisect) {
+    testtriangle(deltri);
+  }
+
+  /* Delete the two spliced-out triangles. */
+  triangledealloc(lefttri.tri);
+  triangledealloc(righttri.tri);
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh transformation routines end here                     *********/
+
+/********* Divide-and-conquer Delaunay triangulation begins here     *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  The divide-and-conquer bounding box                                      */
+/*                                                                           */
+/*  I originally implemented the divide-and-conquer and incremental Delaunay */
+/*  triangulations using the edge-based data structure presented by Guibas   */
+/*  and Stolfi.  Switching to a triangle-based data structure doubled the    */
+/*  speed.  However, I had to think of a few extra tricks to maintain the    */
+/*  elegance of the original algorithms.                                     */
+/*                                                                           */
+/*  The "bounding box" used by my variant of the divide-and-conquer          */
+/*  algorithm uses one triangle for each edge of the convex hull of the      */
+/*  triangulation.  These bounding triangles all share a common apical       */
+/*  vertex, which is represented by NULL and which represents nothing.       */
+/*  The bounding triangles are linked in a circular fan about this NULL      */
+/*  vertex, and the edges on the convex hull of the triangulation appear     */
+/*  opposite the NULL vertex.  You might find it easiest to imagine that     */
+/*  the NULL vertex is a point in 3D space behind the center of the          */
+/*  triangulation, and that the bounding triangles form a sort of cone.      */
+/*                                                                           */
+/*  This bounding box makes it easy to represent degenerate cases.  For      */
+/*  instance, the triangulation of two vertices is a single edge.  This edge */
+/*  is represented by two bounding box triangles, one on each "side" of the  */
+/*  edge.  These triangles are also linked together in a fan about the NULL  */
+/*  vertex.                                                                  */
+/*                                                                           */
+/*  The bounding box also makes it easy to traverse the convex hull, as the  */
+/*  divide-and-conquer algorithm needs to do.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointsort()   Sort an array of points by x-coordinate, using the         */
+/*                y-coordinate as a secondary key.                           */
+/*                                                                           */
+/*  Uses quicksort.  Randomized O(n log n) time.  No, I did not make any of  */
+/*  the usual quicksort mistakes.                                            */
+/*                                                                           */
+/*****************************************************************************/
+
+void pointsort(sortarray, arraysize)
+point *sortarray;
+int arraysize;
+{
+  int left, right;
+  int pivot;
+  REAL pivotx, pivoty;
+  point temp;
+
+  if (arraysize == 2) {
+    /* Recursive base case. */
+    if ((sortarray[0][0] > sortarray[1][0]) ||
+        ((sortarray[0][0] == sortarray[1][0]) &&
+         (sortarray[0][1] > sortarray[1][1]))) {
+      temp = sortarray[1];
+      sortarray[1] = sortarray[0];
+      sortarray[0] = temp;
+    }
+    return;
+  }
+  /* Choose a random pivot to split the array. */
+  pivot = (int) randomnation(arraysize);
+  pivotx = sortarray[pivot][0];
+  pivoty = sortarray[pivot][1];
+  /* Split the array. */
+  left = -1;
+  right = arraysize;
+  while (left < right) {
+    /* Search for a point whose x-coordinate is too large for the left. */
+    do {
+      left++;
+    } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
+                                 ((sortarray[left][0] == pivotx) &&
+                                  (sortarray[left][1] < pivoty))));
+    /* Search for a point whose x-coordinate is too small for the right. */
+    do {
+      right--;
+    } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
+                                 ((sortarray[right][0] == pivotx) &&
+                                  (sortarray[right][1] > pivoty))));
+    if (left < right) {
+      /* Swap the left and right points. */
+      temp = sortarray[left];
+      sortarray[left] = sortarray[right];
+      sortarray[right] = temp;
+    }
+  }
+  if (left > 1) {
+    /* Recursively sort the left subset. */
+    pointsort(sortarray, left);
+  }
+  if (right < arraysize - 2) {
+    /* Recursively sort the right subset. */
+    pointsort(&sortarray[right + 1], arraysize - right - 1);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointmedian()   An order statistic algorithm, almost.  Shuffles an array */
+/*                  of points so that the first `median' points occur        */
+/*                  lexicographically before the remaining points.           */
+/*                                                                           */
+/*  Uses the x-coordinate as the primary key if axis == 0; the y-coordinate  */
+/*  if axis == 1.  Very similar to the pointsort() procedure, but runs in    */
+/*  randomized linear time.                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void pointmedian(sortarray, arraysize, median, axis)
+point *sortarray;
+int arraysize;
+int median;
+int axis;
+{
+  int left, right;
+  int pivot;
+  REAL pivot1, pivot2;
+  point temp;
+
+  if (arraysize == 2) {
+    /* Recursive base case. */
+    if ((sortarray[0][axis] > sortarray[1][axis]) ||
+        ((sortarray[0][axis] == sortarray[1][axis]) &&
+         (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
+      temp = sortarray[1];
+      sortarray[1] = sortarray[0];
+      sortarray[0] = temp;
+    }
+    return;
+  }
+  /* Choose a random pivot to split the array. */
+  pivot = (int) randomnation(arraysize);
+  pivot1 = sortarray[pivot][axis];
+  pivot2 = sortarray[pivot][1 - axis];
+  /* Split the array. */
+  left = -1;
+  right = arraysize;
+  while (left < right) {
+    /* Search for a point whose x-coordinate is too large for the left. */
+    do {
+      left++;
+    } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
+                                 ((sortarray[left][axis] == pivot1) &&
+                                  (sortarray[left][1 - axis] < pivot2))));
+    /* Search for a point whose x-coordinate is too small for the right. */
+    do {
+      right--;
+    } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
+                                 ((sortarray[right][axis] == pivot1) &&
+                                  (sortarray[right][1 - axis] > pivot2))));
+    if (left < right) {
+      /* Swap the left and right points. */
+      temp = sortarray[left];
+      sortarray[left] = sortarray[right];
+      sortarray[right] = temp;
+    }
+  }
+  /* Unlike in pointsort(), at most one of the following */
+  /*   conditionals is true.                             */
+  if (left > median) {
+    /* Recursively shuffle the left subset. */
+    pointmedian(sortarray, left, median, axis);
+  }
+  if (right < median - 1) {
+    /* Recursively shuffle the right subset. */
+    pointmedian(&sortarray[right + 1], arraysize - right - 1,
+                median - right - 1, axis);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  alternateaxes()   Sorts the points as appropriate for the divide-and-    */
+/*                    conquer algorithm with alternating cuts.               */
+/*                                                                           */
+/*  Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1.   */
+/*  For the base case, subsets containing only two or three points are       */
+/*  always sorted by x-coordinate.                                           */
+/*                                                                           */
+/*****************************************************************************/
+
+void alternateaxes(sortarray, arraysize, axis)
+point *sortarray;
+int arraysize;
+int axis;
+{
+  int divider;
+
+  divider = arraysize >> 1;
+  if (arraysize <= 3) {
+    /* Recursive base case:  subsets of two or three points will be      */
+    /*   handled specially, and should always be sorted by x-coordinate. */
+    axis = 0;
+  }
+  /* Partition with a horizontal or vertical cut. */
+  pointmedian(sortarray, arraysize, divider, axis);
+  /* Recursively partition the subsets with a cross cut. */
+  if (arraysize - divider >= 2) {
+    if (divider >= 2) {
+      alternateaxes(sortarray, divider, 1 - axis);
+    }
+    alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  mergehulls()   Merge two adjacent Delaunay triangulations into a         */
+/*                 single Delaunay triangulation.                            */
+/*                                                                           */
+/*  This is similar to the algorithm given by Guibas and Stolfi, but uses    */
+/*  a triangle-based, rather than edge-based, data structure.                */
+/*                                                                           */
+/*  The algorithm walks up the gap between the two triangulations, knitting  */
+/*  them together.  As they are merged, some of their bounding triangles     */
+/*  are converted into real triangles of the triangulation.  The procedure   */
+/*  pulls each hull's bounding triangles apart, then knits them together     */
+/*  like the teeth of two gears.  The Delaunay property determines, at each  */
+/*  step, whether the next "tooth" is a bounding triangle of the left hull   */
+/*  or the right.  When a bounding triangle becomes real, its apex is        */
+/*  changed from NULL to a real point.                                       */
+/*                                                                           */
+/*  Only two new triangles need to be allocated.  These become new bounding  */
+/*  triangles at the top and bottom of the seam.  They are used to connect   */
+/*  the remaining bounding triangles (those that have not been converted     */
+/*  into real triangles) into a single fan.                                  */
+/*                                                                           */
+/*  On entry, `farleft' and `innerleft' are bounding triangles of the left   */
+/*  triangulation.  The origin of `farleft' is the leftmost vertex, and      */
+/*  the destination of `innerleft' is the rightmost vertex of the            */
+/*  triangulation.  Similarly, `innerright' and `farright' are bounding      */
+/*  triangles of the right triangulation.  The origin of `innerright' and    */
+/*  destination of `farright' are the leftmost and rightmost vertices.       */
+/*                                                                           */
+/*  On completion, the origin of `farleft' is the leftmost vertex of the     */
+/*  merged triangulation, and the destination of `farright' is the rightmost */
+/*  vertex.                                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void mergehulls(farleft, innerleft, innerright, farright, axis)
+struct triedge *farleft;
+struct triedge *innerleft;
+struct triedge *innerright;
+struct triedge *farright;
+int axis;
+{
+  struct triedge leftcand, rightcand;
+  struct triedge baseedge;
+  struct triedge nextedge;
+  struct triedge sidecasing, topcasing, outercasing;
+  struct triedge checkedge;
+  point innerleftdest;
+  point innerrightorg;
+  point innerleftapex, innerrightapex;
+  point farleftpt, farrightpt;
+  point farleftapex, farrightapex;
+  point lowerleft, lowerright;
+  point upperleft, upperright;
+  point nextapex;
+  point checkvertex;
+  int changemade;
+  int badedge;
+  int leftfinished, rightfinished;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  dest(*innerleft, innerleftdest);
+  apex(*innerleft, innerleftapex);
+  org(*innerright, innerrightorg);
+  apex(*innerright, innerrightapex);
+  /* Special treatment for horizontal cuts. */
+  if (dwyer && (axis == 1)) {
+    org(*farleft, farleftpt);
+    apex(*farleft, farleftapex);
+    dest(*farright, farrightpt);
+    apex(*farright, farrightapex);
+    /* The pointers to the extremal points are shifted to point to the */
+    /*   topmost and bottommost point of each hull, rather than the    */
+    /*   leftmost and rightmost points.                                */
+    while (farleftapex[1] < farleftpt[1]) {
+      lnextself(*farleft);
+      symself(*farleft);
+      farleftpt = farleftapex;
+      apex(*farleft, farleftapex);
+    }
+    sym(*innerleft, checkedge);
+    apex(checkedge, checkvertex);
+    while (checkvertex[1] > innerleftdest[1]) {
+      lnext(checkedge, *innerleft);
+      innerleftapex = innerleftdest;
+      innerleftdest = checkvertex;
+      sym(*innerleft, checkedge);
+      apex(checkedge, checkvertex);
+    }
+    while (innerrightapex[1] < innerrightorg[1]) {
+      lnextself(*innerright);
+      symself(*innerright);
+      innerrightorg = innerrightapex;
+      apex(*innerright, innerrightapex);
+    }
+    sym(*farright, checkedge);
+    apex(checkedge, checkvertex);
+    while (checkvertex[1] > farrightpt[1]) {
+      lnext(checkedge, *farright);
+      farrightapex = farrightpt;
+      farrightpt = checkvertex;
+      sym(*farright, checkedge);
+      apex(checkedge, checkvertex);
+    }
+  }
+  /* Find a line tangent to and below both hulls. */
+  do {
+    changemade = 0;
+    /* Make innerleftdest the "bottommost" point of the left hull. */
+    if (counterclockwise(innerleftdest, innerleftapex, innerrightorg) > 0.0) {
+      lprevself(*innerleft);
+      symself(*innerleft);
+      innerleftdest = innerleftapex;
+      apex(*innerleft, innerleftapex);
+      changemade = 1;
+    }
+    /* Make innerrightorg the "bottommost" point of the right hull. */
+    if (counterclockwise(innerrightapex, innerrightorg, innerleftdest) > 0.0) {
+      lnextself(*innerright);
+      symself(*innerright);
+      innerrightorg = innerrightapex;
+      apex(*innerright, innerrightapex);
+      changemade = 1;
+    }
+  } while (changemade);
+  /* Find the two candidates to be the next "gear tooth". */
+  sym(*innerleft, leftcand);
+  sym(*innerright, rightcand);
+  /* Create the bottom new bounding triangle. */
+  maketriangle(&baseedge);
+  /* Connect it to the bounding boxes of the left and right triangulations. */
+  bond(baseedge, *innerleft);
+  lnextself(baseedge);
+  bond(baseedge, *innerright);
+  lnextself(baseedge);
+  setorg(baseedge, innerrightorg);
+  setdest(baseedge, innerleftdest);
+  /* Apex is intentionally left NULL. */
+  if (verbose > 2) {
+    printf("  Creating base bounding ");
+    printtriangle(&baseedge);
+  }
+  /* Fix the extreme triangles if necessary. */
+  org(*farleft, farleftpt);
+  if (innerleftdest == farleftpt) {
+    lnext(baseedge, *farleft);
+  }
+  dest(*farright, farrightpt);
+  if (innerrightorg == farrightpt) {
+    lprev(baseedge, *farright);
+  }
+  /* The vertices of the current knitting edge. */
+  lowerleft = innerleftdest;
+  lowerright = innerrightorg;
+  /* The candidate vertices for knitting. */
+  apex(leftcand, upperleft);
+  apex(rightcand, upperright);
+  /* Walk up the gap between the two triangulations, knitting them together. */
+  while (1) {
+    /* Have we reached the top?  (This isn't quite the right question,       */
+    /*   because even though the left triangulation might seem finished now, */
+    /*   moving up on the right triangulation might reveal a new point of    */
+    /*   the left triangulation.  And vice-versa.)                           */
+    leftfinished = counterclockwise(upperleft, lowerleft, lowerright) <= 0.0;
+    rightfinished = counterclockwise(upperright, lowerleft, lowerright) <= 0.0;
+    if (leftfinished && rightfinished) {
+      /* Create the top new bounding triangle. */
+      maketriangle(&nextedge);
+      setorg(nextedge, lowerleft);
+      setdest(nextedge, lowerright);
+      /* Apex is intentionally left NULL. */
+      /* Connect it to the bounding boxes of the two triangulations. */
+      bond(nextedge, baseedge);
+      lnextself(nextedge);
+      bond(nextedge, rightcand);
+      lnextself(nextedge);
+      bond(nextedge, leftcand);
+      if (verbose > 2) {
+        printf("  Creating top bounding ");
+        printtriangle(&baseedge);
+      }
+      /* Special treatment for horizontal cuts. */
+      if (dwyer && (axis == 1)) {
+        org(*farleft, farleftpt);
+        apex(*farleft, farleftapex);
+        dest(*farright, farrightpt);
+        apex(*farright, farrightapex);
+        sym(*farleft, checkedge);
+        apex(checkedge, checkvertex);
+        /* The pointers to the extremal points are restored to the leftmost */
+        /*   and rightmost points (rather than topmost and bottommost).     */
+        while (checkvertex[0] < farleftpt[0]) {
+          lprev(checkedge, *farleft);
+          farleftapex = farleftpt;
+          farleftpt = checkvertex;
+          sym(*farleft, checkedge);
+          apex(checkedge, checkvertex);
+        }
+        while (farrightapex[0] > farrightpt[0]) {
+          lprevself(*farright);
+          symself(*farright);
+          farrightpt = farrightapex;
+          apex(*farright, farrightapex);
+        }
+      }
+      return;
+    }
+    /* Consider eliminating edges from the left triangulation. */
+    if (!leftfinished) {
+      /* What vertex would be exposed if an edge were deleted? */
+      lprev(leftcand, nextedge);
+      symself(nextedge);
+      apex(nextedge, nextapex);
+      /* If nextapex is NULL, then no vertex would be exposed; the */
+      /*   triangulation would have been eaten right through.      */
+      if (nextapex != (point) NULL) {
+        /* Check whether the edge is Delaunay. */
+        badedge = incircle(lowerleft, lowerright, upperleft, nextapex) > 0.0;
+        while (badedge) {
+          /* Eliminate the edge with an edge flip.  As a result, the    */
+          /*   left triangulation will have one more boundary triangle. */
+          lnextself(nextedge);
+          sym(nextedge, topcasing);
+          lnextself(nextedge);
+          sym(nextedge, sidecasing);
+          bond(nextedge, topcasing);
+          bond(leftcand, sidecasing);
+          lnextself(leftcand);
+          sym(leftcand, outercasing);
+          lprevself(nextedge);
+          bond(nextedge, outercasing);
+          /* Correct the vertices to reflect the edge flip. */
+          setorg(leftcand, lowerleft);
+          setdest(leftcand, NULL);
+          setapex(leftcand, nextapex);
+          setorg(nextedge, NULL);
+          setdest(nextedge, upperleft);
+          setapex(nextedge, nextapex);
+          /* Consider the newly exposed vertex. */
+          upperleft = nextapex;
+          /* What vertex would be exposed if another edge were deleted? */
+          triedgecopy(sidecasing, nextedge);
+          apex(nextedge, nextapex);
+          if (nextapex != (point) NULL) {
+            /* Check whether the edge is Delaunay. */
+            badedge = incircle(lowerleft, lowerright, upperleft, nextapex)
+                      > 0.0;
+          } else {
+            /* Avoid eating right through the triangulation. */
+            badedge = 0;
+          }
+        }
+      }
+    }
+    /* Consider eliminating edges from the right triangulation. */
+    if (!rightfinished) {
+      /* What vertex would be exposed if an edge were deleted? */
+      lnext(rightcand, nextedge);
+      symself(nextedge);
+      apex(nextedge, nextapex);
+      /* If nextapex is NULL, then no vertex would be exposed; the */
+      /*   triangulation would have been eaten right through.      */
+      if (nextapex != (point) NULL) {
+        /* Check whether the edge is Delaunay. */
+        badedge = incircle(lowerleft, lowerright, upperright, nextapex) > 0.0;
+        while (badedge) {
+          /* Eliminate the edge with an edge flip.  As a result, the     */
+          /*   right triangulation will have one more boundary triangle. */
+          lprevself(nextedge);
+          sym(nextedge, topcasing);
+          lprevself(nextedge);
+          sym(nextedge, sidecasing);
+          bond(nextedge, topcasing);
+          bond(rightcand, sidecasing);
+          lprevself(rightcand);
+          sym(rightcand, outercasing);
+          lnextself(nextedge);
+          bond(nextedge, outercasing);
+          /* Correct the vertices to reflect the edge flip. */
+          setorg(rightcand, NULL);
+          setdest(rightcand, lowerright);
+          setapex(rightcand, nextapex);
+          setorg(nextedge, upperright);
+          setdest(nextedge, NULL);
+          setapex(nextedge, nextapex);
+          /* Consider the newly exposed vertex. */
+          upperright = nextapex;
+          /* What vertex would be exposed if another edge were deleted? */
+          triedgecopy(sidecasing, nextedge);
+          apex(nextedge, nextapex);
+          if (nextapex != (point) NULL) {
+            /* Check whether the edge is Delaunay. */
+            badedge = incircle(lowerleft, lowerright, upperright, nextapex)
+                      > 0.0;
+          } else {
+            /* Avoid eating right through the triangulation. */
+            badedge = 0;
+          }
+        }
+      }
+    }
+    if (leftfinished || (!rightfinished &&
+           (incircle(upperleft, lowerleft, lowerright, upperright) > 0.0))) {
+      /* Knit the triangulations, adding an edge from `lowerleft' */
+      /*   to `upperright'.                                       */
+      bond(baseedge, rightcand);
+      lprev(rightcand, baseedge);
+      setdest(baseedge, lowerleft);
+      lowerright = upperright;
+      sym(baseedge, rightcand);
+      apex(rightcand, upperright);
+    } else {
+      /* Knit the triangulations, adding an edge from `upperleft' */
+      /*   to `lowerright'.                                       */
+      bond(baseedge, leftcand);
+      lnext(leftcand, baseedge);
+      setorg(baseedge, lowerright);
+      lowerleft = upperleft;
+      sym(baseedge, leftcand);
+      apex(leftcand, upperleft);
+    }
+    if (verbose > 2) {
+      printf("  Connecting ");
+      printtriangle(&baseedge);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  divconqrecurse()   Recursively form a Delaunay triangulation by the      */
+/*                     divide-and-conquer method.                            */
+/*                                                                           */
+/*  Recursively breaks down the problem into smaller pieces, which are       */
+/*  knitted together by mergehulls().  The base cases (problems of two or    */
+/*  three points) are handled specially here.                                */
+/*                                                                           */
+/*  On completion, `farleft' and `farright' are bounding triangles such that */
+/*  the origin of `farleft' is the leftmost vertex (breaking ties by         */
+/*  choosing the highest leftmost vertex), and the destination of            */
+/*  `farright' is the rightmost vertex (breaking ties by choosing the        */
+/*  lowest rightmost vertex).                                                */
+/*                                                                           */
+/*****************************************************************************/
+
+void divconqrecurse(sortarray, vertices, axis, farleft, farright)
+point *sortarray;
+int vertices;
+int axis;
+struct triedge *farleft;
+struct triedge *farright;
+{
+  struct triedge midtri, tri1, tri2, tri3;
+  struct triedge innerleft, innerright;
+  REAL area;
+  int divider;
+
+  if (verbose > 2) {
+    printf("  Triangulating %d points.\n", vertices);
+  }
+  if (vertices == 2) {
+    /* The triangulation of two vertices is an edge.  An edge is */
+    /*   represented by two bounding triangles.                  */
+    maketriangle(farleft);
+    setorg(*farleft, sortarray[0]);
+    setdest(*farleft, sortarray[1]);
+    /* The apex is intentionally left NULL. */
+    maketriangle(farright);
+    setorg(*farright, sortarray[1]);
+    setdest(*farright, sortarray[0]);
+    /* The apex is intentionally left NULL. */
+    bond(*farleft, *farright);
+    lprevself(*farleft);
+    lnextself(*farright);
+    bond(*farleft, *farright);
+    lprevself(*farleft);
+    lnextself(*farright);
+    bond(*farleft, *farright);
+    if (verbose > 2) {
+      printf("  Creating ");
+      printtriangle(farleft);
+      printf("  Creating ");
+      printtriangle(farright);
+    }
+    /* Ensure that the origin of `farleft' is sortarray[0]. */
+    lprev(*farright, *farleft);
+    return;
+  } else if (vertices == 3) {
+    /* The triangulation of three vertices is either a triangle (with */
+    /*   three bounding triangles) or two edges (with four bounding   */
+    /*   triangles).  In either case, four triangles are created.     */
+    maketriangle(&midtri);
+    maketriangle(&tri1);
+    maketriangle(&tri2);
+    maketriangle(&tri3);
+    area = counterclockwise(sortarray[0], sortarray[1], sortarray[2]);
+    if (area == 0.0) {
+      /* Three collinear points; the triangulation is two edges. */
+      setorg(midtri, sortarray[0]);
+      setdest(midtri, sortarray[1]);
+      setorg(tri1, sortarray[1]);
+      setdest(tri1, sortarray[0]);
+      setorg(tri2, sortarray[2]);
+      setdest(tri2, sortarray[1]);
+      setorg(tri3, sortarray[1]);
+      setdest(tri3, sortarray[2]);
+      /* All apices are intentionally left NULL. */
+      bond(midtri, tri1);
+      bond(tri2, tri3);
+      lnextself(midtri);
+      lprevself(tri1);
+      lnextself(tri2);
+      lprevself(tri3);
+      bond(midtri, tri3);
+      bond(tri1, tri2);
+      lnextself(midtri);
+      lprevself(tri1);
+      lnextself(tri2);
+      lprevself(tri3);
+      bond(midtri, tri1);
+      bond(tri2, tri3);
+      /* Ensure that the origin of `farleft' is sortarray[0]. */
+      triedgecopy(tri1, *farleft);
+      /* Ensure that the destination of `farright' is sortarray[2]. */
+      triedgecopy(tri2, *farright);
+    } else {
+      /* The three points are not collinear; the triangulation is one */
+      /*   triangle, namely `midtri'.                                 */
+      setorg(midtri, sortarray[0]);
+      setdest(tri1, sortarray[0]);
+      setorg(tri3, sortarray[0]);
+      /* Apices of tri1, tri2, and tri3 are left NULL. */
+      if (area > 0.0) {
+        /* The vertices are in counterclockwise order. */
+        setdest(midtri, sortarray[1]);
+        setorg(tri1, sortarray[1]);
+        setdest(tri2, sortarray[1]);
+        setapex(midtri, sortarray[2]);
+        setorg(tri2, sortarray[2]);
+        setdest(tri3, sortarray[2]);
+      } else {
+        /* The vertices are in clockwise order. */
+        setdest(midtri, sortarray[2]);
+        setorg(tri1, sortarray[2]);
+        setdest(tri2, sortarray[2]);
+        setapex(midtri, sortarray[1]);
+        setorg(tri2, sortarray[1]);
+        setdest(tri3, sortarray[1]);
+      }
+      /* The topology does not depend on how the vertices are ordered. */
+      bond(midtri, tri1);
+      lnextself(midtri);
+      bond(midtri, tri2);
+      lnextself(midtri);
+      bond(midtri, tri3);
+      lprevself(tri1);
+      lnextself(tri2);
+      bond(tri1, tri2);
+      lprevself(tri1);
+      lprevself(tri3);
+      bond(tri1, tri3);
+      lnextself(tri2);
+      lprevself(tri3);
+      bond(tri2, tri3);
+      /* Ensure that the origin of `farleft' is sortarray[0]. */
+      triedgecopy(tri1, *farleft);
+      /* Ensure that the destination of `farright' is sortarray[2]. */
+      if (area > 0.0) {
+        triedgecopy(tri2, *farright);
+      } else {
+        lnext(*farleft, *farright);
+      }
+    }
+    if (verbose > 2) {
+      printf("  Creating ");
+      printtriangle(&midtri);
+      printf("  Creating ");
+      printtriangle(&tri1);
+      printf("  Creating ");
+      printtriangle(&tri2);
+      printf("  Creating ");
+      printtriangle(&tri3);
+    }
+    return;
+  } else {
+    /* Split the vertices in half. */
+    divider = vertices >> 1;
+    /* Recursively triangulate each half. */
+    divconqrecurse(sortarray, divider, 1 - axis, farleft, &innerleft);
+    divconqrecurse(&sortarray[divider], vertices - divider, 1 - axis,
+                   &innerright, farright);
+    if (verbose > 1) {
+      printf("  Joining triangulations with %d and %d vertices.\n", divider,
+             vertices - divider);
+    }
+    /* Merge the two triangulations into one. */
+    mergehulls(farleft, &innerleft, &innerright, farright, axis);
+  }
+}
+
+long removeghosts(startghost)
+struct triedge *startghost;
+{
+  struct triedge searchedge;
+  struct triedge dissolveedge;
+  struct triedge deadtri;
+  point markorg;
+  long hullsize;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose) {
+    printf("  Removing ghost triangles.\n");
+  }
+  /* Find an edge on the convex hull to start point location from. */
+  lprev(*startghost, searchedge);
+  symself(searchedge);
+  dummytri[0] = encode(searchedge);
+  /* Remove the bounding box and count the convex hull edges. */
+  triedgecopy(*startghost, dissolveedge);
+  hullsize = 0;
+  do {
+    hullsize++;
+    lnext(dissolveedge, deadtri);
+    lprevself(dissolveedge);
+    symself(dissolveedge);
+    /* If no PSLG is involved, set the boundary markers of all the points */
+    /*   on the convex hull.  If a PSLG is used, this step is done later. */
+    if (!poly) {
+      /* Watch out for the case where all the input points are collinear. */
+      if (dissolveedge.tri != dummytri) {
+        org(dissolveedge, markorg);
+        if (pointmark(markorg) == 0) {
+          setpointmark(markorg, 1);
+        }
+      }
+    }
+    /* Remove a bounding triangle from a convex hull triangle. */
+    dissolve(dissolveedge);
+    /* Find the next bounding triangle. */
+    sym(deadtri, dissolveedge);
+    /* Delete the bounding triangle. */
+    triangledealloc(deadtri.tri);
+  } while (!triedgeequal(dissolveedge, *startghost));
+  return hullsize;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  divconqdelaunay()   Form a Delaunay triangulation by the divide-and-     */
+/*                      conquer method.                                      */
+/*                                                                           */
+/*  Sorts the points, calls a recursive procedure to triangulate them, and   */
+/*  removes the bounding box, setting boundary markers as appropriate.       */
+/*                                                                           */
+/*****************************************************************************/
+
+long divconqdelaunay()
+{
+  point *sortarray;
+  struct triedge hullleft, hullright;
+  int divider;
+  int i, j;
+
+  /* Allocate an array of pointers to points for sorting. */
+  sortarray = (point *) malloc(inpoints * sizeof(point));
+  if (sortarray == (point *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  traversalinit(&points);
+  for (i = 0; i < inpoints; i++) {
+    sortarray[i] = pointtraverse();
+  }
+  if (verbose) {
+    printf("  Sorting points.\n");
+  }
+  /* Sort the points. */
+  pointsort(sortarray, inpoints);
+  /* Discard duplicate points, which can really mess up the algorithm. */
+  i = 0;
+  for (j = 1; j < inpoints; j++) {
+    if ((sortarray[i][0] == sortarray[j][0])
+        && (sortarray[i][1] == sortarray[j][1])) {
+      if (!quiet) {
+        printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+               sortarray[j][0], sortarray[j][1]);
+      }
+/*  Commented out - would eliminate point from output .node file, but causes
+    a failure if some segment has this point as an endpoint.
+      setpointmark(sortarray[j], DEADPOINT);
+*/
+    } else {
+      i++;
+      sortarray[i] = sortarray[j];
+    }
+  }
+  i++;
+  if (dwyer) {
+    /* Re-sort the array of points to accommodate alternating cuts. */
+    divider = i >> 1;
+    if (i - divider >= 2) {
+      if (divider >= 2) {
+        alternateaxes(sortarray, divider, 1);
+      }
+      alternateaxes(&sortarray[divider], i - divider, 1);
+    }
+  }
+  if (verbose) {
+    printf("  Forming triangulation.\n");
+  }
+  /* Form the Delaunay triangulation. */
+  divconqrecurse(sortarray, i, 0, &hullleft, &hullright);
+  free(sortarray);
+
+  return removeghosts(&hullleft);
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Divide-and-conquer Delaunay triangulation ends here       *********/
+
+/********* Incremental Delaunay triangulation begins here            *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  boundingbox()   Form an "infinite" bounding triangle to insert points    */
+/*                  into.                                                    */
+/*                                                                           */
+/*  The points at "infinity" are assigned finite coordinates, which are used */
+/*  by the point location routines, but (mostly) ignored by the Delaunay     */
+/*  edge flip routines.                                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+void boundingbox()
+{
+  struct triedge inftri;          /* Handle for the triangular bounding box. */
+  REAL width;
+
+  if (verbose) {
+    printf("  Creating triangular bounding box.\n");
+  }
+  /* Find the width (or height, whichever is larger) of the triangulation. */
+  width = xmax - xmin;
+  if (ymax - ymin > width) {
+    width = ymax - ymin;
+  }
+  if (width == 0.0) {
+    width = 1.0;
+  }
+  /* Create the vertices of the bounding box. */
+  infpoint1 = (point) malloc(points.itembytes);
+  infpoint2 = (point) malloc(points.itembytes);
+  infpoint3 = (point) malloc(points.itembytes);
+  if ((infpoint1 == (point) NULL) || (infpoint2 == (point) NULL)
+      || (infpoint3 == (point) NULL)) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  infpoint1[0] = xmin - 50.0 * width;
+  infpoint1[1] = ymin - 40.0 * width;
+  infpoint2[0] = xmax + 50.0 * width;
+  infpoint2[1] = ymin - 40.0 * width;
+  infpoint3[0] = 0.5 * (xmin + xmax);
+  infpoint3[1] = ymax + 60.0 * width;
+
+  /* Create the bounding box. */
+  maketriangle(&inftri);
+  setorg(inftri, infpoint1);
+  setdest(inftri, infpoint2);
+  setapex(inftri, infpoint3);
+  /* Link dummytri to the bounding box so we can always find an */
+  /*   edge to begin searching (point location) from.           */
+  dummytri[0] = (triangle) inftri.tri;
+  if (verbose > 2) {
+    printf("  Creating ");
+    printtriangle(&inftri);
+  }
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  removebox()   Remove the "infinite" bounding triangle, setting boundary  */
+/*                markers as appropriate.                                    */
+/*                                                                           */
+/*  The triangular bounding box has three boundary triangles (one for each   */
+/*  side of the bounding box), and a bunch of triangles fanning out from     */
+/*  the three bounding box vertices (one triangle for each edge of the       */
+/*  convex hull of the inner mesh).  This routine removes these triangles.   */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+long removebox()
+{
+  struct triedge deadtri;
+  struct triedge searchedge;
+  struct triedge checkedge;
+  struct triedge nextedge, finaledge, dissolveedge;
+  point markorg;
+  long hullsize;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose) {
+    printf("  Removing triangular bounding box.\n");
+  }
+  /* Find a boundary triangle. */
+  nextedge.tri = dummytri;
+  nextedge.orient = 0;
+  symself(nextedge);
+  /* Mark a place to stop. */
+  lprev(nextedge, finaledge);
+  lnextself(nextedge);
+  symself(nextedge);
+  /* Find a triangle (on the boundary of the point set) that isn't */
+  /*   a bounding box triangle.                                    */
+  lprev(nextedge, searchedge);
+  symself(searchedge);
+  /* Check whether nextedge is another boundary triangle */
+  /*   adjacent to the first one.                        */
+  lnext(nextedge, checkedge);
+  symself(checkedge);
+  if (checkedge.tri == dummytri) {
+    /* Go on to the next triangle.  There are only three boundary   */
+    /*   triangles, and this next triangle cannot be the third one, */
+    /*   so it's safe to stop here.                                 */
+    lprevself(searchedge);
+    symself(searchedge);
+  }
+  /* Find a new boundary edge to search from, as the current search */
+  /*   edge lies on a bounding box triangle and will be deleted.    */
+  dummytri[0] = encode(searchedge);
+  hullsize = -2l;
+  while (!triedgeequal(nextedge, finaledge)) {
+    hullsize++;
+    lprev(nextedge, dissolveedge);
+    symself(dissolveedge);
+    /* If not using a PSLG, the vertices should be marked now. */
+    /*   (If using a PSLG, markhull() will do the job.)        */
+    if (!poly) {
+      /* Be careful!  One must check for the case where all the input   */
+      /*   points are collinear, and thus all the triangles are part of */
+      /*   the bounding box.  Otherwise, the setpointmark() call below  */
+      /*   will cause a bad pointer reference.                          */
+      if (dissolveedge.tri != dummytri) {
+        org(dissolveedge, markorg);
+        if (pointmark(markorg) == 0) {
+          setpointmark(markorg, 1);
+        }
+      }
+    }
+    /* Disconnect the bounding box triangle from the mesh triangle. */
+    dissolve(dissolveedge);
+    lnext(nextedge, deadtri);
+    sym(deadtri, nextedge);
+    /* Get rid of the bounding box triangle. */
+    triangledealloc(deadtri.tri);
+    /* Do we need to turn the corner? */
+    if (nextedge.tri == dummytri) {
+      /* Turn the corner. */
+      triedgecopy(dissolveedge, nextedge);
+    }
+  }
+  triangledealloc(finaledge.tri);
+
+  free(infpoint1);                  /* Deallocate the bounding box vertices. */
+  free(infpoint2);
+  free(infpoint3);
+
+  return hullsize;
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  incrementaldelaunay()   Form a Delaunay triangulation by incrementally   */
+/*                          adding vertices.                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+long incrementaldelaunay()
+{
+  struct triedge starttri;
+  point pointloop;
+  int i;
+
+  /* Create a triangular bounding box. */
+  boundingbox();
+  if (verbose) {
+    printf("  Incrementally inserting points.\n");
+  }
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  i = 1;
+  while (pointloop != (point) NULL) {
+    /* Find a boundary triangle to search from. */
+    starttri.tri = (triangle *) NULL;
+    if (insertsite(pointloop, &starttri, (struct edge *) NULL, 0, 0) ==
+        DUPLICATEPOINT) {
+      if (!quiet) {
+        printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+               pointloop[0], pointloop[1]);
+      }
+/*  Commented out - would eliminate point from output .node file.
+      setpointmark(pointloop, DEADPOINT);
+*/
+    }
+    pointloop = pointtraverse();
+    i++;
+  }
+  /* Remove the bounding box. */
+  return removebox();
+}
+
+#endif /* not REDUCED */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Incremental Delaunay triangulation ends here              *********/
+
+/********* Sweepline Delaunay triangulation begins here              *********/
+/**                                                                         **/
+/**                                                                         **/
+
+#ifndef REDUCED
+
+void eventheapinsert(heap, heapsize, newevent)
+struct event **heap;
+int heapsize;
+struct event *newevent;
+{
+  REAL eventx, eventy;
+  int eventnum;
+  int parent;
+  int notdone;
+
+  eventx = newevent->xkey;
+  eventy = newevent->ykey;
+  eventnum = heapsize;
+  notdone = eventnum > 0;
+  while (notdone) {
+    parent = (eventnum - 1) >> 1;
+    if ((heap[parent]->ykey < eventy) ||
+        ((heap[parent]->ykey == eventy)
+         && (heap[parent]->xkey <= eventx))) {
+      notdone = 0;
+    } else {
+      heap[eventnum] = heap[parent];
+      heap[eventnum]->heapposition = eventnum;
+
+      eventnum = parent;
+      notdone = eventnum > 0;
+    }
+  }
+  heap[eventnum] = newevent;
+  newevent->heapposition = eventnum;
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void eventheapify(heap, heapsize, eventnum)
+struct event **heap;
+int heapsize;
+int eventnum;
+{
+  struct event *thisevent;
+  REAL eventx, eventy;
+  int leftchild, rightchild;
+  int smallest;
+  int notdone;
+
+  thisevent = heap[eventnum];
+  eventx = thisevent->xkey;
+  eventy = thisevent->ykey;
+  leftchild = 2 * eventnum + 1;
+  notdone = leftchild < heapsize;
+  while (notdone) {
+    if ((heap[leftchild]->ykey < eventy) ||
+        ((heap[leftchild]->ykey == eventy)
+         && (heap[leftchild]->xkey < eventx))) {
+      smallest = leftchild;
+    } else {
+      smallest = eventnum;
+    }
+    rightchild = leftchild + 1;
+    if (rightchild < heapsize) {
+      if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
+          ((heap[rightchild]->ykey == heap[smallest]->ykey)
+           && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
+        smallest = rightchild;
+      }
+    }
+    if (smallest == eventnum) {
+      notdone = 0;
+    } else {
+      heap[eventnum] = heap[smallest];
+      heap[eventnum]->heapposition = eventnum;
+      heap[smallest] = thisevent;
+      thisevent->heapposition = smallest;
+
+      eventnum = smallest;
+      leftchild = 2 * eventnum + 1;
+      notdone = leftchild < heapsize;
+    }
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void eventheapdelete(heap, heapsize, eventnum)
+struct event **heap;
+int heapsize;
+int eventnum;
+{
+  struct event *moveevent;
+  REAL eventx, eventy;
+  int parent;
+  int notdone;
+
+  moveevent = heap[heapsize - 1];
+  if (eventnum > 0) {
+    eventx = moveevent->xkey;
+    eventy = moveevent->ykey;
+    do {
+      parent = (eventnum - 1) >> 1;
+      if ((heap[parent]->ykey < eventy) ||
+          ((heap[parent]->ykey == eventy)
+           && (heap[parent]->xkey <= eventx))) {
+        notdone = 0;
+      } else {
+        heap[eventnum] = heap[parent];
+        heap[eventnum]->heapposition = eventnum;
+
+        eventnum = parent;
+        notdone = eventnum > 0;
+      }
+    } while (notdone);
+  }
+  heap[eventnum] = moveevent;
+  moveevent->heapposition = eventnum;
+  eventheapify(heap, heapsize - 1, eventnum);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void createeventheap(eventheap, events, freeevents)
+struct event ***eventheap;
+struct event **events;
+struct event **freeevents;
+{
+  point thispoint;
+  int maxevents;
+  int i;
+
+  maxevents = (3 * inpoints) / 2;
+  *eventheap = (struct event **) malloc(maxevents * sizeof(struct event *));
+  if (*eventheap == (struct event **) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  *events = (struct event *) malloc(maxevents * sizeof(struct event));
+  if (*events == (struct event *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  traversalinit(&points);
+  for (i = 0; i < inpoints; i++) {
+    thispoint = pointtraverse();
+    (*events)[i].eventptr = (VOID *) thispoint;
+    (*events)[i].xkey = thispoint[0];
+    (*events)[i].ykey = thispoint[1];
+    eventheapinsert(*eventheap, i, *events + i);
+  }
+  *freeevents = (struct event *) NULL;
+  for (i = maxevents - 1; i >= inpoints; i--) {
+    (*events)[i].eventptr = (VOID *) *freeevents;
+    *freeevents = *events + i;
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+int rightofhyperbola(fronttri, newsite)
+struct triedge *fronttri;
+point newsite;
+{
+  point leftpoint, rightpoint;
+  REAL dxa, dya, dxb, dyb;
+
+  hyperbolacount++;
+
+  dest(*fronttri, leftpoint);
+  apex(*fronttri, rightpoint);
+  if ((leftpoint[1] < rightpoint[1])
+      || ((leftpoint[1] == rightpoint[1]) && (leftpoint[0] < rightpoint[0]))) {
+    if (newsite[0] >= rightpoint[0]) {
+      return 1;
+    }
+  } else {
+    if (newsite[0] <= leftpoint[0]) {
+      return 0;
+    }
+  }
+  dxa = leftpoint[0] - newsite[0];
+  dya = leftpoint[1] - newsite[1];
+  dxb = rightpoint[0] - newsite[0];
+  dyb = rightpoint[1] - newsite[1];
+  return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+REAL circletop(pa, pb, pc, ccwabc)
+point pa;
+point pb;
+point pc;
+REAL ccwabc;
+{
+  REAL xac, yac, xbc, ybc, xab, yab;
+  REAL aclen2, bclen2, ablen2;
+
+  circletopcount++;
+
+  xac = pa[0] - pc[0];
+  yac = pa[1] - pc[1];
+  xbc = pb[0] - pc[0];
+  ybc = pb[1] - pc[1];
+  xab = pa[0] - pb[0];
+  yab = pa[1] - pb[1];
+  aclen2 = xac * xac + yac * yac;
+  bclen2 = xbc * xbc + ybc * ybc;
+  ablen2 = xab * xab + yab * yab;
+  return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
+               / (2.0 * ccwabc);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void check4deadevent(checktri, freeevents, eventheap, heapsize)
+struct triedge *checktri;
+struct event **freeevents;
+struct event **eventheap;
+int *heapsize;
+{
+  struct event *deadevent;
+  point eventpoint;
+  int eventnum;
+
+  org(*checktri, eventpoint);
+  if (eventpoint != (point) NULL) {
+    deadevent = (struct event *) eventpoint;
+    eventnum = deadevent->heapposition;
+    deadevent->eventptr = (VOID *) *freeevents;
+    *freeevents = deadevent;
+    eventheapdelete(eventheap, *heapsize, eventnum);
+    (*heapsize)--;
+    setorg(*checktri, NULL);
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *splay(splaytree, searchpoint, searchtri)
+struct splaynode *splaytree;
+point searchpoint;
+struct triedge *searchtri;
+{
+  struct splaynode *child, *grandchild;
+  struct splaynode *lefttree, *righttree;
+  struct splaynode *leftright;
+  point checkpoint;
+  int rightofroot, rightofchild;
+
+  if (splaytree == (struct splaynode *) NULL) {
+    return (struct splaynode *) NULL;
+  }
+  dest(splaytree->keyedge, checkpoint);
+  if (checkpoint == splaytree->keydest) {
+    rightofroot = rightofhyperbola(&splaytree->keyedge, searchpoint);
+    if (rightofroot) {
+      triedgecopy(splaytree->keyedge, *searchtri);
+      child = splaytree->rchild;
+    } else {
+      child = splaytree->lchild;
+    }
+    if (child == (struct splaynode *) NULL) {
+      return splaytree;
+    }
+    dest(child->keyedge, checkpoint);
+    if (checkpoint != child->keydest) {
+      child = splay(child, searchpoint, searchtri);
+      if (child == (struct splaynode *) NULL) {
+        if (rightofroot) {
+          splaytree->rchild = (struct splaynode *) NULL;
+        } else {
+          splaytree->lchild = (struct splaynode *) NULL;
+        }
+        return splaytree;
+      }
+    }
+    rightofchild = rightofhyperbola(&child->keyedge, searchpoint);
+    if (rightofchild) {
+      triedgecopy(child->keyedge, *searchtri);
+      grandchild = splay(child->rchild, searchpoint, searchtri);
+      child->rchild = grandchild;
+    } else {
+      grandchild = splay(child->lchild, searchpoint, searchtri);
+      child->lchild = grandchild;
+    }
+    if (grandchild == (struct splaynode *) NULL) {
+      if (rightofroot) {
+        splaytree->rchild = child->lchild;
+        child->lchild = splaytree;
+      } else {
+        splaytree->lchild = child->rchild;
+        child->rchild = splaytree;
+      }
+      return child;
+    }
+    if (rightofchild) {
+      if (rightofroot) {
+        splaytree->rchild = child->lchild;
+        child->lchild = splaytree;
+      } else {
+        splaytree->lchild = grandchild->rchild;
+        grandchild->rchild = splaytree;
+      }
+      child->rchild = grandchild->lchild;
+      grandchild->lchild = child;
+    } else {
+      if (rightofroot) {
+        splaytree->rchild = grandchild->lchild;
+        grandchild->lchild = splaytree;
+      } else {
+        splaytree->lchild = child->rchild;
+        child->rchild = splaytree;
+      }
+      child->lchild = grandchild->rchild;
+      grandchild->rchild = child;
+    }
+    return grandchild;
+  } else {
+    lefttree = splay(splaytree->lchild, searchpoint, searchtri);
+    righttree = splay(splaytree->rchild, searchpoint, searchtri);
+
+    pooldealloc(&splaynodes, (VOID *) splaytree);
+    if (lefttree == (struct splaynode *) NULL) {
+      return righttree;
+    } else if (righttree == (struct splaynode *) NULL) {
+      return lefttree;
+    } else if (lefttree->rchild == (struct splaynode *) NULL) {
+      lefttree->rchild = righttree->lchild;
+      righttree->lchild = lefttree;
+      return righttree;
+    } else if (righttree->lchild == (struct splaynode *) NULL) {
+      righttree->lchild = lefttree->rchild;
+      lefttree->rchild = righttree;
+      return lefttree;
+    } else {
+/*      printf("Holy Toledo!!!\n"); */
+      leftright = lefttree->rchild;
+      while (leftright->rchild != (struct splaynode *) NULL) {
+        leftright = leftright->rchild;
+      }
+      leftright->rchild = righttree;
+      return lefttree;
+    }
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *splayinsert(splayroot, newkey, searchpoint)
+struct splaynode *splayroot;
+struct triedge *newkey;
+point searchpoint;
+{
+  struct splaynode *newsplaynode;
+
+  newsplaynode = (struct splaynode *) poolalloc(&splaynodes);
+  triedgecopy(*newkey, newsplaynode->keyedge);
+  dest(*newkey, newsplaynode->keydest);
+  if (splayroot == (struct splaynode *) NULL) {
+    newsplaynode->lchild = (struct splaynode *) NULL;
+    newsplaynode->rchild = (struct splaynode *) NULL;
+  } else if (rightofhyperbola(&splayroot->keyedge, searchpoint)) {
+    newsplaynode->lchild = splayroot;
+    newsplaynode->rchild = splayroot->rchild;
+    splayroot->rchild = (struct splaynode *) NULL;
+  } else {
+    newsplaynode->lchild = splayroot->lchild;
+    newsplaynode->rchild = splayroot;
+    splayroot->lchild = (struct splaynode *) NULL;
+  }
+  return newsplaynode;
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *circletopinsert(splayroot, newkey, pa, pb, pc, topy)
+struct splaynode *splayroot;
+struct triedge *newkey;
+point pa;
+point pb;
+point pc;
+REAL topy;
+{
+  REAL ccwabc;
+  REAL xac, yac, xbc, ybc;
+  REAL aclen2, bclen2;
+  REAL searchpoint[2];
+  struct triedge dummytri;
+
+  ccwabc = counterclockwise(pa, pb, pc);
+  xac = pa[0] - pc[0];
+  yac = pa[1] - pc[1];
+  xbc = pb[0] - pc[0];
+  ybc = pb[1] - pc[1];
+  aclen2 = xac * xac + yac * yac;
+  bclen2 = xbc * xbc + ybc * ybc;
+  searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
+  searchpoint[1] = topy;
+  return splayinsert(splay(splayroot, (point) searchpoint, &dummytri), newkey,
+                     (point) searchpoint);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *frontlocate(splayroot, bottommost, searchpoint, searchtri,
+                              farright)
+struct splaynode *splayroot;
+struct triedge *bottommost;
+point searchpoint;
+struct triedge *searchtri;
+int *farright;
+{
+  int farrightflag;
+  triangle ptr;                       /* Temporary variable used by onext(). */
+
+  triedgecopy(*bottommost, *searchtri);
+  splayroot = splay(splayroot, searchpoint, searchtri);
+
+  farrightflag = 0;
+  while (!farrightflag && rightofhyperbola(searchtri, searchpoint)) {
+    onextself(*searchtri);
+    farrightflag = triedgeequal(*searchtri, *bottommost);
+  }
+  *farright = farrightflag;
+  return splayroot;
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+long sweeplinedelaunay()
+{
+  struct event **eventheap;
+  struct event *events;
+  struct event *freeevents;
+  struct event *nextevent;
+  struct event *newevent;
+  struct splaynode *splayroot;
+  struct triedge bottommost;
+  struct triedge searchtri;
+  struct triedge fliptri;
+  struct triedge lefttri, righttri, farlefttri, farrighttri;
+  struct triedge inserttri;
+  point firstpoint, secondpoint;
+  point nextpoint, lastpoint;
+  point connectpoint;
+  point leftpoint, midpoint, rightpoint;
+  REAL lefttest, righttest;
+  int heapsize;
+  int check4events, farrightflag;
+  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
+
+  poolinit(&splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK, POINTER,
+           0);
+  splayroot = (struct splaynode *) NULL;
+
+  if (verbose) {
+    printf("  Placing points in event heap.\n");
+  }
+  createeventheap(&eventheap, &events, &freeevents);
+  heapsize = inpoints;
+
+  if (verbose) {
+    printf("  Forming triangulation.\n");
+  }
+  maketriangle(&lefttri);
+  maketriangle(&righttri);
+  bond(lefttri, righttri);
+  lnextself(lefttri);
+  lprevself(righttri);
+  bond(lefttri, righttri);
+  lnextself(lefttri);
+  lprevself(righttri);
+  bond(lefttri, righttri);
+  firstpoint = (point) eventheap[0]->eventptr;
+  eventheap[0]->eventptr = (VOID *) freeevents;
+  freeevents = eventheap[0];
+  eventheapdelete(eventheap, heapsize, 0);
+  heapsize--;
+  do {
+    if (heapsize == 0) {
+      printf("Error:  Input points are all identical.\n");
+      exit(1);
+    }
+    secondpoint = (point) eventheap[0]->eventptr;
+    eventheap[0]->eventptr = (VOID *) freeevents;
+    freeevents = eventheap[0];
+    eventheapdelete(eventheap, heapsize, 0);
+    heapsize--;
+    if ((firstpoint[0] == secondpoint[0])
+        && (firstpoint[1] == secondpoint[1])) {
+      printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+             secondpoint[0], secondpoint[1]);
+/*  Commented out - would eliminate point from output .node file.
+      setpointmark(secondpoint, DEADPOINT);
+*/
+    }
+  } while ((firstpoint[0] == secondpoint[0])
+           && (firstpoint[1] == secondpoint[1]));
+  setorg(lefttri, firstpoint);
+  setdest(lefttri, secondpoint);
+  setorg(righttri, secondpoint);
+  setdest(righttri, firstpoint);
+  lprev(lefttri, bottommost);
+  lastpoint = secondpoint;
+  while (heapsize > 0) {
+    nextevent = eventheap[0];
+    eventheapdelete(eventheap, heapsize, 0);
+    heapsize--;
+    check4events = 1;
+    if (nextevent->xkey < xmin) {
+      decode(nextevent->eventptr, fliptri);
+      oprev(fliptri, farlefttri);
+      check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
+      onext(fliptri, farrighttri);
+      check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
+
+      if (triedgeequal(farlefttri, bottommost)) {
+        lprev(fliptri, bottommost);
+      }
+      flip(&fliptri);
+      setapex(fliptri, NULL);
+      lprev(fliptri, lefttri);
+      lnext(fliptri, righttri);
+      sym(lefttri, farlefttri);
+
+      if (randomnation(SAMPLERATE) == 0) {
+        symself(fliptri);
+        dest(fliptri, leftpoint);
+        apex(fliptri, midpoint);
+        org(fliptri, rightpoint);
+        splayroot = circletopinsert(splayroot, &lefttri, leftpoint, midpoint,
+                                    rightpoint, nextevent->ykey);
+      }
+    } else {
+      nextpoint = (point) nextevent->eventptr;
+      if ((nextpoint[0] == lastpoint[0]) && (nextpoint[1] == lastpoint[1])) {
+        printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+               nextpoint[0], nextpoint[1]);
+/*  Commented out - would eliminate point from output .node file.
+        setpointmark(nextpoint, DEADPOINT);
+*/
+        check4events = 0;
+      } else {
+        lastpoint = nextpoint;
+
+        splayroot = frontlocate(splayroot, &bottommost, nextpoint, &searchtri,
+                                &farrightflag);
+/*
+        triedgecopy(bottommost, searchtri);
+        farrightflag = 0;
+        while (!farrightflag && rightofhyperbola(&searchtri, nextpoint)) {
+          onextself(searchtri);
+          farrightflag = triedgeequal(searchtri, bottommost);
+        }
+*/
+
+        check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
+
+        triedgecopy(searchtri, farrighttri);
+        sym(searchtri, farlefttri);
+        maketriangle(&lefttri);
+        maketriangle(&righttri);
+        dest(farrighttri, connectpoint);
+        setorg(lefttri, connectpoint);
+        setdest(lefttri, nextpoint);
+        setorg(righttri, nextpoint);
+        setdest(righttri, connectpoint);
+        bond(lefttri, righttri);
+        lnextself(lefttri);
+        lprevself(righttri);
+        bond(lefttri, righttri);
+        lnextself(lefttri);
+        lprevself(righttri);
+        bond(lefttri, farlefttri);
+        bond(righttri, farrighttri);
+        if (!farrightflag && triedgeequal(farrighttri, bottommost)) {
+          triedgecopy(lefttri, bottommost);
+        }
+
+        if (randomnation(SAMPLERATE) == 0) {
+          splayroot = splayinsert(splayroot, &lefttri, nextpoint);
+        } else if (randomnation(SAMPLERATE) == 0) {
+          lnext(righttri, inserttri);
+          splayroot = splayinsert(splayroot, &inserttri, nextpoint);
+        }
+      }
+    }
+    nextevent->eventptr = (VOID *) freeevents;
+    freeevents = nextevent;
+
+    if (check4events) {
+      apex(farlefttri, leftpoint);
+      dest(lefttri, midpoint);
+      apex(lefttri, rightpoint);
+      lefttest = counterclockwise(leftpoint, midpoint, rightpoint);
+      if (lefttest > 0.0) {
+        newevent = freeevents;
+        freeevents = (struct event *) freeevents->eventptr;
+        newevent->xkey = xminextreme;
+        newevent->ykey = circletop(leftpoint, midpoint, rightpoint,
+                                   lefttest);
+        newevent->eventptr = (VOID *) encode(lefttri);
+        eventheapinsert(eventheap, heapsize, newevent);
+        heapsize++;
+        setorg(lefttri, newevent);
+      }
+      apex(righttri, leftpoint);
+      org(righttri, midpoint);
+      apex(farrighttri, rightpoint);
+      righttest = counterclockwise(leftpoint, midpoint, rightpoint);
+      if (righttest > 0.0) {
+        newevent = freeevents;
+        freeevents = (struct event *) freeevents->eventptr;
+        newevent->xkey = xminextreme;
+        newevent->ykey = circletop(leftpoint, midpoint, rightpoint,
+                                   righttest);
+        newevent->eventptr = (VOID *) encode(farrighttri);
+        eventheapinsert(eventheap, heapsize, newevent);
+        heapsize++;
+        setorg(farrighttri, newevent);
+      }
+    }
+  }
+
+  pooldeinit(&splaynodes);
+  lprevself(bottommost);
+  return removeghosts(&bottommost);
+}
+
+#endif /* not REDUCED */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Sweepline Delaunay triangulation ends here                *********/
+
+/********* General mesh construction routines begin here             *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  delaunay()   Form a Delaunay triangulation.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+long delaunay()
+{
+  eextras = 0;
+  initializetrisegpools();
+
+#ifdef REDUCED
+  if (!quiet) {
+    printf(
+      "Constructing Delaunay triangulation by divide-and-conquer method.\n");
+  }
+  return divconqdelaunay();
+#else /* not REDUCED */
+  if (!quiet) {
+    printf("Constructing Delaunay triangulation ");
+    if (incremental) {
+      printf("by incremental method.\n");
+    } else if (sweepline) {
+      printf("by sweepline method.\n");
+    } else {
+      printf("by divide-and-conquer method.\n");
+    }
+  }
+  if (incremental) {
+    return incrementaldelaunay();
+  } else if (sweepline) {
+    return sweeplinedelaunay();
+  } else {
+    return divconqdelaunay();
+  }
+#endif /* not REDUCED */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  reconstruct()   Reconstruct a triangulation from its .ele (and possibly  */
+/*                  .poly) file.  Used when the -r switch is used.           */
+/*                                                                           */
+/*  Reads an .ele file and reconstructs the original mesh.  If the -p switch */
+/*  is used, this procedure will also read a .poly file and reconstruct the  */
+/*  shell edges of the original mesh.  If the -a switch is used, this        */
+/*  procedure will also read an .area file and set a maximum area constraint */
+/*  on each triangle.                                                        */
+/*                                                                           */
+/*  Points that are not corners of triangles, such as nodes on edges of      */
+/*  subparametric elements, are discarded.                                   */
+/*                                                                           */
+/*  This routine finds the adjacencies between triangles (and shell edges)   */
+/*  by forming one stack of triangles for each vertex.  Each triangle is on  */
+/*  three different stacks simultaneously.  Each triangle's shell edge       */
+/*  pointers are used to link the items in each stack.  This memory-saving   */
+/*  feature makes the code harder to read.  The most important thing to keep */
+/*  in mind is that each triangle is removed from a stack precisely when     */
+/*  the corresponding pointer is adjusted to refer to a shell edge rather    */
+/*  than the next triangle of the stack.                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+#ifdef TRILIBRARY
+
+int reconstruct(trianglelist, triangleattriblist, trianglearealist, elements,
+                corners, attribs, segmentlist, segmentmarkerlist,
+                numberofsegments)
+int *trianglelist;
+REAL *triangleattriblist;
+REAL *trianglearealist;
+int elements;
+int corners;
+int attribs;
+int *segmentlist;
+int *segmentmarkerlist;
+int numberofsegments;
+
+#else /* not TRILIBRARY */
+
+long reconstruct(elefilename, areafilename, polyfilename, polyfile)
+char *elefilename;
+char *areafilename;
+char *polyfilename;
+FILE *polyfile;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int pointindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *elefile;
+  FILE *areafile;
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  int areaelements;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop;
+  struct triedge triangleleft;
+  struct triedge checktri;
+  struct triedge checkleft;
+  struct triedge checkneighbor;
+  struct edge shelleloop;
+  triangle *vertexarray;
+  triangle *prevlink;
+  triangle nexttri;
+  point tdest, tapex;
+  point checkdest, checkapex;
+  point shorg;
+  point killpoint;
+  REAL area;
+  int corner[3];
+  int end[2];
+  int killpointindex;
+  int incorners;
+  int segmentmarkers;
+  int boundmarker;
+  int aroundpoint;
+  long hullsize;
+  int notfound;
+  int elementnumber, segmentnumber;
+  int i, j;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+#ifdef TRILIBRARY
+  inelements = elements;
+  incorners = corners;
+  if (incorners < 3) {
+    printf("Error:  Triangles must have at least 3 points.\n");
+    exit(1);
+  }
+  eextras = attribs;
+#else /* not TRILIBRARY */
+  /* Read the triangles from an .ele file. */
+  if (!quiet) {
+    printf("Opening %s.\n", elefilename);
+  }
+  elefile = fopen(elefilename, "r");
+  if (elefile == (FILE *) NULL) {
+    printf("  Error:  Cannot access file %s.\n", elefilename);
+    exit(1);
+  }
+  /* Read number of triangles, number of points per triangle, and */
+  /*   number of triangle attributes from .ele file.              */
+  stringptr = readline(inputline, elefile, elefilename);
+  inelements = (int) strtol (stringptr, &stringptr, 0);
+  stringptr = findfield(stringptr);
+  if (*stringptr == '\0') {
+    incorners = 3;
+  } else {
+    incorners = (int) strtol (stringptr, &stringptr, 0);
+    if (incorners < 3) {
+      printf("Error:  Triangles in %s must have at least 3 points.\n",
+             elefilename);
+      exit(1);
+    }
+  }
+  stringptr = findfield(stringptr);
+  if (*stringptr == '\0') {
+    eextras = 0;
+  } else {
+    eextras = (int) strtol (stringptr, &stringptr, 0);
+  }
+#endif /* not TRILIBRARY */
+
+  initializetrisegpools();
+
+  /* Create the triangles. */
+  for (elementnumber = 1; elementnumber <= inelements; elementnumber++) {
+    maketriangle(&triangleloop);
+    /* Mark the triangle as living. */
+    triangleloop.tri[3] = (triangle) triangleloop.tri;
+  }
+
+  if (poly) {
+#ifdef TRILIBRARY
+    insegments = numberofsegments;
+    segmentmarkers = segmentmarkerlist != (int *) NULL;
+#else /* not TRILIBRARY */
+    /* Read number of segments and number of segment */
+    /*   boundary markers from .poly file.           */
+    stringptr = readline(inputline, polyfile, inpolyfilename);
+    insegments = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      segmentmarkers = 0;
+    } else {
+      segmentmarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+#endif /* not TRILIBRARY */
+
+    /* Create the shell edges. */
+    for (segmentnumber = 1; segmentnumber <= insegments; segmentnumber++) {
+      makeshelle(&shelleloop);
+      /* Mark the shell edge as living. */
+      shelleloop.sh[2] = (shelle) shelleloop.sh;
+    }
+  }
+
+#ifdef TRILIBRARY
+  pointindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (vararea) {
+    /* Open an .area file, check for consistency with the .ele file. */
+    if (!quiet) {
+      printf("Opening %s.\n", areafilename);
+    }
+    areafile = fopen(areafilename, "r");
+    if (areafile == (FILE *) NULL) {
+      printf("  Error:  Cannot access file %s.\n", areafilename);
+      exit(1);
+    }
+    stringptr = readline(inputline, areafile, areafilename);
+    areaelements = (int) strtol (stringptr, &stringptr, 0);
+    if (areaelements != inelements) {
+      printf("Error:  %s and %s disagree on number of triangles.\n",
+             elefilename, areafilename);
+      exit(1);
+    }
+  }
+#endif /* not TRILIBRARY */
+
+  if (!quiet) {
+    printf("Reconstructing mesh.\n");
+  }
+  /* Allocate a temporary array that maps each point to some adjacent  */
+  /*   triangle.  I took care to allocate all the permanent memory for */
+  /*   triangles and shell edges first.                                */
+  vertexarray = (triangle *) malloc(points.items * sizeof(triangle));
+  if (vertexarray == (triangle *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  /* Each point is initially unrepresented. */
+  for (i = 0; i < points.items; i++) {
+    vertexarray[i] = (triangle) dummytri;
+  }
+
+  if (verbose) {
+    printf("  Assembling triangles.\n");
+  }
+  /* Read the triangles from the .ele file, and link */
+  /*   together those that share an edge.            */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+#ifdef TRILIBRARY
+    /* Copy the triangle's three corners. */
+    for (j = 0; j < 3; j++) {
+      corner[j] = trianglelist[pointindex++];
+      if ((corner[j] < firstnumber) || (corner[j] >= firstnumber + inpoints)) {
+        printf("Error:  Triangle %d has an invalid vertex index.\n",
+               elementnumber);
+        exit(1);
+      }
+    }
+#else /* not TRILIBRARY */
+    /* Read triangle number and the triangle's three corners. */
+    stringptr = readline(inputline, elefile, elefilename);
+    for (j = 0; j < 3; j++) {
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Triangle %d is missing point %d in %s.\n",
+               elementnumber, j + 1, elefilename);
+        exit(1);
+      } else {
+        corner[j] = (int) strtol (stringptr, &stringptr, 0);
+        if ((corner[j] < firstnumber) ||
+            (corner[j] >= firstnumber + inpoints)) {
+          printf("Error:  Triangle %d has an invalid vertex index.\n",
+                 elementnumber);
+          exit(1);
+        }
+      }
+    }
+#endif /* not TRILIBRARY */
+
+    /* Find out about (and throw away) extra nodes. */
+    for (j = 3; j < incorners; j++) {
+#ifdef TRILIBRARY
+      killpointindex = trianglelist[pointindex++];
+#else /* not TRILIBRARY */
+      stringptr = findfield(stringptr);
+      if (*stringptr != '\0') {
+        killpointindex = (int) strtol (stringptr, &stringptr, 0);
+#endif /* not TRILIBRARY */
+        if ((killpointindex >= firstnumber) &&
+            (killpointindex < firstnumber + inpoints)) {
+          /* Delete the non-corner point if it's not already deleted. */
+          killpoint = getpoint(killpointindex);
+          if (pointmark(killpoint) != DEADPOINT) {
+            pointdealloc(killpoint);
+          }
+        }
+#ifndef TRILIBRARY
+      }
+#endif /* not TRILIBRARY */
+    }
+
+    /* Read the triangle's attributes. */
+    for (j = 0; j < eextras; j++) {
+#ifdef TRILIBRARY
+      setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
+#else /* not TRILIBRARY */
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        setelemattribute(triangleloop, j, 0);
+      } else {
+        setelemattribute(triangleloop, j,
+                         (REAL) strtod (stringptr, &stringptr));
+      }
+#endif /* not TRILIBRARY */
+    }
+
+    if (vararea) {
+#ifdef TRILIBRARY
+      area = trianglearealist[elementnumber - firstnumber];
+#else /* not TRILIBRARY */
+      /* Read an area constraint from the .area file. */
+      stringptr = readline(inputline, areafile, areafilename);
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        area = -1.0;                      /* No constraint on this triangle. */
+      } else {
+        area = (REAL) strtod(stringptr, &stringptr);
+      }
+#endif /* not TRILIBRARY */
+      setareabound(triangleloop, area);
+    }
+
+    /* Set the triangle's vertices. */
+    triangleloop.orient = 0;
+    setorg(triangleloop, getpoint(corner[0]));
+    setdest(triangleloop, getpoint(corner[1]));
+    setapex(triangleloop, getpoint(corner[2]));
+    /* Try linking the triangle to others that share these vertices. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      /* Take the number for the origin of triangleloop. */
+      aroundpoint = corner[triangleloop.orient];
+      /* Look for other triangles having this vertex. */
+      nexttri = vertexarray[aroundpoint - firstnumber];
+      /* Link the current triangle to the next one in the stack. */
+      triangleloop.tri[6 + triangleloop.orient] = nexttri;
+      /* Push the current triangle onto the stack. */
+      vertexarray[aroundpoint - firstnumber] = encode(triangleloop);
+      decode(nexttri, checktri);
+      if (checktri.tri != dummytri) {
+        dest(triangleloop, tdest);
+        apex(triangleloop, tapex);
+        /* Look for other triangles that share an edge. */
+        do {
+          dest(checktri, checkdest);
+          apex(checktri, checkapex);
+          if (tapex == checkdest) {
+            /* The two triangles share an edge; bond them together. */
+            lprev(triangleloop, triangleleft);
+            bond(triangleleft, checktri);
+          }
+          if (tdest == checkapex) {
+            /* The two triangles share an edge; bond them together. */
+            lprev(checktri, checkleft);
+            bond(triangleloop, checkleft);
+          }
+          /* Find the next triangle in the stack. */
+          nexttri = checktri.tri[6 + checktri.orient];
+          decode(nexttri, checktri);
+        } while (checktri.tri != dummytri);
+      }
+    }
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+
+#ifdef TRILIBRARY
+  pointindex = 0;
+#else /* not TRILIBRARY */
+  fclose(elefile);
+  if (vararea) {
+    fclose(areafile);
+  }
+#endif /* not TRILIBRARY */
+
+  hullsize = 0;                      /* Prepare to count the boundary edges. */
+  if (poly) {
+    if (verbose) {
+      printf("  Marking segments in triangulation.\n");
+    }
+    /* Read the segments from the .poly file, and link them */
+    /*   to their neighboring triangles.                    */
+    boundmarker = 0;
+    traversalinit(&shelles);
+    shelleloop.sh = shelletraverse();
+    segmentnumber = firstnumber;
+    while (shelleloop.sh != (shelle *) NULL) {
+#ifdef TRILIBRARY
+      end[0] = segmentlist[pointindex++];
+      end[1] = segmentlist[pointindex++];
+      if (segmentmarkers) {
+        boundmarker = segmentmarkerlist[segmentnumber - firstnumber];
+      }
+#else /* not TRILIBRARY */
+      /* Read the endpoints of each segment, and possibly a boundary marker. */
+      stringptr = readline(inputline, polyfile, inpolyfilename);
+      /* Skip the first (segment number) field. */
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d has no endpoints in %s.\n", segmentnumber,
+               polyfilename);
+        exit(1);
+      } else {
+        end[0] = (int) strtol (stringptr, &stringptr, 0);
+      }
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d is missing its second endpoint in %s.\n",
+               segmentnumber, polyfilename);
+        exit(1);
+      } else {
+        end[1] = (int) strtol (stringptr, &stringptr, 0);
+      }
+      if (segmentmarkers) {
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          boundmarker = 0;
+        } else {
+          boundmarker = (int) strtol (stringptr, &stringptr, 0);
+        }
+      }
+#endif /* not TRILIBRARY */
+      for (j = 0; j < 2; j++) {
+        if ((end[j] < firstnumber) || (end[j] >= firstnumber + inpoints)) {
+          printf("Error:  Segment %d has an invalid vertex index.\n", 
+                 segmentnumber);
+          exit(1);
+        }
+      }
+
+      /* set the shell edge's vertices. */
+      shelleloop.shorient = 0;
+      setsorg(shelleloop, getpoint(end[0]));
+      setsdest(shelleloop, getpoint(end[1]));
+      setmark(shelleloop, boundmarker);
+      /* Try linking the shell edge to triangles that share these vertices. */
+      for (shelleloop.shorient = 0; shelleloop.shorient < 2;
+           shelleloop.shorient++) {
+        /* Take the number for the destination of shelleloop. */
+        aroundpoint = end[1 - shelleloop.shorient];
+        /* Look for triangles having this vertex. */
+        prevlink = &vertexarray[aroundpoint - firstnumber];
+        nexttri = vertexarray[aroundpoint - firstnumber];
+        decode(nexttri, checktri);
+        sorg(shelleloop, shorg);
+        notfound = 1;
+        /* Look for triangles having this edge.  Note that I'm only       */
+        /*   comparing each triangle's destination with the shell edge;   */
+        /*   each triangle's apex is handled through a different vertex.  */
+        /*   Because each triangle appears on three vertices' lists, each */
+        /*   occurrence of a triangle on a list can (and does) represent  */
+        /*   an edge.  In this way, most edges are represented twice, and */
+        /*   every triangle-segment bond is represented once.             */
+        while (notfound && (checktri.tri != dummytri)) {
+          dest(checktri, checkdest);
+          if (shorg == checkdest) {
+            /* We have a match.  Remove this triangle from the list. */
+            *prevlink = checktri.tri[6 + checktri.orient];
+            /* Bond the shell edge to the triangle. */
+            tsbond(checktri, shelleloop);
+            /* Check if this is a boundary edge. */
+            sym(checktri, checkneighbor);
+            if (checkneighbor.tri == dummytri) {
+              /* The next line doesn't insert a shell edge (because there's */
+              /*   already one there), but it sets the boundary markers of  */
+              /*   the existing shell edge and its vertices.                */
+              insertshelle(&checktri, 1);
+              hullsize++;
+            }
+            notfound = 0;
+          }
+          /* Find the next triangle in the stack. */
+          prevlink = &checktri.tri[6 + checktri.orient];
+          nexttri = checktri.tri[6 + checktri.orient];
+          decode(nexttri, checktri);
+        }
+      }
+      shelleloop.sh = shelletraverse();
+      segmentnumber++;
+    }
+  }
+
+  /* Mark the remaining edges as not being attached to any shell edge. */
+  /* Also, count the (yet uncounted) boundary edges.                   */
+  for (i = 0; i < points.items; i++) {
+    /* Search the stack of triangles adjacent to a point. */
+    nexttri = vertexarray[i];
+    decode(nexttri, checktri);
+    while (checktri.tri != dummytri) {
+      /* Find the next triangle in the stack before this */
+      /*   information gets overwritten.                 */
+      nexttri = checktri.tri[6 + checktri.orient];
+      /* No adjacent shell edge.  (This overwrites the stack info.) */
+      tsdissolve(checktri);
+      sym(checktri, checkneighbor);
+      if (checkneighbor.tri == dummytri) {
+        insertshelle(&checktri, 1);
+        hullsize++;
+      }
+      decode(nexttri, checktri);
+    }
+  }
+
+  free(vertexarray);
+  return hullsize;
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* General mesh construction routines end here               *********/
+
+/********* Segment (shell edge) insertion begins here                *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  finddirection()   Find the first triangle on the path from one point     */
+/*                    to another.                                            */
+/*                                                                           */
+/*  Finds the triangle that intersects a line segment drawn from the         */
+/*  origin of `searchtri' to the point `endpoint', and returns the result    */
+/*  in `searchtri'.  The origin of `searchtri' does not change, even though  */
+/*  the triangle returned may differ from the one passed in.  This routine   */
+/*  is used to find the direction to move in to get from one point to        */
+/*  another.                                                                 */
+/*                                                                           */
+/*  The return value notes whether the destination or apex of the found      */
+/*  triangle is collinear with the two points in question.                   */
+/*                                                                           */
+/*****************************************************************************/
+
+enum finddirectionresult finddirection(searchtri, endpoint)
+struct triedge *searchtri;
+point endpoint;
+{
+  struct triedge checktri;
+  point startpoint;
+  point leftpoint, rightpoint;
+  REAL leftccw, rightccw;
+  int leftflag, rightflag;
+  triangle ptr;           /* Temporary variable used by onext() and oprev(). */
+
+  org(*searchtri, startpoint);
+  dest(*searchtri, rightpoint);
+  apex(*searchtri, leftpoint);
+  /* Is `endpoint' to the left? */
+  leftccw = counterclockwise(endpoint, startpoint, leftpoint);
+  leftflag = leftccw > 0.0;
+  /* Is `endpoint' to the right? */
+  rightccw = counterclockwise(startpoint, endpoint, rightpoint);
+  rightflag = rightccw > 0.0;
+  if (leftflag && rightflag) {
+    /* `searchtri' faces directly away from `endpoint'.  We could go */
+    /*   left or right.  Ask whether it's a triangle or a boundary   */
+    /*   on the left.                                                */
+    onext(*searchtri, checktri);
+    if (checktri.tri == dummytri) {
+      leftflag = 0;
+    } else {
+      rightflag = 0;
+    }
+  }
+  while (leftflag) {
+    /* Turn left until satisfied. */
+    onextself(*searchtri);
+    if (searchtri->tri == dummytri) {
+      printf("Internal error in finddirection():  Unable to find a\n");
+      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
+             startpoint[1]);
+      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
+      internalerror();
+    }
+    apex(*searchtri, leftpoint);
+    rightccw = leftccw;
+    leftccw = counterclockwise(endpoint, startpoint, leftpoint);
+    leftflag = leftccw > 0.0;
+  }
+  while (rightflag) {
+    /* Turn right until satisfied. */
+    oprevself(*searchtri);
+    if (searchtri->tri == dummytri) {
+      printf("Internal error in finddirection():  Unable to find a\n");
+      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
+             startpoint[1]);
+      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
+      internalerror();
+    }
+    dest(*searchtri, rightpoint);
+    leftccw = rightccw;
+    rightccw = counterclockwise(startpoint, endpoint, rightpoint);
+    rightflag = rightccw > 0.0;
+  }
+  if (leftccw == 0.0) {
+    return LEFTCOLLINEAR;
+  } else if (rightccw == 0.0) {
+    return RIGHTCOLLINEAR;
+  } else {
+    return WITHIN;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  segmentintersection()   Find the intersection of an existing segment     */
+/*                          and a segment that is being inserted.  Insert    */
+/*                          a point at the intersection, splitting an        */
+/*                          existing shell edge.                             */
+/*                                                                           */
+/*  The segment being inserted connects the apex of splittri to endpoint2.   */
+/*  splitshelle is the shell edge being split, and MUST be opposite          */
+/*  splittri.  Hence, the edge being split connects the origin and           */
+/*  destination of splittri.                                                 */
+/*                                                                           */
+/*  On completion, splittri is a handle having the newly inserted            */
+/*  intersection point as its origin, and endpoint1 as its destination.      */
+/*                                                                           */
+/*****************************************************************************/
+
+void segmentintersection(splittri, splitshelle, endpoint2)
+struct triedge *splittri;
+struct edge *splitshelle;
+point endpoint2;
+{
+  point endpoint1;
+  point torg, tdest;
+  point leftpoint, rightpoint;
+  point newpoint;
+  enum insertsiteresult success;
+  enum finddirectionresult collinear;
+  REAL ex, ey;
+  REAL tx, ty;
+  REAL etx, ety;
+  REAL split, denom;
+  int i;
+  triangle ptr;                       /* Temporary variable used by onext(). */
+
+  /* Find the other three segment endpoints. */
+  apex(*splittri, endpoint1);
+  org(*splittri, torg);
+  dest(*splittri, tdest);
+  /* Segment intersection formulae; see the Antonio reference. */
+  tx = tdest[0] - torg[0];
+  ty = tdest[1] - torg[1];
+  ex = endpoint2[0] - endpoint1[0];
+  ey = endpoint2[1] - endpoint1[1];
+  etx = torg[0] - endpoint2[0];
+  ety = torg[1] - endpoint2[1];
+  denom = ty * ex - tx * ey;
+  if (denom == 0.0) {
+    printf("Internal error in segmentintersection():");
+    printf("  Attempt to find intersection of parallel segments.\n");
+    internalerror();
+  }
+  split = (ey * etx - ex * ety) / denom;
+  /* Create the new point. */
+  newpoint = (point) poolalloc(&points);
+  /* Interpolate its coordinate and attributes. */
+  for (i = 0; i < 2 + nextras; i++) {
+    newpoint[i] = torg[i] + split * (tdest[i] - torg[i]);
+  }
+  setpointmark(newpoint, mark(*splitshelle));
+  if (verbose > 1) {
+    printf(
+    "  Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
+           torg[0], torg[1], tdest[0], tdest[1], newpoint[0], newpoint[1]);
+  }
+  /* Insert the intersection point.  This should always succeed. */
+  success = insertsite(newpoint, splittri, splitshelle, 0, 0);
+  if (success != SUCCESSFULPOINT) {
+    printf("Internal error in segmentintersection():\n");
+    printf("  Failure to split a segment.\n");
+    internalerror();
+  }
+  if (steinerleft > 0) {
+    steinerleft--;
+  }
+  /* Inserting the point may have caused edge flips.  We wish to rediscover */
+  /*   the edge connecting endpoint1 to the new intersection point.         */
+  collinear = finddirection(splittri, endpoint1);
+  dest(*splittri, rightpoint);
+  apex(*splittri, leftpoint);
+  if ((leftpoint[0] == endpoint1[0]) && (leftpoint[1] == endpoint1[1])) {
+    onextself(*splittri);
+  } else if ((rightpoint[0] != endpoint1[0]) ||
+             (rightpoint[1] != endpoint1[1])) {
+    printf("Internal error in segmentintersection():\n");
+    printf("  Topological inconsistency after splitting a segment.\n");
+    internalerror();
+  }
+  /* `splittri' should have destination endpoint1. */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  scoutsegment()   Scout the first triangle on the path from one endpoint  */
+/*                   to another, and check for completion (reaching the      */
+/*                   second endpoint), a collinear point, and the            */
+/*                   intersection of two segments.                           */
+/*                                                                           */
+/*  Returns one if the entire segment is successfully inserted, and zero if  */
+/*  the job must be finished by conformingedge() or constrainededge().       */
+/*                                                                           */
+/*  If the first triangle on the path has the second endpoint as its         */
+/*  destination or apex, a shell edge is inserted and the job is done.       */
+/*                                                                           */
+/*  If the first triangle on the path has a destination or apex that lies on */
+/*  the segment, a shell edge is inserted connecting the first endpoint to   */
+/*  the collinear point, and the search is continued from the collinear      */
+/*  point.                                                                   */
+/*                                                                           */
+/*  If the first triangle on the path has a shell edge opposite its origin,  */
+/*  then there is a segment that intersects the segment being inserted.      */
+/*  Their intersection point is inserted, splitting the shell edge.          */
+/*                                                                           */
+/*  Otherwise, return zero.                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+int scoutsegment(searchtri, endpoint2, newmark)
+struct triedge *searchtri;
+point endpoint2;
+int newmark;
+{
+  struct triedge crosstri;
+  struct edge crossedge;
+  point leftpoint, rightpoint;
+  point endpoint1;
+  enum finddirectionresult collinear;
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  collinear = finddirection(searchtri, endpoint2);
+  dest(*searchtri, rightpoint);
+  apex(*searchtri, leftpoint);
+  if (((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) ||
+      ((rightpoint[0] == endpoint2[0]) && (rightpoint[1] == endpoint2[1]))) {
+    /* The segment is already an edge in the mesh. */
+    if ((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) {
+      lprevself(*searchtri);
+    }
+    /* Insert a shell edge, if there isn't already one there. */
+    insertshelle(searchtri, newmark);
+    return 1;
+  } else if (collinear == LEFTCOLLINEAR) {
+    /* We've collided with a point between the segment's endpoints. */
+    /* Make the collinear point be the triangle's origin. */
+    lprevself(*searchtri);
+    insertshelle(searchtri, newmark);
+    /* Insert the remainder of the segment. */
+    return scoutsegment(searchtri, endpoint2, newmark);
+  } else if (collinear == RIGHTCOLLINEAR) {
+    /* We've collided with a point between the segment's endpoints. */
+    insertshelle(searchtri, newmark);
+    /* Make the collinear point be the triangle's origin. */
+    lnextself(*searchtri);
+    /* Insert the remainder of the segment. */
+    return scoutsegment(searchtri, endpoint2, newmark);
+  } else {
+    lnext(*searchtri, crosstri);
+    tspivot(crosstri, crossedge);
+    /* Check for a crossing segment. */
+    if (crossedge.sh == dummysh) {
+      return 0;
+    } else {
+      org(*searchtri, endpoint1);
+      /* Insert a point at the intersection. */
+      segmentintersection(&crosstri, &crossedge, endpoint2);
+      triedgecopy(crosstri, *searchtri);
+      insertshelle(searchtri, newmark);
+      /* Insert the remainder of the segment. */
+      return scoutsegment(searchtri, endpoint2, newmark);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  conformingedge()   Force a segment into a conforming Delaunay            */
+/*                     triangulation by inserting a point at its midpoint,   */
+/*                     and recursively forcing in the two half-segments if   */
+/*                     necessary.                                            */
+/*                                                                           */
+/*  Generates a sequence of edges connecting `endpoint1' to `endpoint2'.     */
+/*  `newmark' is the boundary marker of the segment, assigned to each new    */
+/*  splitting point and shell edge.                                          */
+/*                                                                           */
+/*  Note that conformingedge() does not always maintain the conforming       */
+/*  Delaunay property.  Once inserted, segments are locked into place;       */
+/*  points inserted later (to force other segments in) may render these      */
+/*  fixed segments non-Delaunay.  The conforming Delaunay property will be   */
+/*  restored by enforcequality() by splitting encroached segments.           */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+#ifndef CDT_ONLY
+
+void conformingedge(endpoint1, endpoint2, newmark)
+point endpoint1;
+point endpoint2;
+int newmark;
+{
+  struct triedge searchtri1, searchtri2;
+  struct edge brokenshelle;
+  point newpoint;
+  point midpoint1, midpoint2;
+  enum insertsiteresult success;
+  int result1, result2;
+  int i;
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose > 2) {
+    printf("Forcing segment into triangulation by recursive splitting:\n");
+    printf("  (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
+           endpoint2[0], endpoint2[1]);
+  }
+  /* Create a new point to insert in the middle of the segment. */
+  newpoint = (point) poolalloc(&points);
+  /* Interpolate coordinates and attributes. */
+  for (i = 0; i < 2 + nextras; i++) {
+    newpoint[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
+  }
+  setpointmark(newpoint, newmark);
+  /* Find a boundary triangle to search from. */
+  searchtri1.tri = (triangle *) NULL;
+  /* Attempt to insert the new point. */
+  success = insertsite(newpoint, &searchtri1, (struct edge *) NULL, 0, 0);
+  if (success == DUPLICATEPOINT) {
+    if (verbose > 2) {
+      printf("  Segment intersects existing point (%.12g, %.12g).\n",
+             newpoint[0], newpoint[1]);
+    }
+    /* Use the point that's already there. */
+    pointdealloc(newpoint);
+    org(searchtri1, newpoint);
+  } else {
+    if (success == VIOLATINGPOINT) {
+      if (verbose > 2) {
+        printf("  Two segments intersect at (%.12g, %.12g).\n",
+               newpoint[0], newpoint[1]);
+      }
+      /* By fluke, we've landed right on another segment.  Split it. */
+      tspivot(searchtri1, brokenshelle);
+      success = insertsite(newpoint, &searchtri1, &brokenshelle, 0, 0);
+      if (success != SUCCESSFULPOINT) {
+        printf("Internal error in conformingedge():\n");
+        printf("  Failure to split a segment.\n");
+        internalerror();
+      }
+    }
+    /* The point has been inserted successfully. */
+    if (steinerleft > 0) {
+      steinerleft--;
+    }
+  }
+  triedgecopy(searchtri1, searchtri2);
+  result1 = scoutsegment(&searchtri1, endpoint1, newmark);
+  result2 = scoutsegment(&searchtri2, endpoint2, newmark);
+  if (!result1) {
+    /* The origin of searchtri1 may have changed if a collision with an */
+    /*   intervening vertex on the segment occurred.                    */
+    org(searchtri1, midpoint1);
+    conformingedge(midpoint1, endpoint1, newmark);
+  }
+  if (!result2) {
+    /* The origin of searchtri2 may have changed if a collision with an */
+    /*   intervening vertex on the segment occurred.                    */
+    org(searchtri2, midpoint2);
+    conformingedge(midpoint2, endpoint2, newmark);
+  }
+}
+
+#endif /* not CDT_ONLY */
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  delaunayfixup()   Enforce the Delaunay condition at an edge, fanning out */
+/*                    recursively from an existing point.  Pay special       */
+/*                    attention to stacking inverted triangles.              */
+/*                                                                           */
+/*  This is a support routine for inserting segments into a constrained      */
+/*  Delaunay triangulation.                                                  */
+/*                                                                           */
+/*  The origin of fixuptri is treated as if it has just been inserted, and   */
+/*  the local Delaunay condition needs to be enforced.  It is only enforced  */
+/*  in one sector, however, that being the angular range defined by          */
+/*  fixuptri.                                                                */
+/*                                                                           */
+/*  This routine also needs to make decisions regarding the "stacking" of    */
+/*  triangles.  (Read the description of constrainededge() below before      */
+/*  reading on here, so you understand the algorithm.)  If the position of   */
+/*  the new point (the origin of fixuptri) indicates that the vertex before  */
+/*  it on the polygon is a reflex vertex, then "stack" the triangle by       */
+/*  doing nothing.  (fixuptri is an inverted triangle, which is how stacked  */
+/*  triangles are identified.)                                               */
+/*                                                                           */
+/*  Otherwise, check whether the vertex before that was a reflex vertex.     */
+/*  If so, perform an edge flip, thereby eliminating an inverted triangle    */
+/*  (popping it off the stack).  The edge flip may result in the creation    */
+/*  of a new inverted triangle, depending on whether or not the new vertex   */
+/*  is visible to the vertex three edges behind on the polygon.              */
+/*                                                                           */
+/*  If neither of the two vertices behind the new vertex are reflex          */
+/*  vertices, fixuptri and fartri, the triangle opposite it, are not         */
+/*  inverted; hence, ensure that the edge between them is locally Delaunay.  */
+/*                                                                           */
+/*  `leftside' indicates whether or not fixuptri is to the left of the       */
+/*  segment being inserted.  (Imagine that the segment is pointing up from   */
+/*  endpoint1 to endpoint2.)                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+void delaunayfixup(fixuptri, leftside)
+struct triedge *fixuptri;
+int leftside;
+{
+  struct triedge neartri;
+  struct triedge fartri;
+  struct edge faredge;
+  point nearpoint, leftpoint, rightpoint, farpoint;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  lnext(*fixuptri, neartri);
+  sym(neartri, fartri);
+  /* Check if the edge opposite the origin of fixuptri can be flipped. */
+  if (fartri.tri == dummytri) {
+    return;
+  }
+  tspivot(neartri, faredge);
+  if (faredge.sh != dummysh) {
+    return;
+  }
+  /* Find all the relevant vertices. */
+  apex(neartri, nearpoint);
+  org(neartri, leftpoint);
+  dest(neartri, rightpoint);
+  apex(fartri, farpoint);
+  /* Check whether the previous polygon vertex is a reflex vertex. */
+  if (leftside) {
+    if (counterclockwise(nearpoint, leftpoint, farpoint) <= 0.0) {
+      /* leftpoint is a reflex vertex too.  Nothing can */
+      /*   be done until a convex section is found.     */
+      return;
+    }
+  } else {
+    if (counterclockwise(farpoint, rightpoint, nearpoint) <= 0.0) {
+      /* rightpoint is a reflex vertex too.  Nothing can */
+      /*   be done until a convex section is found.      */
+      return;
+    }
+  }
+  if (counterclockwise(rightpoint, leftpoint, farpoint) > 0.0) {
+    /* fartri is not an inverted triangle, and farpoint is not a reflex */
+    /*   vertex.  As there are no reflex vertices, fixuptri isn't an    */
+    /*   inverted triangle, either.  Hence, test the edge between the   */
+    /*   triangles to ensure it is locally Delaunay.                    */
+    if (incircle(leftpoint, farpoint, rightpoint, nearpoint) <= 0.0) {
+      return;
+    }
+    /* Not locally Delaunay; go on to an edge flip. */
+  }        /* else fartri is inverted; remove it from the stack by flipping. */
+  flip(&neartri);
+  lprevself(*fixuptri);    /* Restore the origin of fixuptri after the flip. */
+  /* Recursively process the two triangles that result from the flip. */
+  delaunayfixup(fixuptri, leftside);
+  delaunayfixup(&fartri, leftside);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  constrainededge()   Force a segment into a constrained Delaunay          */
+/*                      triangulation by deleting the triangles it           */
+/*                      intersects, and triangulating the polygons that      */
+/*                      form on each side of it.                             */
+/*                                                                           */
+/*  Generates a single edge connecting `endpoint1' to `endpoint2'.  The      */
+/*  triangle `starttri' has `endpoint1' as its origin.  `newmark' is the     */
+/*  boundary marker of the segment.                                          */
+/*                                                                           */
+/*  To insert a segment, every triangle whose interior intersects the        */
+/*  segment is deleted.  The union of these deleted triangles is a polygon   */
+/*  (which is not necessarily monotone, but is close enough), which is       */
+/*  divided into two polygons by the new segment.  This routine's task is    */
+/*  to generate the Delaunay triangulation of these two polygons.            */
+/*                                                                           */
+/*  You might think of this routine's behavior as a two-step process.  The   */
+/*  first step is to walk from endpoint1 to endpoint2, flipping each edge    */
+/*  encountered.  This step creates a fan of edges connected to endpoint1,   */
+/*  including the desired edge to endpoint2.  The second step enforces the   */
+/*  Delaunay condition on each side of the segment in an incremental manner: */
+/*  proceeding along the polygon from endpoint1 to endpoint2 (this is done   */
+/*  independently on each side of the segment), each vertex is "enforced"    */
+/*  as if it had just been inserted, but affecting only the previous         */
+/*  vertices.  The result is the same as if the vertices had been inserted   */
+/*  in the order they appear on the polygon, so the result is Delaunay.      */
+/*                                                                           */
+/*  In truth, constrainededge() interleaves these two steps.  The procedure  */
+/*  walks from endpoint1 to endpoint2, and each time an edge is encountered  */
+/*  and flipped, the newly exposed vertex (at the far end of the flipped     */
+/*  edge) is "enforced" upon the previously flipped edges, usually affecting */
+/*  only one side of the polygon (depending upon which side of the segment   */
+/*  the vertex falls on).                                                    */
+/*                                                                           */
+/*  The algorithm is complicated by the need to handle polygons that are not */
+/*  convex.  Although the polygon is not necessarily monotone, it can be     */
+/*  triangulated in a manner similar to the stack-based algorithms for       */
+/*  monotone polygons.  For each reflex vertex (local concavity) of the      */
+/*  polygon, there will be an inverted triangle formed by one of the edge    */
+/*  flips.  (An inverted triangle is one with negative area - that is, its   */
+/*  vertices are arranged in clockwise order - and is best thought of as a   */
+/*  wrinkle in the fabric of the mesh.)  Each inverted triangle can be       */
+/*  thought of as a reflex vertex pushed on the stack, waiting to be fixed   */
+/*  later.                                                                   */
+/*                                                                           */
+/*  A reflex vertex is popped from the stack when a vertex is inserted that  */
+/*  is visible to the reflex vertex.  (However, if the vertex behind the     */
+/*  reflex vertex is not visible to the reflex vertex, a new inverted        */
+/*  triangle will take its place on the stack.)  These details are handled   */
+/*  by the delaunayfixup() routine above.                                    */
+/*                                                                           */
+/*****************************************************************************/
+
+void constrainededge(starttri, endpoint2, newmark)
+struct triedge *starttri;
+point endpoint2;
+int newmark;
+{
+  struct triedge fixuptri, fixuptri2;
+  struct edge fixupedge;
+  point endpoint1;
+  point farpoint;
+  REAL area;
+  int collision;
+  int done;
+  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  org(*starttri, endpoint1);
+  lnext(*starttri, fixuptri);
+  flip(&fixuptri);
+  /* `collision' indicates whether we have found a point directly */
+  /*   between endpoint1 and endpoint2.                           */
+  collision = 0;
+  done = 0;
+  do {
+    org(fixuptri, farpoint);
+    /* `farpoint' is the extreme point of the polygon we are "digging" */
+    /*   to get from endpoint1 to endpoint2.                           */
+    if ((farpoint[0] == endpoint2[0]) && (farpoint[1] == endpoint2[1])) {
+      oprev(fixuptri, fixuptri2);
+      /* Enforce the Delaunay condition around endpoint2. */
+      delaunayfixup(&fixuptri, 0);
+      delaunayfixup(&fixuptri2, 1);
+      done = 1;
+    } else {
+      /* Check whether farpoint is to the left or right of the segment */
+      /*   being inserted, to decide which edge of fixuptri to dig     */
+      /*   through next.                                               */
+      area = counterclockwise(endpoint1, endpoint2, farpoint);
+      if (area == 0.0) {
+        /* We've collided with a point between endpoint1 and endpoint2. */
+        collision = 1;
+        oprev(fixuptri, fixuptri2);
+        /* Enforce the Delaunay condition around farpoint. */
+        delaunayfixup(&fixuptri, 0);
+        delaunayfixup(&fixuptri2, 1);
+        done = 1;
+      } else {
+        if (area > 0.0) {         /* farpoint is to the left of the segment. */
+          oprev(fixuptri, fixuptri2);
+          /* Enforce the Delaunay condition around farpoint, on the */
+          /*   left side of the segment only.                       */
+          delaunayfixup(&fixuptri2, 1);
+          /* Flip the edge that crosses the segment.  After the edge is */
+          /*   flipped, one of its endpoints is the fan vertex, and the */
+          /*   destination of fixuptri is the fan vertex.               */
+          lprevself(fixuptri);
+        } else {                 /* farpoint is to the right of the segment. */
+          delaunayfixup(&fixuptri, 0);
+          /* Flip the edge that crosses the segment.  After the edge is */
+          /*   flipped, one of its endpoints is the fan vertex, and the */
+          /*   destination of fixuptri is the fan vertex.               */
+          oprevself(fixuptri);
+        }
+        /* Check for two intersecting segments. */
+        tspivot(fixuptri, fixupedge);
+        if (fixupedge.sh == dummysh) {
+          flip(&fixuptri);   /* May create an inverted triangle on the left. */
+        } else {
+          /* We've collided with a segment between endpoint1 and endpoint2. */
+          collision = 1;
+          /* Insert a point at the intersection. */
+          segmentintersection(&fixuptri, &fixupedge, endpoint2);
+          done = 1;
+        }
+      }
+    }
+  } while (!done);
+  /* Insert a shell edge to make the segment permanent. */
+  insertshelle(&fixuptri, newmark);
+  /* If there was a collision with an interceding vertex, install another */
+  /*   segment connecting that vertex with endpoint2.                     */
+  if (collision) {
+    /* Insert the remainder of the segment. */
+    if (!scoutsegment(&fixuptri, endpoint2, newmark)) {
+      constrainededge(&fixuptri, endpoint2, newmark);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  insertsegment()   Insert a PSLG segment into a triangulation.            */
+/*                                                                           */
+/*****************************************************************************/
+
+void insertsegment(endpoint1, endpoint2, newmark)
+point endpoint1;
+point endpoint2;
+int newmark;
+{
+  struct triedge searchtri1, searchtri2;
+  triangle encodedtri;
+  point checkpoint;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose > 1) {
+    printf("  Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
+           endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
+  }
+
+  /* Find a triangle whose origin is the segment's first endpoint. */
+  checkpoint = (point) NULL;
+  encodedtri = point2tri(endpoint1);
+  if (encodedtri != (triangle) NULL) {
+    decode(encodedtri, searchtri1);
+    org(searchtri1, checkpoint);
+  }
+  if (checkpoint != endpoint1) {
+    /* Find a boundary triangle to search from. */
+    searchtri1.tri = dummytri;
+    searchtri1.orient = 0;
+    symself(searchtri1);
+    /* Search for the segment's first endpoint by point location. */
+    if (locate(endpoint1, &searchtri1) != ONVERTEX) {
+      printf(
+        "Internal error in insertsegment():  Unable to locate PSLG point\n");
+      printf("  (%.12g, %.12g) in triangulation.\n",
+             endpoint1[0], endpoint1[1]);
+      internalerror();
+    }
+  }
+  /* Remember this triangle to improve subsequent point location. */
+  triedgecopy(searchtri1, recenttri);
+  /* Scout the beginnings of a path from the first endpoint */
+  /*   toward the second.                                   */
+  if (scoutsegment(&searchtri1, endpoint2, newmark)) {
+    /* The segment was easily inserted. */
+    return;
+  }
+  /* The first endpoint may have changed if a collision with an intervening */
+  /*   vertex on the segment occurred.                                      */
+  org(searchtri1, endpoint1);
+
+  /* Find a triangle whose origin is the segment's second endpoint. */
+  checkpoint = (point) NULL;
+  encodedtri = point2tri(endpoint2);
+  if (encodedtri != (triangle) NULL) {
+    decode(encodedtri, searchtri2);
+    org(searchtri2, checkpoint);
+  }
+  if (checkpoint != endpoint2) {
+    /* Find a boundary triangle to search from. */
+    searchtri2.tri = dummytri;
+    searchtri2.orient = 0;
+    symself(searchtri2);
+    /* Search for the segment's second endpoint by point location. */
+    if (locate(endpoint2, &searchtri2) != ONVERTEX) {
+      printf(
+        "Internal error in insertsegment():  Unable to locate PSLG point\n");
+      printf("  (%.12g, %.12g) in triangulation.\n",
+             endpoint2[0], endpoint2[1]);
+      internalerror();
+    }
+  }
+  /* Remember this triangle to improve subsequent point location. */
+  triedgecopy(searchtri2, recenttri);
+  /* Scout the beginnings of a path from the second endpoint */
+  /*   toward the first.                                     */
+  if (scoutsegment(&searchtri2, endpoint1, newmark)) {
+    /* The segment was easily inserted. */
+    return;
+  }
+  /* The second endpoint may have changed if a collision with an intervening */
+  /*   vertex on the segment occurred.                                       */
+  org(searchtri2, endpoint2);
+
+#ifndef REDUCED
+#ifndef CDT_ONLY
+  if (splitseg) {
+    /* Insert vertices to force the segment into the triangulation. */
+    conformingedge(endpoint1, endpoint2, newmark);
+  } else {
+#endif /* not CDT_ONLY */
+#endif /* not REDUCED */
+    /* Insert the segment directly into the triangulation. */
+    constrainededge(&searchtri1, endpoint2, newmark);
+#ifndef REDUCED
+#ifndef CDT_ONLY
+  }
+#endif /* not CDT_ONLY */
+#endif /* not REDUCED */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  markhull()   Cover the convex hull of a triangulation with shell edges.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void markhull()
+{
+  struct triedge hulltri;
+  struct triedge nexttri;
+  struct triedge starttri;
+  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
+
+  /* Find a triangle handle on the hull. */
+  hulltri.tri = dummytri;
+  hulltri.orient = 0;
+  symself(hulltri);
+  /* Remember where we started so we know when to stop. */
+  triedgecopy(hulltri, starttri);
+  /* Go once counterclockwise around the convex hull. */
+  do {
+    /* Create a shell edge if there isn't already one here. */
+    insertshelle(&hulltri, 1);
+    /* To find the next hull edge, go clockwise around the next vertex. */
+    lnextself(hulltri);
+    oprev(hulltri, nexttri);
+    while (nexttri.tri != dummytri) {
+      triedgecopy(nexttri, hulltri);
+      oprev(hulltri, nexttri);
+    }
+  } while (!triedgeequal(hulltri, starttri));
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  formskeleton()   Create the shell edges of a triangulation, including    */
+/*                   PSLG edges and edges on the convex hull.                */
+/*                                                                           */
+/*  The PSLG edges are read from a .poly file.  The return value is the      */
+/*  number of segments in the file.                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+int formskeleton(segmentlist, segmentmarkerlist, numberofsegments)
+int *segmentlist;
+int *segmentmarkerlist;
+int numberofsegments;
+
+#else /* not TRILIBRARY */
+
+int formskeleton(polyfile, polyfilename)
+FILE *polyfile;
+char *polyfilename;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  char polyfilename[6];
+  int index;
+#else /* not TRILIBRARY */
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+#endif /* not TRILIBRARY */
+  point endpoint1, endpoint2;
+  int segments;
+  int segmentmarkers;
+  int end1, end2;
+  int boundmarker;
+  int i;
+
+  if (poly) {
+    if (!quiet) {
+      printf("Inserting segments into Delaunay triangulation.\n");
+    }
+#ifdef TRILIBRARY
+    strcpy(polyfilename, "input");
+    segments = numberofsegments;
+    segmentmarkers = segmentmarkerlist != (int *) NULL;
+    index = 0;
+#else /* not TRILIBRARY */
+    /* Read the segments from a .poly file. */
+    /* Read number of segments and number of boundary markers. */
+    stringptr = readline(inputline, polyfile, polyfilename);
+    segments = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      segmentmarkers = 0;
+    } else {
+      segmentmarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+#endif /* not TRILIBRARY */
+    /* If segments are to be inserted, compute a mapping */
+    /*   from points to triangles.                       */
+    if (segments > 0) {
+      if (verbose) {
+        printf("  Inserting PSLG segments.\n");
+      }
+      makepointmap();
+    }
+
+    boundmarker = 0;
+    /* Read and insert the segments. */
+    for (i = 1; i <= segments; i++) {
+#ifdef TRILIBRARY
+      end1 = segmentlist[index++];
+      end2 = segmentlist[index++];
+      if (segmentmarkers) {
+        boundmarker = segmentmarkerlist[i - 1];
+      }
+#else /* not TRILIBRARY */
+      stringptr = readline(inputline, polyfile, inpolyfilename);
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d has no endpoints in %s.\n", i,
+               polyfilename);
+        exit(1);
+      } else {
+        end1 = (int) strtol (stringptr, &stringptr, 0);
+      }
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d is missing its second endpoint in %s.\n", i,
+               polyfilename);
+        exit(1);
+      } else {
+        end2 = (int) strtol (stringptr, &stringptr, 0);
+      }
+      if (segmentmarkers) {
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          boundmarker = 0;
+        } else {
+          boundmarker = (int) strtol (stringptr, &stringptr, 0);
+        }
+      }
+#endif /* not TRILIBRARY */
+      if ((end1 < firstnumber) || (end1 >= firstnumber + inpoints)) {
+        if (!quiet) {
+          printf("Warning:  Invalid first endpoint of segment %d in %s.\n", i,
+                 polyfilename);
+        }
+      } else if ((end2 < firstnumber) || (end2 >= firstnumber + inpoints)) {
+        if (!quiet) {
+          printf("Warning:  Invalid second endpoint of segment %d in %s.\n", i,
+                 polyfilename);
+        }
+      } else {
+        endpoint1 = getpoint(end1);
+        endpoint2 = getpoint(end2);
+        if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
+          if (!quiet) {
+            printf("Warning:  Endpoints of segment %d are coincident in %s.\n",
+                   i, polyfilename);
+          }
+        } else {
+          insertsegment(endpoint1, endpoint2, boundmarker);
+        }
+      }
+    }
+  } else {
+    segments = 0;
+  }
+  if (convex || !poly) {
+    /* Enclose the convex hull with shell edges. */
+    if (verbose) {
+      printf("  Enclosing convex hull with segments.\n");
+    }
+    markhull();
+  }
+  return segments;
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Segment (shell edge) insertion ends here                  *********/
+
+/********* Carving out holes and concavities begins here             *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  infecthull()   Virally infect all of the triangles of the convex hull    */
+/*                 that are not protected by shell edges.  Where there are   */
+/*                 shell edges, set boundary markers as appropriate.         */
+/*                                                                           */
+/*****************************************************************************/
+
+void infecthull()
+{
+  struct triedge hulltri;
+  struct triedge nexttri;
+  struct triedge starttri;
+  struct edge hulledge;
+  triangle **deadtri;
+  point horg, hdest;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose) {
+    printf("  Marking concavities (external triangles) for elimination.\n");
+  }
+  /* Find a triangle handle on the hull. */
+  hulltri.tri = dummytri;
+  hulltri.orient = 0;
+  symself(hulltri);
+  /* Remember where we started so we know when to stop. */
+  triedgecopy(hulltri, starttri);
+  /* Go once counterclockwise around the convex hull. */
+  do {
+    /* Ignore triangles that are already infected. */
+    if (!infected(hulltri)) {
+      /* Is the triangle protected by a shell edge? */
+      tspivot(hulltri, hulledge);
+      if (hulledge.sh == dummysh) {
+        /* The triangle is not protected; infect it. */
+        infect(hulltri);
+        deadtri = (triangle **) poolalloc(&viri);
+        *deadtri = hulltri.tri;
+      } else {
+        /* The triangle is protected; set boundary markers if appropriate. */
+        if (mark(hulledge) == 0) {
+          setmark(hulledge, 1);
+          org(hulltri, horg);
+          dest(hulltri, hdest);
+          if (pointmark(horg) == 0) {
+            setpointmark(horg, 1);
+          }
+          if (pointmark(hdest) == 0) {
+            setpointmark(hdest, 1);
+          }
+        }
+      }
+    }
+    /* To find the next hull edge, go clockwise around the next vertex. */
+    lnextself(hulltri);
+    oprev(hulltri, nexttri);
+    while (nexttri.tri != dummytri) {
+      triedgecopy(nexttri, hulltri);
+      oprev(hulltri, nexttri);
+    }
+  } while (!triedgeequal(hulltri, starttri));
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  plague()   Spread the virus from all infected triangles to any neighbors */
+/*             not protected by shell edges.  Delete all infected triangles. */
+/*                                                                           */
+/*  This is the procedure that actually creates holes and concavities.       */
+/*                                                                           */
+/*  This procedure operates in two phases.  The first phase identifies all   */
+/*  the triangles that will die, and marks them as infected.  They are       */
+/*  marked to ensure that each triangle is added to the virus pool only      */
+/*  once, so the procedure will terminate.                                   */
+/*                                                                           */
+/*  The second phase actually eliminates the infected triangles.  It also    */
+/*  eliminates orphaned points.                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+void plague()
+{
+  struct triedge testtri;
+  struct triedge neighbor;
+  triangle **virusloop;
+  triangle **deadtri;
+  struct edge neighborshelle;
+  point testpoint;
+  point norg, ndest;
+  point deadorg, deaddest, deadapex;
+  int killorg;
+  triangle ptr;             /* Temporary variable used by sym() and onext(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose) {
+    printf("  Marking neighbors of marked triangles.\n");
+  }
+  /* Loop through all the infected triangles, spreading the virus to */
+  /*   their neighbors, then to their neighbors' neighbors.          */
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+    /* A triangle is marked as infected by messing with one of its shell */
+    /*   edges, setting it to an illegal value.  Hence, we have to       */
+    /*   temporarily uninfect this triangle so that we can examine its   */
+    /*   adjacent shell edges.                                           */
+    uninfect(testtri);
+    if (verbose > 2) {
+      /* Assign the triangle an orientation for convenience in */
+      /*   checking its points.                                */
+      testtri.orient = 0;
+      org(testtri, deadorg);
+      dest(testtri, deaddest);
+      apex(testtri, deadapex);
+      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+             deadorg[0], deadorg[1], deaddest[0], deaddest[1],
+             deadapex[0], deadapex[1]);
+    }
+    /* Check each of the triangle's three neighbors. */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      /* Find the neighbor. */
+      sym(testtri, neighbor);
+      /* Check for a shell between the triangle and its neighbor. */
+      tspivot(testtri, neighborshelle);
+      /* Check if the neighbor is nonexistent or already infected. */
+      if ((neighbor.tri == dummytri) || infected(neighbor)) {
+        if (neighborshelle.sh != dummysh) {
+          /* There is a shell edge separating the triangle from its */
+          /*   neighbor, but both triangles are dying, so the shell */
+          /*   edge dies too.                                       */
+          shelledealloc(neighborshelle.sh);
+          if (neighbor.tri != dummytri) {
+            /* Make sure the shell edge doesn't get deallocated again */
+            /*   later when the infected neighbor is visited.         */
+            uninfect(neighbor);
+            tsdissolve(neighbor);
+            infect(neighbor);
+          }
+        }
+      } else {                   /* The neighbor exists and is not infected. */
+        if (neighborshelle.sh == dummysh) {
+          /* There is no shell edge protecting the neighbor, so */
+          /*   the neighbor becomes infected.                   */
+          if (verbose > 2) {
+            org(neighbor, deadorg);
+            dest(neighbor, deaddest);
+            apex(neighbor, deadapex);
+            printf(
+              "    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+                   deadorg[0], deadorg[1], deaddest[0], deaddest[1],
+                   deadapex[0], deadapex[1]);
+          }
+          infect(neighbor);
+          /* Ensure that the neighbor's neighbors will be infected. */
+          deadtri = (triangle **) poolalloc(&viri);
+          *deadtri = neighbor.tri;
+        } else {               /* The neighbor is protected by a shell edge. */
+          /* Remove this triangle from the shell edge. */
+          stdissolve(neighborshelle);
+          /* The shell edge becomes a boundary.  Set markers accordingly. */
+          if (mark(neighborshelle) == 0) {
+            setmark(neighborshelle, 1);
+          }
+          org(neighbor, norg);
+          dest(neighbor, ndest);
+          if (pointmark(norg) == 0) {
+            setpointmark(norg, 1);
+          }
+          if (pointmark(ndest) == 0) {
+            setpointmark(ndest, 1);
+          }
+        }
+      }
+    }
+    /* Remark the triangle as infected, so it doesn't get added to the */
+    /*   virus pool again.                                             */
+    infect(testtri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+
+  if (verbose) {
+    printf("  Deleting marked triangles.\n");
+  }
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+
+    /* Check each of the three corners of the triangle for elimination. */
+    /*   This is done by walking around each point, checking if it is   */
+    /*   still connected to at least one live triangle.                 */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      org(testtri, testpoint);
+      /* Check if the point has already been tested. */
+      if (testpoint != (point) NULL) {
+        killorg = 1;
+        /* Mark the corner of the triangle as having been tested. */
+        setorg(testtri, NULL);
+        /* Walk counterclockwise about the point. */
+        onext(testtri, neighbor);
+        /* Stop upon reaching a boundary or the starting triangle. */
+        while ((neighbor.tri != dummytri)
+               && (!triedgeequal(neighbor, testtri))) {
+          if (infected(neighbor)) {
+            /* Mark the corner of this triangle as having been tested. */
+            setorg(neighbor, NULL);
+          } else {
+            /* A live triangle.  The point survives. */
+            killorg = 0;
+          }
+          /* Walk counterclockwise about the point. */
+          onextself(neighbor);
+        }
+        /* If we reached a boundary, we must walk clockwise as well. */
+        if (neighbor.tri == dummytri) {
+          /* Walk clockwise about the point. */
+          oprev(testtri, neighbor);
+          /* Stop upon reaching a boundary. */
+          while (neighbor.tri != dummytri) {
+            if (infected(neighbor)) {
+            /* Mark the corner of this triangle as having been tested. */
+              setorg(neighbor, NULL);
+            } else {
+              /* A live triangle.  The point survives. */
+              killorg = 0;
+            }
+            /* Walk clockwise about the point. */
+            oprevself(neighbor);
+          }
+        }
+        if (killorg) {
+          if (verbose > 1) {
+            printf("    Deleting point (%.12g, %.12g)\n",
+                   testpoint[0], testpoint[1]);
+          }
+          pointdealloc(testpoint);
+        }
+      }
+    }
+
+    /* Record changes in the number of boundary edges, and disconnect */
+    /*   dead triangles from their neighbors.                         */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      sym(testtri, neighbor);
+      if (neighbor.tri == dummytri) {
+        /* There is no neighboring triangle on this edge, so this edge    */
+        /*   is a boundary edge.  This triangle is being deleted, so this */
+        /*   boundary edge is deleted.                                    */
+        hullsize--;
+      } else {
+        /* Disconnect the triangle from its neighbor. */
+        dissolve(neighbor);
+        /* There is a neighboring triangle on this edge, so this edge */
+        /*   becomes a boundary edge when this triangle is deleted.   */
+        hullsize++;
+      }
+    }
+    /* Return the dead triangle to the pool of triangles. */
+    triangledealloc(testtri.tri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+  /* Empty the virus pool. */
+  poolrestart(&viri);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  regionplague()   Spread regional attributes and/or area constraints      */
+/*                   (from a .poly file) throughout the mesh.                */
+/*                                                                           */
+/*  This procedure operates in two phases.  The first phase spreads an       */
+/*  attribute and/or an area constraint through a (segment-bounded) region.  */
+/*  The triangles are marked to ensure that each triangle is added to the    */
+/*  virus pool only once, so the procedure will terminate.                   */
+/*                                                                           */
+/*  The second phase uninfects all infected triangles, returning them to     */
+/*  normal.                                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void regionplague(attribute, area)
+REAL attribute;
+REAL area;
+{
+  struct triedge testtri;
+  struct triedge neighbor;
+  triangle **virusloop;
+  triangle **regiontri;
+  struct edge neighborshelle;
+  point regionorg, regiondest, regionapex;
+  triangle ptr;             /* Temporary variable used by sym() and onext(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose > 1) {
+    printf("  Marking neighbors of marked triangles.\n");
+  }
+  /* Loop through all the infected triangles, spreading the attribute      */
+  /*   and/or area constraint to their neighbors, then to their neighbors' */
+  /*   neighbors.                                                          */
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+    /* A triangle is marked as infected by messing with one of its shell */
+    /*   edges, setting it to an illegal value.  Hence, we have to       */
+    /*   temporarily uninfect this triangle so that we can examine its   */
+    /*   adjacent shell edges.                                           */
+    uninfect(testtri);
+    if (regionattrib) {
+      /* Set an attribute. */
+      setelemattribute(testtri, eextras, attribute);
+    }
+    if (vararea) {
+      /* Set an area constraint. */
+      setareabound(testtri, area);
+    }
+    if (verbose > 2) {
+      /* Assign the triangle an orientation for convenience in */
+      /*   checking its points.                                */
+      testtri.orient = 0;
+      org(testtri, regionorg);
+      dest(testtri, regiondest);
+      apex(testtri, regionapex);
+      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+             regionorg[0], regionorg[1], regiondest[0], regiondest[1],
+             regionapex[0], regionapex[1]);
+    }
+    /* Check each of the triangle's three neighbors. */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      /* Find the neighbor. */
+      sym(testtri, neighbor);
+      /* Check for a shell between the triangle and its neighbor. */
+      tspivot(testtri, neighborshelle);
+      /* Make sure the neighbor exists, is not already infected, and */
+      /*   isn't protected by a shell edge.                          */
+      if ((neighbor.tri != dummytri) && !infected(neighbor)
+          && (neighborshelle.sh == dummysh)) {
+        if (verbose > 2) {
+          org(neighbor, regionorg);
+          dest(neighbor, regiondest);
+          apex(neighbor, regionapex);
+          printf("    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+                 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
+                 regionapex[0], regionapex[1]);
+        }
+        /* Infect the neighbor. */
+        infect(neighbor);
+        /* Ensure that the neighbor's neighbors will be infected. */
+        regiontri = (triangle **) poolalloc(&viri);
+        *regiontri = neighbor.tri;
+      }
+    }
+    /* Remark the triangle as infected, so it doesn't get added to the */
+    /*   virus pool again.                                             */
+    infect(testtri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+
+  /* Uninfect all triangles. */
+  if (verbose > 1) {
+    printf("  Unmarking marked triangles.\n");
+  }
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+    uninfect(testtri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+  /* Empty the virus pool. */
+  poolrestart(&viri);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  carveholes()   Find the holes and infect them.  Find the area            */
+/*                 constraints and infect them.  Infect the convex hull.     */
+/*                 Spread the infection and kill triangles.  Spread the      */
+/*                 area constraints.                                         */
+/*                                                                           */
+/*  This routine mainly calls other routines to carry out all these          */
+/*  functions.                                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+void carveholes(holelist, holes, regionlist, regions)
+REAL *holelist;
+int holes;
+REAL *regionlist;
+int regions;
+{
+  struct triedge searchtri;
+  struct triedge triangleloop;
+  struct triedge *regiontris;
+  triangle **holetri;
+  triangle **regiontri;
+  point searchorg, searchdest;
+  enum locateresult intersect;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (!(quiet || (noholes && convex))) {
+    printf("Removing unwanted triangles.\n");
+    if (verbose && (holes > 0)) {
+      printf("  Marking holes for elimination.\n");
+    }
+  }
+
+  if (regions > 0) {
+    /* Allocate storage for the triangles in which region points fall. */
+    regiontris = (struct triedge *) malloc(regions * sizeof(struct triedge));
+    if (regiontris == (struct triedge *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+
+  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
+    /* Initialize a pool of viri to be used for holes, concavities, */
+    /*   regional attributes, and/or regional area constraints.     */
+    poolinit(&viri, sizeof(triangle *), VIRUSPERBLOCK, POINTER, 0);
+  }
+
+  if (!convex) {
+    /* Mark as infected any unprotected triangles on the boundary. */
+    /*   This is one way by which concavities are created.         */
+    infecthull();
+  }
+
+  if ((holes > 0) && !noholes) {
+    /* Infect each triangle in which a hole lies. */
+    for (i = 0; i < 2 * holes; i += 2) {
+      /* Ignore holes that aren't within the bounds of the mesh. */
+      if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
+          && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)) {
+        /* Start searching from some triangle on the outer boundary. */
+        searchtri.tri = dummytri;
+        searchtri.orient = 0;
+        symself(searchtri);
+        /* Ensure that the hole is to the left of this boundary edge; */
+        /*   otherwise, locate() will falsely report that the hole    */
+        /*   falls within the starting triangle.                      */
+        org(searchtri, searchorg);
+        dest(searchtri, searchdest);
+        if (counterclockwise(searchorg, searchdest, &holelist[i]) > 0.0) {
+          /* Find a triangle that contains the hole. */
+          intersect = locate(&holelist[i], &searchtri);
+          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
+            /* Infect the triangle.  This is done by marking the triangle */
+            /*   as infect and including the triangle in the virus pool.  */
+            infect(searchtri);
+            holetri = (triangle **) poolalloc(&viri);
+            *holetri = searchtri.tri;
+          }
+        }
+      }
+    }
+  }
+
+  /* Now, we have to find all the regions BEFORE we carve the holes, because */
+  /*   locate() won't work when the triangulation is no longer convex.       */
+  /*   (Incidentally, this is the reason why regional attributes and area    */
+  /*   constraints can't be used when refining a preexisting mesh, which     */
+  /*   might not be convex; they can only be used with a freshly             */
+  /*   triangulated PSLG.)                                                   */
+  if (regions > 0) {
+    /* Find the starting triangle for each region. */
+    for (i = 0; i < regions; i++) {
+      regiontris[i].tri = dummytri;
+      /* Ignore region points that aren't within the bounds of the mesh. */
+      if ((regionlist[4 * i] >= xmin) && (regionlist[4 * i] <= xmax) &&
+          (regionlist[4 * i + 1] >= ymin) && (regionlist[4 * i + 1] <= ymax)) {
+        /* Start searching from some triangle on the outer boundary. */
+        searchtri.tri = dummytri;
+        searchtri.orient = 0;
+        symself(searchtri);
+        /* Ensure that the region point is to the left of this boundary */
+        /*   edge; otherwise, locate() will falsely report that the     */
+        /*   region point falls within the starting triangle.           */
+        org(searchtri, searchorg);
+        dest(searchtri, searchdest);
+        if (counterclockwise(searchorg, searchdest, &regionlist[4 * i]) >
+            0.0) {
+          /* Find a triangle that contains the region point. */
+          intersect = locate(&regionlist[4 * i], &searchtri);
+          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
+            /* Record the triangle for processing after the */
+            /*   holes have been carved.                    */
+            triedgecopy(searchtri, regiontris[i]);
+          }
+        }
+      }
+    }
+  }
+
+  if (viri.items > 0) {
+    /* Carve the holes and concavities. */
+    plague();
+  }
+  /* The virus pool should be empty now. */
+
+  if (regions > 0) {
+    if (!quiet) {
+      if (regionattrib) {
+        if (vararea) {
+          printf("Spreading regional attributes and area constraints.\n");
+        } else {
+          printf("Spreading regional attributes.\n");
+        }
+      } else { 
+        printf("Spreading regional area constraints.\n");
+      }
+    }
+    if (regionattrib && !refine) {
+      /* Assign every triangle a regional attribute of zero. */
+      traversalinit(&triangles);
+      triangleloop.orient = 0;
+      triangleloop.tri = triangletraverse();
+      while (triangleloop.tri != (triangle *) NULL) {
+        setelemattribute(triangleloop, eextras, 0.0);
+        triangleloop.tri = triangletraverse();
+      }
+    }
+    for (i = 0; i < regions; i++) {
+      if (regiontris[i].tri != dummytri) {
+        /* Make sure the triangle under consideration still exists. */
+        /*   It may have been eaten by the virus.                   */
+        if (regiontris[i].tri[3] != (triangle) NULL) {
+          /* Put one triangle in the virus pool. */
+          infect(regiontris[i]);
+          regiontri = (triangle **) poolalloc(&viri);
+          *regiontri = regiontris[i].tri;
+          /* Apply one region's attribute and/or area constraint. */
+          regionplague(regionlist[4 * i + 2], regionlist[4 * i + 3]);
+          /* The virus pool should be empty now. */
+        }
+      }
+    }
+    if (regionattrib && !refine) {
+      /* Note the fact that each triangle has an additional attribute. */
+      eextras++;
+    }
+  }
+
+  /* Free up memory. */
+  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
+    pooldeinit(&viri);
+  }
+  if (regions > 0) {
+    free(regiontris);
+  }
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Carving out holes and concavities ends here               *********/
+
+/********* Mesh quality maintenance begins here                      *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  tallyencs()   Traverse the entire list of shell edges, check each edge   */
+/*                to see if it is encroached.  If so, add it to the list.    */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void tallyencs()
+{
+  struct edge edgeloop;
+  int dummy;
+
+  traversalinit(&shelles);
+  edgeloop.shorient = 0;
+  edgeloop.sh = shelletraverse();
+  while (edgeloop.sh != (shelle *) NULL) {
+    /* If the segment is encroached, add it to the list. */
+    dummy = checkedge4encroach(&edgeloop);
+    edgeloop.sh = shelletraverse();
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  precisionerror()  Print an error message for precision problems.         */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void precisionerror()
+{
+  printf("Try increasing the area criterion and/or reducing the minimum\n");
+  printf("  allowable angle so that tiny triangles are not created.\n");
+#ifdef SINGLE
+  printf("Alternatively, try recompiling me with double precision\n");
+  printf("  arithmetic (by removing \"#define SINGLE\" from the\n");
+  printf("  source file or \"-DSINGLE\" from the makefile).\n");
+#endif /* SINGLE */
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  repairencs()   Find and repair all the encroached segments.              */
+/*                                                                           */
+/*  Encroached segments are repaired by splitting them by inserting a point  */
+/*  at or near their centers.                                                */
+/*                                                                           */
+/*  `flaws' is a flag that specifies whether one should take note of new     */
+/*  encroached segments and bad triangles that result from inserting points  */
+/*  to repair existing encroached segments.                                  */
+/*                                                                           */
+/*  When a segment is split, the two resulting subsegments are always        */
+/*  tested to see if they are encroached upon, regardless of the value       */
+/*  of `flaws'.                                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void repairencs(flaws)
+int flaws;
+{
+  struct triedge enctri;
+  struct triedge testtri;
+  struct edge *encloop;
+  struct edge testsh;
+  point eorg, edest;
+  point newpoint;
+  enum insertsiteresult success;
+  REAL segmentlength, nearestpoweroftwo;
+  REAL split;
+  int acuteorg, acutedest;
+  int dummy;
+  int i;
+  triangle ptr;                     /* Temporary variable used by stpivot(). */
+  shelle sptr;                        /* Temporary variable used by snext(). */
+
+  while ((badsegments.items > 0) && (steinerleft != 0)) {
+    traversalinit(&badsegments);
+    encloop = badsegmenttraverse();
+    while ((encloop != (struct edge *) NULL) && (steinerleft != 0)) {
+      /* To decide where to split a segment, we need to know if the  */
+      /*   segment shares an endpoint with an adjacent segment.      */
+      /*   The concern is that, if we simply split every encroached  */
+      /*   segment in its center, two adjacent segments with a small */
+      /*   angle between them might lead to an infinite loop; each   */
+      /*   point added to split one segment will encroach upon the   */
+      /*   other segment, which must then be split with a point that */
+      /*   will encroach upon the first segment, and so on forever.  */
+      /* To avoid this, imagine a set of concentric circles, whose   */
+      /*   radii are powers of two, about each segment endpoint.     */
+      /*   These concentric circles determine where the segment is   */
+      /*   split.  (If both endpoints are shared with adjacent       */
+      /*   segments, split the segment in the middle, and apply the  */
+      /*   concentric shells for later splittings.)                  */
+
+      /* Is the origin shared with another segment? */
+      stpivot(*encloop, enctri);
+      lnext(enctri, testtri);
+      tspivot(testtri, testsh);
+      acuteorg = testsh.sh != dummysh;
+      /* Is the destination shared with another segment? */
+      lnextself(testtri);
+      tspivot(testtri, testsh);
+      acutedest = testsh.sh != dummysh;
+      /* Now, check the other side of the segment, if there's a triangle */
+      /*   there.                                                        */
+      sym(enctri, testtri);
+      if (testtri.tri != dummytri) {
+        /* Is the destination shared with another segment? */
+        lnextself(testtri);
+        tspivot(testtri, testsh);
+        acutedest = acutedest || (testsh.sh != dummysh);
+        /* Is the origin shared with another segment? */
+        lnextself(testtri);
+        tspivot(testtri, testsh);
+        acuteorg = acuteorg || (testsh.sh != dummysh);
+      }
+
+      sorg(*encloop, eorg);
+      sdest(*encloop, edest);
+      /* Use the concentric circles if exactly one endpoint is shared */
+      /*   with another adjacent segment.                             */
+      if (acuteorg ^ acutedest) {
+        segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0])
+                             + (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
+        /* Find the power of two nearest the segment's length. */
+        nearestpoweroftwo = 1.0;
+        while (segmentlength > SQUAREROOTTWO * nearestpoweroftwo) {
+          nearestpoweroftwo *= 2.0;
+        }
+        while (segmentlength < (0.5 * SQUAREROOTTWO) * nearestpoweroftwo) {
+          nearestpoweroftwo *= 0.5;
+        }
+        /* Where do we split the segment? */
+        split = 0.5 * nearestpoweroftwo / segmentlength;
+        if (acutedest) {
+          split = 1.0 - split;
+        }
+      } else {
+        /* If we're not worried about adjacent segments, split */
+        /*   this segment in the middle.                       */
+        split = 0.5;
+      }
+
+      /* Create the new point. */
+      newpoint = (point) poolalloc(&points);
+      /* Interpolate its coordinate and attributes. */
+      for (i = 0; i < 2 + nextras; i++) {
+        newpoint[i] = (1.0 - split) * eorg[i] + split * edest[i];
+      }
+      setpointmark(newpoint, mark(*encloop));
+      if (verbose > 1) {
+        printf(
+        "  Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
+               eorg[0], eorg[1], edest[0], edest[1], newpoint[0], newpoint[1]);
+      }
+      /* Check whether the new point lies on an endpoint. */
+      if (((newpoint[0] == eorg[0]) && (newpoint[1] == eorg[1]))
+        || ((newpoint[0] == edest[0]) && (newpoint[1] == edest[1]))) {
+        printf("Error:  Ran out of precision at (%.12g, %.12g).\n",
+               newpoint[0], newpoint[1]);
+        printf("I attempted to split a segment to a smaller size than can\n");
+        printf("  be accommodated by the finite precision of floating point\n"
+               );
+        printf("  arithmetic.\n");
+        precisionerror();
+        exit(1);
+      }
+      /* Insert the splitting point.  This should always succeed. */
+      success = insertsite(newpoint, &enctri, encloop, flaws, flaws);
+      if ((success != SUCCESSFULPOINT) && (success != ENCROACHINGPOINT)) {
+        printf("Internal error in repairencs():\n");
+        printf("  Failure to split a segment.\n");
+        internalerror();
+      }
+      if (steinerleft > 0) {
+        steinerleft--;
+      }
+      /* Check the two new subsegments to see if they're encroached. */
+      dummy = checkedge4encroach(encloop);
+      snextself(*encloop);
+      dummy = checkedge4encroach(encloop);
+
+      badsegmentdealloc(encloop);
+      encloop = badsegmenttraverse();
+    }
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  tallyfaces()   Test every triangle in the mesh for quality measures.     */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void tallyfaces()
+{
+  struct triedge triangleloop;
+
+  if (verbose) {
+    printf("  Making a list of bad triangles.\n");
+  }
+  traversalinit(&triangles);
+  triangleloop.orient = 0;
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* If the triangle is bad, enqueue it. */
+    testtriangle(&triangleloop);
+    triangleloop.tri = triangletraverse();
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  findcircumcenter()   Find the circumcenter of a triangle.                */
+/*                                                                           */
+/*  The result is returned both in terms of x-y coordinates and xi-eta       */
+/*  coordinates.  The xi-eta coordinate system is defined in terms of the    */
+/*  triangle:  the origin of the triangle is the origin of the coordinate    */
+/*  system; the destination of the triangle is one unit along the xi axis;   */
+/*  and the apex of the triangle is one unit along the eta axis.             */
+/*                                                                           */
+/*  The return value indicates which edge of the triangle is shortest.       */
+/*                                                                           */
+/*****************************************************************************/
+
+enum circumcenterresult findcircumcenter(torg, tdest, tapex, circumcenter,
+                                         xi, eta)
+point torg;
+point tdest;
+point tapex;
+point circumcenter;
+REAL *xi;
+REAL *eta;
+{
+  REAL xdo, ydo, xao, yao, xad, yad;
+  REAL dodist, aodist, addist;
+  REAL denominator;
+  REAL dx, dy;
+
+  circumcentercount++;
+
+  /* Compute the circumcenter of the triangle. */
+  xdo = tdest[0] - torg[0];
+  ydo = tdest[1] - torg[1];
+  xao = tapex[0] - torg[0];
+  yao = tapex[1] - torg[1];
+  dodist = xdo * xdo + ydo * ydo;
+  aodist = xao * xao + yao * yao;
+  if (noexact) {
+    denominator = 0.5 / (xdo * yao - xao * ydo);
+  } else {
+    /* Use the counterclockwise() routine to ensure a positive (and */
+    /*   reasonably accurate) result, avoiding any possibility of   */
+    /*   division by zero.                                          */
+    denominator = 0.5 / counterclockwise(tdest, tapex, torg);
+    /* Don't count the above as an orientation test. */
+    counterclockcount--;
+  }
+  circumcenter[0] = torg[0] - (ydo * aodist - yao * dodist) * denominator;  
+  circumcenter[1] = torg[1] + (xdo * aodist - xao * dodist) * denominator;  
+
+  /* To interpolate point attributes for the new point inserted at  */
+  /*   the circumcenter, define a coordinate system with a xi-axis, */
+  /*   directed from the triangle's origin to its destination, and  */
+  /*   an eta-axis, directed from its origin to its apex.           */
+  /*   Calculate the xi and eta coordinates of the circumcenter.    */
+  dx = circumcenter[0] - torg[0];
+  dy = circumcenter[1] - torg[1];
+  *xi = (dx * yao - xao * dy) * (2.0 * denominator);
+  *eta = (xdo * dy - dx * ydo) * (2.0 * denominator);
+
+  xad = tapex[0] - tdest[0];
+  yad = tapex[1] - tdest[1];
+  addist = xad * xad + yad * yad;
+  if ((addist < dodist) && (addist < aodist)) {
+    return OPPOSITEORG;
+  } else if (dodist < aodist) {
+    return OPPOSITEAPEX;
+  } else {
+    return OPPOSITEDEST;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  splittriangle()   Inserts a point at the circumcenter of a triangle.     */
+/*                    Deletes the newly inserted point if it encroaches upon */
+/*                    a segment.                                             */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void splittriangle(badtri)
+struct badface *badtri;
+{
+  point borg, bdest, bapex;
+  point newpoint;
+  REAL xi, eta;
+  enum insertsiteresult success;
+  enum circumcenterresult shortedge;
+  int errorflag;
+  int i;
+
+  org(badtri->badfacetri, borg);
+  dest(badtri->badfacetri, bdest);
+  apex(badtri->badfacetri, bapex);
+  /* Make sure that this triangle is still the same triangle it was      */
+  /*   when it was tested and determined to be of bad quality.           */
+  /*   Subsequent transformations may have made it a different triangle. */
+  if ((borg == badtri->faceorg) && (bdest == badtri->facedest) &&
+      (bapex == badtri->faceapex)) {
+    if (verbose > 1) {
+      printf("  Splitting this triangle at its circumcenter:\n");
+      printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
+             borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
+    }
+    errorflag = 0;
+    /* Create a new point at the triangle's circumcenter. */
+    newpoint = (point) poolalloc(&points);
+    shortedge = findcircumcenter(borg, bdest, bapex, newpoint, &xi, &eta);
+    /* Check whether the new point lies on a triangle vertex. */
+    if (((newpoint[0] == borg[0]) && (newpoint[1] == borg[1]))
+        || ((newpoint[0] == bdest[0]) && (newpoint[1] == bdest[1]))
+        || ((newpoint[0] == bapex[0]) && (newpoint[1] == bapex[1]))) {
+      if (!quiet) {
+        printf("Warning:  New point (%.12g, %.12g) falls on existing vertex.\n"
+               , newpoint[0], newpoint[1]);
+        errorflag = 1;
+      }
+      pointdealloc(newpoint);
+    } else {
+      for (i = 2; i < 2 + nextras; i++) {
+        /* Interpolate the point attributes at the circumcenter. */
+        newpoint[i] = borg[i] + xi * (bdest[i] - borg[i])
+                             + eta * (bapex[i] - borg[i]);
+      }
+      /* The new point must be in the interior, and have a marker of zero. */
+      setpointmark(newpoint, 0);
+      /* Ensure that the handle `badtri->badfacetri' represents the shortest */
+      /*   edge of the triangle.  This ensures that the circumcenter must    */
+      /*   fall to the left of this edge, so point location will work.       */
+      if (shortedge == OPPOSITEORG) {
+        lnextself(badtri->badfacetri);
+      } else if (shortedge == OPPOSITEDEST) {
+        lprevself(badtri->badfacetri);
+      }
+      /* Insert the circumcenter, searching from the edge of the triangle, */
+      /*   and maintain the Delaunay property of the triangulation.        */
+      success = insertsite(newpoint, &(badtri->badfacetri),
+                           (struct edge *) NULL, 1, 1);
+      if (success == SUCCESSFULPOINT) {
+        if (steinerleft > 0) {
+          steinerleft--;
+        }
+      } else if (success == ENCROACHINGPOINT) {
+        /* If the newly inserted point encroaches upon a segment, delete it. */
+        deletesite(&(badtri->badfacetri));
+      } else if (success == VIOLATINGPOINT) {
+        /* Failed to insert the new point, but some segment was */
+        /*   marked as being encroached.                        */
+        pointdealloc(newpoint);
+      } else {                                  /* success == DUPLICATEPOINT */
+        /* Failed to insert the new point because a vertex is already there. */
+        if (!quiet) {
+          printf(
+            "Warning:  New point (%.12g, %.12g) falls on existing vertex.\n"
+                 , newpoint[0], newpoint[1]);
+          errorflag = 1;
+        }
+        pointdealloc(newpoint);
+      }
+    }
+    if (errorflag) {
+      if (verbose) {
+        printf("  The new point is at the circumcenter of triangle\n");
+        printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+               borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
+      }
+      printf("This probably means that I am trying to refine triangles\n");
+      printf("  to a smaller size than can be accommodated by the finite\n");
+      printf("  precision of floating point arithmetic.  (You can be\n");
+      printf("  sure of this if I fail to terminate.)\n");
+      precisionerror();
+    }
+  }
+  /* Return the bad triangle to the pool. */
+  pooldealloc(&badtriangles, (VOID *) badtri);
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  enforcequality()   Remove all the encroached edges and bad triangles     */
+/*                     from the triangulation.                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void enforcequality()
+{
+  int i;
+
+  if (!quiet) {
+    printf("Adding Steiner points to enforce quality.\n");
+  }
+  /* Initialize the pool of encroached segments. */
+  poolinit(&badsegments, sizeof(struct edge), BADSEGMENTPERBLOCK, POINTER, 0);
+  if (verbose) {
+    printf("  Looking for encroached segments.\n");
+  }
+  /* Test all segments to see if they're encroached. */
+  tallyencs();
+  if (verbose && (badsegments.items > 0)) {
+    printf("  Splitting encroached segments.\n");
+  }
+  /* Note that steinerleft == -1 if an unlimited number */
+  /*   of Steiner points is allowed.                    */
+  while ((badsegments.items > 0) && (steinerleft != 0)) {
+    /* Fix the segments without noting newly encroached segments or   */
+    /*   bad triangles.  The reason we don't want to note newly       */
+    /*   encroached segments is because some encroached segments are  */
+    /*   likely to be noted multiple times, and would then be blindly */
+    /*   split multiple times.  I should fix that some time.          */
+    repairencs(0);
+    /* Now, find all the segments that became encroached while adding */
+    /*   points to split encroached segments.                         */
+    tallyencs();
+  }
+  /* At this point, if we haven't run out of Steiner points, the */
+  /*   triangulation should be (conforming) Delaunay.            */
+
+  /* Next, we worry about enforcing triangle quality. */
+  if ((minangle > 0.0) || vararea || fixedarea) {
+    /* Initialize the pool of bad triangles. */
+    poolinit(&badtriangles, sizeof(struct badface), BADTRIPERBLOCK, POINTER,
+             0);
+    /* Initialize the queues of bad triangles. */
+    for (i = 0; i < 64; i++) {
+      queuefront[i] = (struct badface *) NULL;
+      queuetail[i] = &queuefront[i];
+    }
+    /* Test all triangles to see if they're bad. */
+    tallyfaces();
+    if (verbose) {
+      printf("  Splitting bad triangles.\n");
+    }
+    while ((badtriangles.items > 0) && (steinerleft != 0)) {
+      /* Fix one bad triangle by inserting a point at its circumcenter. */
+      splittriangle(dequeuebadtri());
+      /* Fix any encroached segments that may have resulted.  Record */
+      /*   any new bad triangles or encroached segments that result. */
+      if (badsegments.items > 0) {
+        repairencs(1);
+      }
+    }
+  }
+  /* At this point, if we haven't run out of Steiner points, the */
+  /*   triangulation should be (conforming) Delaunay and have no */
+  /*   low-quality triangles.                                    */
+
+  /* Might we have run out of Steiner points too soon? */
+  if (!quiet && (badsegments.items > 0) && (steinerleft == 0)) {
+    printf("\nWarning:  I ran out of Steiner points, but the mesh has\n");
+    if (badsegments.items == 1) {
+      printf("  an encroached segment, and therefore might not be truly\n");
+    } else {
+      printf("  %ld encroached segments, and therefore might not be truly\n",
+             badsegments.items);
+    }
+    printf("  Delaunay.  If the Delaunay property is important to you,\n");
+    printf("  try increasing the number of Steiner points (controlled by\n");
+    printf("  the -S switch) slightly and try again.\n\n");
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh quality maintenance ends here                        *********/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  highorder()   Create extra nodes for quadratic subparametric elements.   */
+/*                                                                           */
+/*****************************************************************************/
+
+void highorder()
+{
+  struct triedge triangleloop, trisym;
+  struct edge checkmark;
+  point newpoint;
+  point torg, tdest;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (!quiet) {
+    printf("Adding vertices for second-order triangles.\n");
+  }
+  /* The following line ensures that dead items in the pool of nodes    */
+  /*   cannot be allocated for the extra nodes associated with high     */
+  /*   order elements.  This ensures that the primary nodes (at the     */
+  /*   corners of elements) will occur earlier in the output files, and */
+  /*   have lower indices, than the extra nodes.                        */
+  points.deaditemstack = (VOID *) NULL;
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  /* To loop over the set of edges, loop over all triangles, and look at   */
+  /*   the three edges of each triangle.  If there isn't another triangle  */
+  /*   adjacent to the edge, operate on the edge.  If there is another     */
+  /*   adjacent triangle, operate on the edge only if the current triangle */
+  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
+  /*   considered only once.                                               */
+  while (triangleloop.tri != (triangle *) NULL) {
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      sym(triangleloop, trisym);
+      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
+        org(triangleloop, torg);
+        dest(triangleloop, tdest);
+        /* Create a new node in the middle of the edge.  Interpolate */
+        /*   its attributes.                                         */
+        newpoint = (point) poolalloc(&points);
+        for (i = 0; i < 2 + nextras; i++) {
+          newpoint[i] = 0.5 * (torg[i] + tdest[i]);
+        }
+        /* Set the new node's marker to zero or one, depending on */
+        /*   whether it lies on a boundary.                       */
+        setpointmark(newpoint, trisym.tri == dummytri);
+        if (useshelles) {
+          tspivot(triangleloop, checkmark);
+          /* If this edge is a segment, transfer the marker to the new node. */
+          if (checkmark.sh != dummysh) {
+            setpointmark(newpoint, mark(checkmark));
+          }
+        }
+        if (verbose > 1) {
+          printf("  Creating (%.12g, %.12g).\n", newpoint[0], newpoint[1]);
+        }
+        /* Record the new node in the (one or two) adjacent elements. */
+        triangleloop.tri[highorderindex + triangleloop.orient] =
+                (triangle) newpoint;
+        if (trisym.tri != dummytri) {
+          trisym.tri[highorderindex + trisym.orient] = (triangle) newpoint;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+}
+
+/********* File I/O routines begin here                              *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  readline()   Read a nonempty line from a file.                           */
+/*                                                                           */
+/*  A line is considered "nonempty" if it contains something that looks like */
+/*  a number.                                                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+char *readline(string, infile, infilename)
+char *string;
+FILE *infile;
+char *infilename;
+{
+  char *result;
+
+  /* Search for something that looks like a number. */
+  do {
+    result = fgets(string, INPUTLINESIZE, infile);
+    if (result == (char *) NULL) {
+      printf("  Error:  Unexpected end of file in %s.\n", infilename);
+      exit(1);
+    }
+    /* Skip anything that doesn't look like a number, a comment, */
+    /*   or the end of a line.                                   */
+    while ((*result != '\0') && (*result != '#')
+           && (*result != '.') && (*result != '+') && (*result != '-')
+           && ((*result < '0') || (*result > '9'))) {
+      result++;
+    }
+  /* If it's a comment or end of line, read another line and try again. */
+  } while ((*result == '#') || (*result == '\0'));
+  return result;
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  findfield()   Find the next field of a string.                           */
+/*                                                                           */
+/*  Jumps past the current field by searching for whitespace, then jumps     */
+/*  past the whitespace to find the next field.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+char *findfield(string)
+char *string;
+{
+  char *result;
+
+  result = string;
+  /* Skip the current field.  Stop upon reaching whitespace. */
+  while ((*result != '\0') && (*result != '#')
+         && (*result != ' ') && (*result != '\t')) {
+    result++;
+  }
+  /* Now skip the whitespace and anything else that doesn't look like a */
+  /*   number, a comment, or the end of a line.                         */
+  while ((*result != '\0') && (*result != '#')
+         && (*result != '.') && (*result != '+') && (*result != '-')
+         && ((*result < '0') || (*result > '9'))) {
+    result++;
+  }
+  /* Check for a comment (prefixed with `#'). */
+  if (*result == '#') {
+    *result = '\0';
+  }
+  return result;
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  readnodes()   Read the points from a file, which may be a .node or .poly */
+/*                file.                                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void readnodes(nodefilename, polyfilename, polyfile)
+char *nodefilename;
+char *polyfilename;
+FILE **polyfile;
+{
+  FILE *infile;
+  point pointloop;
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  char *infilename;
+  REAL x, y;
+  int firstnode;
+  int nodemarkers;
+  int currentmarker;
+  int i, j;
+
+  if (poly) {
+    /* Read the points from a .poly file. */
+    if (!quiet) {
+      printf("Opening %s.\n", polyfilename);
+    }
+    *polyfile = fopen(polyfilename, "r");
+    if (*polyfile == (FILE *) NULL) {
+      printf("  Error:  Cannot access file %s.\n", polyfilename);
+      exit(1);
+    }
+    /* Read number of points, number of dimensions, number of point */
+    /*   attributes, and number of boundary markers.                */
+    stringptr = readline(inputline, *polyfile, polyfilename);
+    inpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      mesh_dim = 2;
+    } else {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nextras = 0;
+    } else {
+      nextras = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nodemarkers = 0;
+    } else {
+      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+    if (inpoints > 0) {
+      infile = *polyfile;
+      infilename = polyfilename;
+      readnodefile = 0;
+    } else {
+      /* If the .poly file claims there are zero points, that means that */
+      /*   the points should be read from a separate .node file.         */
+      readnodefile = 1;
+      infilename = innodefilename;
+    }
+  } else {
+    readnodefile = 1;
+    infilename = innodefilename;
+    *polyfile = (FILE *) NULL;
+  }
+
+  if (readnodefile) {
+    /* Read the points from a .node file. */
+    if (!quiet) {
+      printf("Opening %s.\n", innodefilename);
+    }
+    infile = fopen(innodefilename, "r");
+    if (infile == (FILE *) NULL) {
+      printf("  Error:  Cannot access file %s.\n", innodefilename);
+      exit(1);
+    }
+    /* Read number of points, number of dimensions, number of point */
+    /*   attributes, and number of boundary markers.                */
+    stringptr = readline(inputline, infile, innodefilename);
+    inpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      mesh_dim = 2;
+    } else {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nextras = 0;
+    } else {
+      nextras = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nodemarkers = 0;
+    } else {
+      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+  }
+
+  if (inpoints < 3) {
+    printf("Error:  Input must have at least three input points.\n");
+    exit(1);
+  }
+  if (mesh_dim != 2) {
+    printf("Error:  Triangle only works with two-dimensional meshes.\n");
+    exit(1);
+  }
+
+  initializepointpool();
+
+  /* Read the points. */
+  for (i = 0; i < inpoints; i++) {
+    pointloop = (point) poolalloc(&points);
+    stringptr = readline(inputline, infile, infilename);
+    if (i == 0) {
+      firstnode = (int) strtol (stringptr, &stringptr, 0);
+      if ((firstnode == 0) || (firstnode == 1)) {
+        firstnumber = firstnode;
+      }
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
+      exit(1);
+    }
+    x = (REAL) strtod(stringptr, &stringptr);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
+      exit(1);
+    }
+    y = (REAL) strtod(stringptr, &stringptr);
+    pointloop[0] = x;
+    pointloop[1] = y;
+    /* Read the point attributes. */
+    for (j = 2; j < 2 + nextras; j++) {
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        pointloop[j] = 0.0;
+      } else {
+        pointloop[j] = (REAL) strtod(stringptr, &stringptr);
+      }
+    }
+    if (nodemarkers) {
+      /* Read a point marker. */
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        setpointmark(pointloop, 0);
+      } else {
+        currentmarker = (int) strtol (stringptr, &stringptr, 0);
+        setpointmark(pointloop, currentmarker);
+      }
+    } else {
+      /* If no markers are specified in the file, they default to zero. */
+      setpointmark(pointloop, 0);
+    }
+    /* Determine the smallest and largest x and y coordinates. */
+    if (i == 0) {
+      xmin = xmax = x;
+      ymin = ymax = y;
+    } else {
+      xmin = (x < xmin) ? x : xmin;
+      xmax = (x > xmax) ? x : xmax;
+      ymin = (y < ymin) ? y : ymin;
+      ymax = (y > ymax) ? y : ymax;
+    }
+  }
+  if (readnodefile) {
+    fclose(infile);
+  }
+
+  /* Nonexistent x value used as a flag to mark circle events in sweepline */
+  /*   Delaunay algorithm.                                                 */
+  xminextreme = 10 * xmin - 9 * xmax;
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  transfernodes()   Read the points from memory.                           */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void transfernodes(pointlist, pointattriblist, pointmarkerlist, numberofpoints,
+                   numberofpointattribs)
+REAL *pointlist;
+REAL *pointattriblist;
+int *pointmarkerlist;
+int numberofpoints;
+int numberofpointattribs;
+{
+  point pointloop;
+  REAL x, y;
+  int i, j;
+  int coordindex;
+  int attribindex;
+
+  inpoints = numberofpoints;
+  mesh_dim = 2;
+  nextras = numberofpointattribs;
+  readnodefile = 0;
+  if (inpoints < 3) {
+    printf("Error:  Input must have at least three input points.\n");
+    exit(1);
+  }
+
+  initializepointpool();
+
+  /* Read the points. */
+  coordindex = 0;
+  attribindex = 0;
+  for (i = 0; i < inpoints; i++) {
+    pointloop = (point) poolalloc(&points);
+    /* Read the point coordinates. */
+    x = pointloop[0] = pointlist[coordindex++];
+    y = pointloop[1] = pointlist[coordindex++];
+    /* Read the point attributes. */
+    for (j = 0; j < numberofpointattribs; j++) {
+      pointloop[2 + j] = pointattriblist[attribindex++];
+    }
+    if (pointmarkerlist != (int *) NULL) {
+      /* Read a point marker. */
+      setpointmark(pointloop, pointmarkerlist[i]);
+    } else {
+      /* If no markers are specified, they default to zero. */
+      setpointmark(pointloop, 0);
+    }
+    x = pointloop[0];
+    y = pointloop[1];
+    /* Determine the smallest and largest x and y coordinates. */
+    if (i == 0) {
+      xmin = xmax = x;
+      ymin = ymax = y;
+    } else {
+      xmin = (x < xmin) ? x : xmin;
+      xmax = (x > xmax) ? x : xmax;
+      ymin = (y < ymin) ? y : ymin;
+      ymax = (y > ymax) ? y : ymax;
+    }
+  }
+
+  /* Nonexistent x value used as a flag to mark circle events in sweepline */
+  /*   Delaunay algorithm.                                                 */
+  xminextreme = 10 * xmin - 9 * xmax;
+}
+
+#endif /* TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  readholes()   Read the holes, and possibly regional attributes and area  */
+/*                constraints, from a .poly file.                            */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void readholes(polyfile, polyfilename, hlist, holes, rlist, regions)
+FILE *polyfile;
+char *polyfilename;
+REAL **hlist;
+int *holes;
+REAL **rlist;
+int *regions;
+{
+  REAL *holelist;
+  REAL *regionlist;
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  int index;
+  int i;
+
+  /* Read the holes. */
+  stringptr = readline(inputline, polyfile, polyfilename);
+  *holes = (int) strtol (stringptr, &stringptr, 0);
+  if (*holes > 0) {
+    holelist = (REAL *) malloc(2 * *holes * sizeof(REAL));
+    *hlist = holelist;
+    if (holelist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+    for (i = 0; i < 2 * *holes; i += 2) {
+      stringptr = readline(inputline, polyfile, polyfilename);
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Hole %d has no x coordinate.\n",
+               firstnumber + (i >> 1));
+        exit(1);
+      } else {
+        holelist[i] = (REAL) strtod(stringptr, &stringptr);
+      }
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Hole %d has no y coordinate.\n",
+               firstnumber + (i >> 1));
+        exit(1);
+      } else {
+        holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
+      }
+    }
+  } else {
+    *hlist = (REAL *) NULL;
+  }
+
+#ifndef CDT_ONLY
+  if ((regionattrib || vararea) && !refine) {
+    /* Read the area constraints. */
+    stringptr = readline(inputline, polyfile, polyfilename);
+    *regions = (int) strtol (stringptr, &stringptr, 0);
+    if (*regions > 0) {
+      regionlist = (REAL *) malloc(4 * *regions * sizeof(REAL));
+      *rlist = regionlist;
+      if (regionlist == (REAL *) NULL) {
+        printf("Error:  Out of memory.\n");
+        exit(1);
+      }
+      index = 0;
+      for (i = 0; i < *regions; i++) {
+        stringptr = readline(inputline, polyfile, polyfilename);
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no x coordinate.\n",
+                 firstnumber + i);
+          exit(1);
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no y coordinate.\n",
+                 firstnumber + i);
+          exit(1);
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          printf(
+            "Error:  Region %d has no region attribute or area constraint.\n",
+                 firstnumber + i);
+          exit(1);
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          regionlist[index] = regionlist[index - 1];
+        } else {
+          regionlist[index] = (REAL) strtod(stringptr, &stringptr);
+        }
+        index++;
+      }
+    }
+  } else {
+    /* Set `*regions' to zero to avoid an accidental free() later. */
+    *regions = 0;
+    *rlist = (REAL *) NULL;
+  }
+#endif /* not CDT_ONLY */
+
+  fclose(polyfile);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  finishfile()   Write the command line to the output file so the user     */
+/*                 can remember how the file was generated.  Close the file. */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void finishfile(outfile, argc, argv)
+FILE *outfile;
+int argc;
+char **argv;
+{
+  int i;
+
+  fprintf(outfile, "# Generated by");
+  for (i = 0; i < argc; i++) {
+    fprintf(outfile, " ");
+    fputs(argv[i], outfile);
+  }
+  fprintf(outfile, "\n");
+  fclose(outfile);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writenodes()   Number the points and write them to a .node file.         */
+/*                                                                           */
+/*  To save memory, the point numbers are written over the shell markers     */
+/*  after the points are written to a file.                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writenodes(pointlist, pointattriblist, pointmarkerlist)
+REAL **pointlist;
+REAL **pointattriblist;
+int **pointmarkerlist;
+
+#else /* not TRILIBRARY */
+
+void writenodes(nodefilename, argc, argv)
+char *nodefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  REAL *plist;
+  REAL *palist;
+  int *pmlist;
+  int coordindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  point pointloop;
+  int pointnumber;
+  int i;
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing points.\n");
+  }
+  /* Allocate memory for output points if necessary. */
+  if (*pointlist == (REAL *) NULL) {
+    *pointlist = (REAL *) malloc(points.items * 2 * sizeof(REAL));
+    if (*pointlist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output point attributes if necessary. */
+  if ((nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
+    *pointattriblist = (REAL *) malloc(points.items * nextras * sizeof(REAL));
+    if (*pointattriblist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output point markers if necessary. */
+  if (!nobound && (*pointmarkerlist == (int *) NULL)) {
+    *pointmarkerlist = (int *) malloc(points.items * sizeof(int));
+    if (*pointmarkerlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  plist = *pointlist;
+  palist = *pointattriblist;
+  pmlist = *pointmarkerlist;
+  coordindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", nodefilename);
+  }
+  outfile = fopen(nodefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", nodefilename);
+    exit(1);
+  }
+  /* Number of points, number of dimensions, number of point attributes, */
+  /*   and number of boundary markers (zero or one).                     */
+  fprintf(outfile, "%ld  %d  %d  %d\n", points.items, mesh_dim, nextras,
+          1 - nobound);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  pointnumber = firstnumber;
+  while (pointloop != (point) NULL) {
+#ifdef TRILIBRARY
+    /* X and y coordinates. */
+    plist[coordindex++] = pointloop[0];
+    plist[coordindex++] = pointloop[1];
+    /* Point attributes. */
+    for (i = 0; i < nextras; i++) {
+      palist[attribindex++] = pointloop[2 + i];
+    }
+    if (!nobound) {
+      /* Copy the boundary marker. */
+      pmlist[pointnumber - firstnumber] = pointmark(pointloop);
+    }
+#else /* not TRILIBRARY */
+    /* Point number, x and y coordinates. */
+    fprintf(outfile, "%4d    %.17g  %.17g", pointnumber, pointloop[0],
+            pointloop[1]);
+    for (i = 0; i < nextras; i++) {
+      /* Write an attribute. */
+      fprintf(outfile, "  %.17g", pointloop[i + 2]);
+    }
+    if (nobound) {
+      fprintf(outfile, "\n");
+    } else {
+      /* Write the boundary marker. */
+      fprintf(outfile, "    %d\n", pointmark(pointloop));
+    }
+#endif /* not TRILIBRARY */
+
+    setpointmark(pointloop, pointnumber);
+    pointloop = pointtraverse();
+    pointnumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  numbernodes()   Number the points.                                       */
+/*                                                                           */
+/*  Each point is assigned a marker equal to its number.                     */
+/*                                                                           */
+/*  Used when writenodes() is not called because no .node file is written.   */
+/*                                                                           */
+/*****************************************************************************/
+
+void numbernodes()
+{
+  point pointloop;
+  int pointnumber;
+
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  pointnumber = firstnumber;
+  while (pointloop != (point) NULL) {
+    setpointmark(pointloop, pointnumber);
+    pointloop = pointtraverse();
+    pointnumber++;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writeelements()   Write the triangles to an .ele file.                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writeelements(trianglelist, triangleattriblist)
+int **trianglelist;
+REAL **triangleattriblist;
+
+#else /* not TRILIBRARY */
+
+void writeelements(elefilename, argc, argv)
+char *elefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *tlist;
+  REAL *talist;
+  int pointindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop;
+  point p1, p2, p3;
+  point mid1, mid2, mid3;
+  int elementnumber;
+  int i;
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing triangles.\n");
+  }
+  /* Allocate memory for output triangles if necessary. */
+  if (*trianglelist == (int *) NULL) {
+    *trianglelist = (int *) malloc(triangles.items *
+                               ((order + 1) * (order + 2) / 2) * sizeof(int));
+    if (*trianglelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output triangle attributes if necessary. */
+  if ((eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
+    *triangleattriblist = (REAL *) malloc(triangles.items * eextras *
+                                          sizeof(REAL));
+    if (*triangleattriblist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  tlist = *trianglelist;
+  talist = *triangleattriblist;
+  pointindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", elefilename);
+  }
+  outfile = fopen(elefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", elefilename);
+    exit(1);
+  }
+  /* Number of triangles, points per triangle, attributes per triangle. */
+  fprintf(outfile, "%ld  %d  %d\n", triangles.items,
+          (order + 1) * (order + 2) / 2, eextras);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, p1);
+    dest(triangleloop, p2);
+    apex(triangleloop, p3);
+    if (order == 1) {
+#ifdef TRILIBRARY
+      tlist[pointindex++] = pointmark(p1);
+      tlist[pointindex++] = pointmark(p2);
+      tlist[pointindex++] = pointmark(p3);
+#else /* not TRILIBRARY */
+      /* Triangle number, indices for three points. */
+      fprintf(outfile, "%4d    %4d  %4d  %4d", elementnumber,
+              pointmark(p1), pointmark(p2), pointmark(p3));
+#endif /* not TRILIBRARY */
+    } else {
+      mid1 = (point) triangleloop.tri[highorderindex + 1];
+      mid2 = (point) triangleloop.tri[highorderindex + 2];
+      mid3 = (point) triangleloop.tri[highorderindex];
+#ifdef TRILIBRARY
+      tlist[pointindex++] = pointmark(p1);
+      tlist[pointindex++] = pointmark(p2);
+      tlist[pointindex++] = pointmark(p3);
+      tlist[pointindex++] = pointmark(mid1);
+      tlist[pointindex++] = pointmark(mid2);
+      tlist[pointindex++] = pointmark(mid3);
+#else /* not TRILIBRARY */
+      /* Triangle number, indices for six points. */
+      fprintf(outfile, "%4d    %4d  %4d  %4d  %4d  %4d  %4d", elementnumber,
+              pointmark(p1), pointmark(p2), pointmark(p3), pointmark(mid1),
+              pointmark(mid2), pointmark(mid3));
+#endif /* not TRILIBRARY */
+    }
+
+#ifdef TRILIBRARY
+    for (i = 0; i < eextras; i++) {
+      talist[attribindex++] = elemattribute(triangleloop, i);
+    }
+#else /* not TRILIBRARY */
+    for (i = 0; i < eextras; i++) {
+      fprintf(outfile, "  %.17g", elemattribute(triangleloop, i));
+    }
+    fprintf(outfile, "\n");
+#endif /* not TRILIBRARY */
+
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writepoly()   Write the segments and holes to a .poly file.              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writepoly(segmentlist, segmentmarkerlist)
+int **segmentlist;
+int **segmentmarkerlist;
+
+#else /* not TRILIBRARY */
+
+void writepoly(polyfilename, holelist, holes, regionlist, regions, argc, argv)
+char *polyfilename;
+REAL *holelist;
+int holes;
+REAL *regionlist;
+int regions;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *slist;
+  int *smlist;
+  int index;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+  int i;
+#endif /* not TRILIBRARY */
+  struct edge shelleloop;
+  point endpoint1, endpoint2;
+  int shellenumber;
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing segments.\n");
+  }
+  /* Allocate memory for output segments if necessary. */
+  if (*segmentlist == (int *) NULL) {
+    *segmentlist = (int *) malloc(shelles.items * 2 * sizeof(int));
+    if (*segmentlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output segment markers if necessary. */
+  if (!nobound && (*segmentmarkerlist == (int *) NULL)) {
+    *segmentmarkerlist = (int *) malloc(shelles.items * sizeof(int));
+    if (*segmentmarkerlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  slist = *segmentlist;
+  smlist = *segmentmarkerlist;
+  index = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", polyfilename);
+  }
+  outfile = fopen(polyfilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", polyfilename);
+    exit(1);
+  }
+  /* The zero indicates that the points are in a separate .node file. */
+  /*   Followed by number of dimensions, number of point attributes,  */
+  /*   and number of boundary markers (zero or one).                  */
+  fprintf(outfile, "%d  %d  %d  %d\n", 0, mesh_dim, nextras, 1 - nobound);
+  /* Number of segments, number of boundary markers (zero or one). */
+  fprintf(outfile, "%ld  %d\n", shelles.items, 1 - nobound);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&shelles);
+  shelleloop.sh = shelletraverse();
+  shelleloop.shorient = 0;
+  shellenumber = firstnumber;
+  while (shelleloop.sh != (shelle *) NULL) {
+    sorg(shelleloop, endpoint1);
+    sdest(shelleloop, endpoint2);
+#ifdef TRILIBRARY
+    /* Copy indices of the segment's two endpoints. */
+    slist[index++] = pointmark(endpoint1);
+    slist[index++] = pointmark(endpoint2);
+    if (!nobound) {
+      /* Copy the boundary marker. */
+      smlist[shellenumber - firstnumber] = mark(shelleloop);
+    }
+#else /* not TRILIBRARY */
+    /* Segment number, indices of its two endpoints, and possibly a marker. */
+    if (nobound) {
+      fprintf(outfile, "%4d    %4d  %4d\n", shellenumber,
+              pointmark(endpoint1), pointmark(endpoint2));
+    } else {
+      fprintf(outfile, "%4d    %4d  %4d    %4d\n", shellenumber,
+              pointmark(endpoint1), pointmark(endpoint2), mark(shelleloop));
+    }
+#endif /* not TRILIBRARY */
+
+    shelleloop.sh = shelletraverse();
+    shellenumber++;
+  }
+
+#ifndef TRILIBRARY
+#ifndef CDT_ONLY
+  fprintf(outfile, "%d\n", holes);
+  if (holes > 0) {
+    for (i = 0; i < holes; i++) {
+      /* Hole number, x and y coordinates. */
+      fprintf(outfile, "%4d   %.17g  %.17g\n", firstnumber + i,
+              holelist[2 * i], holelist[2 * i + 1]);
+    }
+  }
+  if (regions > 0) {
+    fprintf(outfile, "%d\n", regions);
+    for (i = 0; i < regions; i++) {
+      /* Region number, x and y coordinates, attribute, maximum area. */
+      fprintf(outfile, "%4d   %.17g  %.17g  %.17g  %.17g\n", firstnumber + i,
+              regionlist[4 * i], regionlist[4 * i + 1],
+              regionlist[4 * i + 2], regionlist[4 * i + 3]);
+    }
+  }
+#endif /* not CDT_ONLY */
+
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writeedges()   Write the edges to a .edge file.                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writeedges(edgelist, edgemarkerlist)
+int **edgelist;
+int **edgemarkerlist;
+
+#else /* not TRILIBRARY */
+
+void writeedges(edgefilename, argc, argv)
+char *edgefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *elist;
+  int *emlist;
+  int index;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop, trisym;
+  struct edge checkmark;
+  point p1, p2;
+  int edgenumber;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing edges.\n");
+  }
+  /* Allocate memory for edges if necessary. */
+  if (*edgelist == (int *) NULL) {
+    *edgelist = (int *) malloc(edges * 2 * sizeof(int));
+    if (*edgelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for edge markers if necessary. */
+  if (!nobound && (*edgemarkerlist == (int *) NULL)) {
+    *edgemarkerlist = (int *) malloc(edges * sizeof(int));
+    if (*edgemarkerlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  elist = *edgelist;
+  emlist = *edgemarkerlist;
+  index = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", edgefilename);
+  }
+  outfile = fopen(edgefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", edgefilename);
+    exit(1);
+  }
+  /* Number of edges, number of boundary markers (zero or one). */
+  fprintf(outfile, "%ld  %d\n", edges, 1 - nobound);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  edgenumber = firstnumber;
+  /* To loop over the set of edges, loop over all triangles, and look at   */
+  /*   the three edges of each triangle.  If there isn't another triangle  */
+  /*   adjacent to the edge, operate on the edge.  If there is another     */
+  /*   adjacent triangle, operate on the edge only if the current triangle */
+  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
+  /*   considered only once.                                               */
+  while (triangleloop.tri != (triangle *) NULL) {
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      sym(triangleloop, trisym);
+      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
+        org(triangleloop, p1);
+        dest(triangleloop, p2);
+#ifdef TRILIBRARY
+        elist[index++] = pointmark(p1);
+        elist[index++] = pointmark(p2);
+#endif /* TRILIBRARY */
+        if (nobound) {
+#ifndef TRILIBRARY
+          /* Edge number, indices of two endpoints. */
+          fprintf(outfile, "%4d   %d  %d\n", edgenumber,
+                  pointmark(p1), pointmark(p2));
+#endif /* not TRILIBRARY */
+        } else {
+          /* Edge number, indices of two endpoints, and a boundary marker. */
+          /*   If there's no shell edge, the boundary marker is zero.      */
+          if (useshelles) {
+            tspivot(triangleloop, checkmark);
+            if (checkmark.sh == dummysh) {
+#ifdef TRILIBRARY
+              emlist[edgenumber - firstnumber] = 0;
+#else /* not TRILIBRARY */
+              fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
+                      pointmark(p1), pointmark(p2), 0);
+#endif /* not TRILIBRARY */
+            } else {
+#ifdef TRILIBRARY
+              emlist[edgenumber - firstnumber] = mark(checkmark);
+#else /* not TRILIBRARY */
+              fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
+                      pointmark(p1), pointmark(p2), mark(checkmark));
+#endif /* not TRILIBRARY */
+            }
+          } else {
+#ifdef TRILIBRARY
+            emlist[edgenumber - firstnumber] = trisym.tri == dummytri;
+#else /* not TRILIBRARY */
+            fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
+                    pointmark(p1), pointmark(p2), trisym.tri == dummytri);
+#endif /* not TRILIBRARY */
+          }
+        }
+        edgenumber++;
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writevoronoi()   Write the Voronoi diagram to a .v.node and .v.edge      */
+/*                   file.                                                   */
+/*                                                                           */
+/*  The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
+/*  Hence, the Voronoi vertices are listed by traversing the Delaunay        */
+/*  triangles, and the Voronoi edges are listed by traversing the Delaunay   */
+/*  edges.                                                                   */
+/*                                                                           */
+/*  WARNING:  In order to assign numbers to the Voronoi vertices, this       */
+/*  procedure messes up the shell edges or the extra nodes of every          */
+/*  element.  Hence, you should call this procedure last.                    */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writevoronoi(vpointlist, vpointattriblist, vpointmarkerlist, vedgelist,
+                  vedgemarkerlist, vnormlist)
+REAL **vpointlist;
+REAL **vpointattriblist;
+int **vpointmarkerlist;
+int **vedgelist;
+int **vedgemarkerlist;
+REAL **vnormlist;
+
+#else /* not TRILIBRARY */
+
+void writevoronoi(vnodefilename, vedgefilename, argc, argv)
+char *vnodefilename;
+char *vedgefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  REAL *plist;
+  REAL *palist;
+  int *elist;
+  REAL *normlist;
+  int coordindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop, trisym;
+  point torg, tdest, tapex;
+  REAL circumcenter[2];
+  REAL xi, eta;
+  int vnodenumber, vedgenumber;
+  int p1, p2;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing Voronoi vertices.\n");
+  }
+  /* Allocate memory for Voronoi vertices if necessary. */
+  if (*vpointlist == (REAL *) NULL) {
+    *vpointlist = (REAL *) malloc(triangles.items * 2 * sizeof(REAL));
+    if (*vpointlist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for Voronoi vertex attributes if necessary. */
+  if (*vpointattriblist == (REAL *) NULL) {
+    *vpointattriblist = (REAL *) malloc(triangles.items * nextras *
+                                        sizeof(REAL));
+    if (*vpointattriblist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  *vpointmarkerlist = (int *) NULL;
+  plist = *vpointlist;
+  palist = *vpointattriblist;
+  coordindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", vnodefilename);
+  }
+  outfile = fopen(vnodefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", vnodefilename);
+    exit(1);
+  }
+  /* Number of triangles, two dimensions, number of point attributes, */
+  /*   zero markers.                                                  */
+  fprintf(outfile, "%ld  %d  %d  %d\n", triangles.items, 2, nextras, 0);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  vnodenumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, torg);
+    dest(triangleloop, tdest);
+    apex(triangleloop, tapex);
+    findcircumcenter(torg, tdest, tapex, circumcenter, &xi, &eta);
+#ifdef TRILIBRARY
+    /* X and y coordinates. */
+    plist[coordindex++] = circumcenter[0];
+    plist[coordindex++] = circumcenter[1];
+    for (i = 2; i < 2 + nextras; i++) {
+      /* Interpolate the point attributes at the circumcenter. */
+      palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
+                                     + eta * (tapex[i] - torg[i]);
+    }
+#else /* not TRILIBRARY */
+    /* Voronoi vertex number, x and y coordinates. */
+    fprintf(outfile, "%4d    %.17g  %.17g", vnodenumber, circumcenter[0],
+            circumcenter[1]);
+    for (i = 2; i < 2 + nextras; i++) {
+      /* Interpolate the point attributes at the circumcenter. */
+      fprintf(outfile, "  %.17g", torg[i] + xi * (tdest[i] - torg[i])
+                                         + eta * (tapex[i] - torg[i]));
+    }
+    fprintf(outfile, "\n");
+#endif /* not TRILIBRARY */
+
+    * (int *) (triangleloop.tri + 6) = vnodenumber;
+    triangleloop.tri = triangletraverse();
+    vnodenumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing Voronoi edges.\n");
+  }
+  /* Allocate memory for output Voronoi edges if necessary. */
+  if (*vedgelist == (int *) NULL) {
+    *vedgelist = (int *) malloc(edges * 2 * sizeof(int));
+    if (*vedgelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  *vedgemarkerlist = (int *) NULL;
+  /* Allocate memory for output Voronoi norms if necessary. */
+  if (*vnormlist == (REAL *) NULL) {
+    *vnormlist = (REAL *) malloc(edges * 2 * sizeof(REAL));
+    if (*vnormlist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  elist = *vedgelist;
+  normlist = *vnormlist;
+  coordindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", vedgefilename);
+  }
+  outfile = fopen(vedgefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", vedgefilename);
+    exit(1);
+  }
+  /* Number of edges, zero boundary markers. */
+  fprintf(outfile, "%ld  %d\n", edges, 0);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  vedgenumber = firstnumber;
+  /* To loop over the set of edges, loop over all triangles, and look at   */
+  /*   the three edges of each triangle.  If there isn't another triangle  */
+  /*   adjacent to the edge, operate on the edge.  If there is another     */
+  /*   adjacent triangle, operate on the edge only if the current triangle */
+  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
+  /*   considered only once.                                               */
+  while (triangleloop.tri != (triangle *) NULL) {
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      sym(triangleloop, trisym);
+      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
+        /* Find the number of this triangle (and Voronoi vertex). */
+        p1 = * (int *) (triangleloop.tri + 6);
+        if (trisym.tri == dummytri) {
+          org(triangleloop, torg);
+          dest(triangleloop, tdest);
+#ifdef TRILIBRARY
+          /* Copy an infinite ray.  Index of one endpoint, and -1. */
+          elist[coordindex] = p1;
+          normlist[coordindex++] = tdest[1] - torg[1];
+          elist[coordindex] = -1;
+          normlist[coordindex++] = torg[0] - tdest[0];
+#else /* not TRILIBRARY */
+          /* Write an infinite ray.  Edge number, index of one endpoint, -1, */
+          /*   and x and y coordinates of a vector representing the          */
+          /*   direction of the ray.                                         */
+          fprintf(outfile, "%4d   %d  %d   %.17g  %.17g\n", vedgenumber,
+                  p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
+#endif /* not TRILIBRARY */
+        } else {
+          /* Find the number of the adjacent triangle (and Voronoi vertex). */
+          p2 = * (int *) (trisym.tri + 6);
+          /* Finite edge.  Write indices of two endpoints. */
+#ifdef TRILIBRARY
+          elist[coordindex] = p1;
+          normlist[coordindex++] = 0.0;
+          elist[coordindex] = p2;
+          normlist[coordindex++] = 0.0;
+#else /* not TRILIBRARY */
+          fprintf(outfile, "%4d   %d  %d\n", vedgenumber, p1, p2);
+#endif /* not TRILIBRARY */
+        }
+        vedgenumber++;
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+#ifdef TRILIBRARY
+
+void writeneighbors(neighborlist)
+int **neighborlist;
+
+#else /* not TRILIBRARY */
+
+void writeneighbors(neighborfilename, argc, argv)
+char *neighborfilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *nlist;
+  int index;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop, trisym;
+  int elementnumber;
+  int neighbor1, neighbor2, neighbor3;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing neighbors.\n");
+  }
+  /* Allocate memory for neighbors if necessary. */
+  if (*neighborlist == (int *) NULL) {
+    *neighborlist = (int *) malloc(triangles.items * 3 * sizeof(int));
+    if (*neighborlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  nlist = *neighborlist;
+  index = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", neighborfilename);
+  }
+  outfile = fopen(neighborfilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", neighborfilename);
+    exit(1);
+  }
+  /* Number of triangles, three edges per triangle. */
+  fprintf(outfile, "%ld  %d\n", triangles.items, 3);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    * (int *) (triangleloop.tri + 6) = elementnumber;
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+  * (int *) (dummytri + 6) = -1;
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    triangleloop.orient = 1;
+    sym(triangleloop, trisym);
+    neighbor1 = * (int *) (trisym.tri + 6);
+    triangleloop.orient = 2;
+    sym(triangleloop, trisym);
+    neighbor2 = * (int *) (trisym.tri + 6);
+    triangleloop.orient = 0;
+    sym(triangleloop, trisym);
+    neighbor3 = * (int *) (trisym.tri + 6);
+#ifdef TRILIBRARY
+    nlist[index++] = neighbor1;
+    nlist[index++] = neighbor2;
+    nlist[index++] = neighbor3;
+#else /* not TRILIBRARY */
+    /* Triangle number, neighboring triangle numbers. */
+    fprintf(outfile, "%4d    %d  %d  %d\n", elementnumber,
+            neighbor1, neighbor2, neighbor3);
+#endif /* not TRILIBRARY */
+
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writeoff()   Write the triangulation to an .off file.                    */
+/*                                                                           */
+/*  OFF stands for the Object File Format, a format used by the Geometry     */
+/*  Center's Geomview package.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void writeoff(offfilename, argc, argv)
+char *offfilename;
+int argc;
+char **argv;
+{
+  FILE *outfile;
+  struct triedge triangleloop;
+  point pointloop;
+  point p1, p2, p3;
+
+  if (!quiet) {
+    printf("Writing %s.\n", offfilename);
+  }
+  outfile = fopen(offfilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", offfilename);
+    exit(1);
+  }
+  /* Number of points, triangles, and edges. */
+  fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points.items, triangles.items,
+          edges);
+
+  /* Write the points. */
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  while (pointloop != (point) NULL) {
+    /* The "0.0" is here because the OFF format uses 3D coordinates. */
+    fprintf(outfile, " %.17g  %.17g  %.17g\n", pointloop[0],
+            pointloop[1], 0.0);
+    pointloop = pointtraverse();
+  }
+
+  /* Write the triangles. */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, p1);
+    dest(triangleloop, p2);
+    apex(triangleloop, p3);
+    /* The "3" means a three-vertex polygon. */
+    fprintf(outfile, " 3   %4d  %4d  %4d\n", pointmark(p1) - 1,
+            pointmark(p2) - 1, pointmark(p3) - 1);
+    triangleloop.tri = triangletraverse();
+  }
+  finishfile(outfile, argc, argv);
+}
+
+#endif /* not TRILIBRARY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* File I/O routines end here                                *********/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  quality_statistics()   Print statistics about the quality of the mesh.   */
+/*                                                                           */
+/*****************************************************************************/
+
+void quality_statistics()
+{
+  struct triedge triangleloop;
+  point p[3];
+  REAL cossquaretable[8];
+  REAL ratiotable[16];
+  REAL dx[3], dy[3];
+  REAL edgelength[3];
+  REAL dotproduct;
+  REAL cossquare;
+  REAL triarea;
+  REAL shortest, longest;
+  REAL trilongest2;
+  REAL smallestarea, biggestarea;
+  REAL triminaltitude2;
+  REAL minaltitude;
+  REAL triaspect2;
+  REAL worstaspect;
+  REAL smallestangle, biggestangle;
+  REAL radconst, degconst;
+  int angletable[18];
+  int aspecttable[16];
+  int aspectindex;
+  int tendegree;
+  int acutebiggest;
+  int i, ii, j, k;
+
+  printf("Mesh quality statistics:\n\n");
+  radconst = PI / 18.0;
+  degconst = 180.0 / PI;
+  for (i = 0; i < 8; i++) {
+    cossquaretable[i] = cos(radconst * (REAL) (i + 1));
+    cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
+  }
+  for (i = 0; i < 18; i++) {
+    angletable[i] = 0;
+  }
+
+  ratiotable[0]  =      1.5;      ratiotable[1]  =     2.0;
+  ratiotable[2]  =      2.5;      ratiotable[3]  =     3.0;
+  ratiotable[4]  =      4.0;      ratiotable[5]  =     6.0;
+  ratiotable[6]  =     10.0;      ratiotable[7]  =    15.0;
+  ratiotable[8]  =     25.0;      ratiotable[9]  =    50.0;
+  ratiotable[10] =    100.0;      ratiotable[11] =   300.0;
+  ratiotable[12] =   1000.0;      ratiotable[13] = 10000.0;
+  ratiotable[14] = 100000.0;      ratiotable[15] =     0.0;
+  for (i = 0; i < 16; i++) {
+    aspecttable[i] = 0;
+  }
+
+  worstaspect = 0.0;
+  minaltitude = xmax - xmin + ymax - ymin;
+  minaltitude = minaltitude * minaltitude;
+  shortest = minaltitude;
+  longest = 0.0;
+  smallestarea = minaltitude;
+  biggestarea = 0.0;
+  worstaspect = 0.0;
+  smallestangle = 0.0;
+  biggestangle = 2.0;
+  acutebiggest = 1;
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, p[0]);
+    dest(triangleloop, p[1]);
+    apex(triangleloop, p[2]);
+    trilongest2 = 0.0;
+
+    for (i = 0; i < 3; i++) {
+      j = plus1mod3[i];
+      k = minus1mod3[i];
+      dx[i] = p[j][0] - p[k][0];
+      dy[i] = p[j][1] - p[k][1];
+      edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
+      if (edgelength[i] > trilongest2) {
+        trilongest2 = edgelength[i];
+      }
+      if (edgelength[i] > longest) {
+        longest = edgelength[i];
+      }
+      if (edgelength[i] < shortest) {
+        shortest = edgelength[i];
+      }
+    }
+
+    triarea = counterclockwise(p[0], p[1], p[2]);
+    if (triarea < smallestarea) {
+      smallestarea = triarea;
+    }
+    if (triarea > biggestarea) {
+      biggestarea = triarea;
+    }
+    triminaltitude2 = triarea * triarea / trilongest2;
+    if (triminaltitude2 < minaltitude) {
+      minaltitude = triminaltitude2;
+    }
+    triaspect2 = trilongest2 / triminaltitude2;
+    if (triaspect2 > worstaspect) {
+      worstaspect = triaspect2;
+    }
+    aspectindex = 0;
+    while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
+           && (aspectindex < 15)) {
+      aspectindex++;
+    }
+    aspecttable[aspectindex]++;
+
+    for (i = 0; i < 3; i++) {
+      j = plus1mod3[i];
+      k = minus1mod3[i];
+      dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
+      cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
+      tendegree = 8;
+      for (ii = 7; ii >= 0; ii--) {
+        if (cossquare > cossquaretable[ii]) {
+          tendegree = ii;
+        }
+      }
+      if (dotproduct <= 0.0) {
+        angletable[tendegree]++;
+        if (cossquare > smallestangle) {
+          smallestangle = cossquare;
+        }
+        if (acutebiggest && (cossquare < biggestangle)) {
+          biggestangle = cossquare;
+        }
+      } else {
+        angletable[17 - tendegree]++;
+        if (acutebiggest || (cossquare > biggestangle)) {
+          biggestangle = cossquare;
+          acutebiggest = 0;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+
+  shortest = sqrt(shortest);
+  longest = sqrt(longest);
+  minaltitude = sqrt(minaltitude);
+  worstaspect = sqrt(worstaspect);
+  smallestarea *= 2.0;
+  biggestarea *= 2.0;
+  if (smallestangle >= 1.0) {
+    smallestangle = 0.0;
+  } else {
+    smallestangle = degconst * acos(sqrt(smallestangle));
+  }
+  if (biggestangle >= 1.0) {
+    biggestangle = 180.0;
+  } else {
+    if (acutebiggest) {
+      biggestangle = degconst * acos(sqrt(biggestangle));
+    } else {
+      biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
+    }
+  }
+
+  printf("  Smallest area: %16.5g   |  Largest area: %16.5g\n",
+         smallestarea, biggestarea);
+  printf("  Shortest edge: %16.5g   |  Longest edge: %16.5g\n",
+         shortest, longest);
+  printf("  Shortest altitude: %12.5g   |  Largest aspect ratio: %8.5g\n\n",
+         minaltitude, worstaspect);
+  printf("  Aspect ratio histogram:\n");
+  printf("  1.1547 - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
+         ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
+         aspecttable[8]);
+  for (i = 1; i < 7; i++) {
+    printf("  %6.6g - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
+           ratiotable[i - 1], ratiotable[i], aspecttable[i],
+           ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
+  }
+  printf("  %6.6g - %-6.6g    :  %8d    | %6.6g -            :  %8d\n",
+         ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
+         aspecttable[15]);
+  printf(
+"  (Triangle aspect ratio is longest edge divided by shortest altitude)\n\n");
+  printf("  Smallest angle: %15.5g   |  Largest angle: %15.5g\n\n",
+         smallestangle, biggestangle);
+  printf("  Angle histogram:\n");
+  for (i = 0; i < 9; i++) {
+    printf("    %3d - %3d degrees:  %8d    |    %3d - %3d degrees:  %8d\n",
+           i * 10, i * 10 + 10, angletable[i],
+           i * 10 + 90, i * 10 + 100, angletable[i + 9]);
+  }
+  printf("\n");
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  statistics()   Print all sorts of cool facts.                            */
+/*                                                                           */
+/*****************************************************************************/
+
+void statistics()
+{
+  printf("\nStatistics:\n\n");
+  printf("  Input points: %d\n", inpoints);
+  if (refine) {
+    printf("  Input triangles: %d\n", inelements);
+  }
+  if (poly) {
+    printf("  Input segments: %d\n", insegments);
+    if (!refine) {
+      printf("  Input holes: %d\n", holes);
+    }
+  }
+
+  printf("\n  Mesh points: %ld\n", points.items);
+  printf("  Mesh triangles: %ld\n", triangles.items);
+  printf("  Mesh edges: %ld\n", edges);
+  if (poly || refine) {
+    printf("  Mesh boundary edges: %ld\n", hullsize);
+    printf("  Mesh segments: %ld\n\n", shelles.items);
+  } else {
+    printf("  Mesh convex hull edges: %ld\n\n", hullsize);
+  }
+  if (verbose) {
+    quality_statistics();
+    printf("Memory allocation statistics:\n\n");
+    printf("  Maximum number of points: %ld\n", points.maxitems);
+    printf("  Maximum number of triangles: %ld\n", triangles.maxitems);
+    if (shelles.maxitems > 0) {
+      printf("  Maximum number of segments: %ld\n", shelles.maxitems);
+    }
+    if (viri.maxitems > 0) {
+      printf("  Maximum number of viri: %ld\n", viri.maxitems);
+    }
+    if (badsegments.maxitems > 0) {
+      printf("  Maximum number of encroached segments: %ld\n",
+             badsegments.maxitems);
+    }
+    if (badtriangles.maxitems > 0) {
+      printf("  Maximum number of bad triangles: %ld\n",
+             badtriangles.maxitems);
+    }
+    if (splaynodes.maxitems > 0) {
+      printf("  Maximum number of splay tree nodes: %ld\n",
+             splaynodes.maxitems);
+    }
+    printf("  Approximate heap memory use (bytes): %ld\n\n",
+           points.maxitems * points.itembytes
+           + triangles.maxitems * triangles.itembytes
+           + shelles.maxitems * shelles.itembytes
+           + viri.maxitems * viri.itembytes
+           + badsegments.maxitems * badsegments.itembytes
+           + badtriangles.maxitems * badtriangles.itembytes
+           + splaynodes.maxitems * splaynodes.itembytes);
+
+    printf("Algorithmic statistics:\n\n");
+    printf("  Number of incircle tests: %ld\n", incirclecount);
+    printf("  Number of orientation tests: %ld\n", counterclockcount);
+    if (hyperbolacount > 0) {
+      printf("  Number of right-of-hyperbola tests: %ld\n",
+             hyperbolacount);
+    }
+    if (circumcentercount > 0) {
+      printf("  Number of circumcenter computations: %ld\n",
+             circumcentercount);
+    }
+    if (circletopcount > 0) {
+      printf("  Number of circle top computations: %ld\n",
+             circletopcount);
+    }
+    printf("\n");
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  main() or triangulate()   Gosh, do everything.                           */
+/*                                                                           */
+/*  The sequence is roughly as follows.  Many of these steps can be skipped, */
+/*  depending on the command line switches.                                  */
+/*                                                                           */
+/*  - Initialize constants and parse the command line.                       */
+/*  - Read the points from a file and either                                 */
+/*    - triangulate them (no -r), or                                         */
+/*    - read an old mesh from files and reconstruct it (-r).                 */
+/*  - Insert the PSLG segments (-p), and possibly segments on the convex     */
+/*      hull (-c).                                                           */
+/*  - Read the holes (-p), regional attributes (-pA), and regional area      */
+/*      constraints (-pa).  Carve the holes and concavities, and spread the  */
+/*      regional attributes and area constraints.                            */
+/*  - Enforce the constraints on minimum angle (-q) and maximum area (-a).   */
+/*      Also enforce the conforming Delaunay property (-q and -a).           */
+/*  - Compute the number of edges in the resulting mesh.                     */
+/*  - Promote the mesh's linear triangles to higher order elements (-o).     */
+/*  - Write the output files and print the statistics.                       */
+/*  - Check the consistency and Delaunay property of the mesh (-C).          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void triangulate(triswitches, in, out, vorout)
+char *triswitches;
+struct triangulateio *in;
+struct triangulateio *out;
+struct triangulateio *vorout;
+
+#else /* not TRILIBRARY */
+
+int main(argc, argv)
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+  REAL *holearray;                                        /* Array of holes. */
+  REAL *regionarray;   /* Array of regional attributes and area constraints. */
+#ifndef TRILIBRARY
+  FILE *polyfile;
+#endif /* not TRILIBRARY */
+#ifndef NO_TIMER
+  /* Variables for timing the performance of Triangle.  The types are */
+  /*   defined in sys/time.h.                                         */
+  struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
+  struct timezone tz;
+#endif /* NO_TIMER */
+
+#ifndef NO_TIMER
+  gettimeofday(&tv0, &tz);
+#endif /* NO_TIMER */
+
+  triangleinit();
+#ifdef TRILIBRARY
+  parsecommandline(1, &triswitches);
+#else /* not TRILIBRARY */
+  parsecommandline(argc, argv);
+#endif /* not TRILIBRARY */
+
+#ifdef TRILIBRARY
+  transfernodes(in->pointlist, in->pointattributelist, in->pointmarkerlist,
+                in->numberofpoints, in->numberofpointattributes);
+#else /* not TRILIBRARY */
+  readnodes(innodefilename, inpolyfilename, &polyfile);
+#endif /* not TRILIBRARY */
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv1, &tz);
+  }
+#endif /* NO_TIMER */
+
+#ifdef CDT_ONLY
+  hullsize = delaunay();                          /* Triangulate the points. */
+#else /* not CDT_ONLY */
+  if (refine) {
+    /* Read and reconstruct a mesh. */
+#ifdef TRILIBRARY
+    hullsize = reconstruct(in->trianglelist, in->triangleattributelist,
+                           in->trianglearealist, in->numberoftriangles,
+                           in->numberofcorners, in->numberoftriangleattributes,
+                           in->segmentlist, in->segmentmarkerlist,
+                           in->numberofsegments);
+#else /* not TRILIBRARY */
+    hullsize = reconstruct(inelefilename, areafilename, inpolyfilename,
+                           polyfile);
+#endif /* not TRILIBRARY */
+  } else {
+    hullsize = delaunay();                        /* Triangulate the points. */
+  }
+#endif /* not CDT_ONLY */
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv2, &tz);
+    if (refine) {
+      printf("Mesh reconstruction");
+    } else {
+      printf("Delaunay");
+    }
+    printf(" milliseconds:  %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec)
+           + (tv2.tv_usec - tv1.tv_usec) / 1000l);
+  }
+#endif /* NO_TIMER */
+
+  /* Ensure that no point can be mistaken for a triangular bounding */
+  /*   box point in insertsite().                                   */
+  infpoint1 = (point) NULL;
+  infpoint2 = (point) NULL;
+  infpoint3 = (point) NULL;
+
+  if (useshelles) {
+    checksegments = 1;                  /* Segments will be introduced next. */
+    if (!refine) {
+      /* Insert PSLG segments and/or convex hull segments. */
+#ifdef TRILIBRARY
+      insegments = formskeleton(in->segmentlist, in->segmentmarkerlist,
+                                in->numberofsegments);
+#else /* not TRILIBRARY */
+      insegments = formskeleton(polyfile, inpolyfilename);
+#endif /* not TRILIBRARY */
+    }
+  }
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv3, &tz);
+    if (useshelles && !refine) {
+      printf("Segment milliseconds:  %ld\n",
+             1000l * (tv3.tv_sec - tv2.tv_sec)
+             + (tv3.tv_usec - tv2.tv_usec) / 1000l);
+    }
+  }
+#endif /* NO_TIMER */
+
+  if (poly) {
+#ifdef TRILIBRARY
+    holearray = in->holelist;
+    holes = in->numberofholes;
+    regionarray = in->regionlist;
+    regions = in->numberofregions;
+#else /* not TRILIBRARY */
+    readholes(polyfile, inpolyfilename, &holearray, &holes,
+              &regionarray, &regions);
+#endif /* not TRILIBRARY */
+    if (!refine) {
+      /* Carve out holes and concavities. */
+      carveholes(holearray, holes, regionarray, regions);
+    }
+  } else {
+    /* Without a PSLG, there can be no holes or regional attributes   */
+    /*   or area constraints.  The following are set to zero to avoid */
+    /*   an accidental free() later.                                  */
+    holes = 0;
+    regions = 0;
+  }
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv4, &tz);
+    if (poly && !refine) {
+      printf("Hole milliseconds:  %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec)
+             + (tv4.tv_usec - tv3.tv_usec) / 1000l);
+    }
+  }
+#endif /* NO_TIMER */
+
+#ifndef CDT_ONLY
+  if (quality) {
+    enforcequality();                 /* Enforce angle and area constraints. */
+  }
+#endif /* not CDT_ONLY */
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv5, &tz);
+#ifndef CDT_ONLY
+    if (quality) {
+      printf("Quality milliseconds:  %ld\n",
+             1000l * (tv5.tv_sec - tv4.tv_sec)
+             + (tv5.tv_usec - tv4.tv_usec) / 1000l);
+    }
+#endif /* not CDT_ONLY */
+  }
+#endif /* NO_TIMER */
+
+  /* Compute the number of edges. */
+  edges = (3l * triangles.items + hullsize) / 2l;
+
+  if (order > 1) {
+    highorder();             /* Promote elements to higher polynomial order. */
+  }
+  if (!quiet) {
+    printf("\n");
+  }
+
+#ifdef TRILIBRARY
+  out->numberofpoints = points.items;
+  out->numberofpointattributes = nextras;
+  out->numberoftriangles = triangles.items;
+  out->numberofcorners = (order + 1) * (order + 2) / 2;
+  out->numberoftriangleattributes = eextras;
+  out->numberofedges = edges;
+  if (useshelles) {
+    out->numberofsegments = shelles.items;
+  } else {
+    out->numberofsegments = hullsize;
+  }
+  if (vorout != (struct triangulateio *) NULL) {
+    vorout->numberofpoints = triangles.items;
+    vorout->numberofpointattributes = nextras;
+    vorout->numberofedges = edges;
+  }
+#endif /* TRILIBRARY */
+  /* If not using iteration numbers, don't write a .node file if one was */
+  /*   read, because the original one would be overwritten!              */
+  if (nonodewritten || (noiterationnum && readnodefile)) {
+    if (!quiet) {
+#ifdef TRILIBRARY
+      printf("NOT writing points.\n");
+#else /* not TRILIBRARY */
+      printf("NOT writing a .node file.\n");
+#endif /* not TRILIBRARY */
+    }
+    numbernodes();                 /* We must remember to number the points. */
+  } else {
+#ifdef TRILIBRARY
+    writenodes(&out->pointlist, &out->pointattributelist,
+               &out->pointmarkerlist);
+#else /* not TRILIBRARY */
+    writenodes(outnodefilename, argc, argv);      /* Numbers the points too. */
+#endif /* TRILIBRARY */
+  }
+  if (noelewritten) {
+    if (!quiet) {
+#ifdef TRILIBRARY
+      printf("NOT writing triangles.\n");
+#else /* not TRILIBRARY */
+      printf("NOT writing an .ele file.\n");
+#endif /* not TRILIBRARY */
+    }
+  } else {
+#ifdef TRILIBRARY
+    writeelements(&out->trianglelist, &out->triangleattributelist);
+#else /* not TRILIBRARY */
+    writeelements(outelefilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+  /* The -c switch (convex switch) causes a PSLG to be written */
+  /*   even if none was read.                                  */
+  if (poly || convex) {
+    /* If not using iteration numbers, don't overwrite the .poly file. */
+    if (nopolywritten || noiterationnum) {
+      if (!quiet) {
+#ifdef TRILIBRARY
+        printf("NOT writing segments.\n");
+#else /* not TRILIBRARY */
+        printf("NOT writing a .poly file.\n");
+#endif /* not TRILIBRARY */
+      }
+    } else {
+#ifdef TRILIBRARY
+      writepoly(&out->segmentlist, &out->segmentmarkerlist);
+      out->numberofholes = holes;
+      out->numberofregions = regions;
+      if (poly) {
+        out->holelist = in->holelist;
+        out->regionlist = in->regionlist;
+      } else {
+        out->holelist = (REAL *) NULL;
+        out->regionlist = (REAL *) NULL;
+      }
+#else /* not TRILIBRARY */
+      writepoly(outpolyfilename, holearray, holes, regionarray, regions,
+                argc, argv);
+#endif /* not TRILIBRARY */
+    }
+  }
+#ifndef TRILIBRARY
+#ifndef CDT_ONLY
+  if (regions > 0) {
+    free(regionarray);
+  }
+#endif /* not CDT_ONLY */
+  if (holes > 0) {
+    free(holearray);
+  }
+  if (geomview) {
+    writeoff(offfilename, argc, argv);
+  }
+#endif /* not TRILIBRARY */
+  if (edgesout) {
+#ifdef TRILIBRARY
+    writeedges(&out->edgelist, &out->edgemarkerlist);
+#else /* not TRILIBRARY */
+    writeedges(edgefilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+  if (voronoi) {
+#ifdef TRILIBRARY
+    writevoronoi(&vorout->pointlist, &vorout->pointattributelist,
+                 &vorout->pointmarkerlist, &vorout->edgelist,
+                 &vorout->edgemarkerlist, &vorout->normlist);
+#else /* not TRILIBRARY */
+    writevoronoi(vnodefilename, vedgefilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+  if (neighbors) {
+#ifdef TRILIBRARY
+    writeneighbors(&out->neighborlist);
+#else /* not TRILIBRARY */
+    writeneighbors(neighborfilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+
+  if (!quiet) {
+#ifndef NO_TIMER
+    gettimeofday(&tv6, &tz);
+    printf("\nOutput milliseconds:  %ld\n",
+           1000l * (tv6.tv_sec - tv5.tv_sec)
+           + (tv6.tv_usec - tv5.tv_usec) / 1000l);
+    printf("Total running milliseconds:  %ld\n",
+           1000l * (tv6.tv_sec - tv0.tv_sec)
+           + (tv6.tv_usec - tv0.tv_usec) / 1000l);
+#endif /* NO_TIMER */
+
+    statistics();
+  }
+
+#ifndef REDUCED
+  if (docheck) {
+    checkmesh();
+    checkdelaunay();
+  }
+#endif /* not REDUCED */
+
+  triangledeinit();
+#ifndef TRILIBRARY
+  return 0;
+#endif /* not TRILIBRARY */
+}
diff --git a/Triangle/triangle.h b/Triangle/triangle.h
new file mode 100644
index 000000000..8fb543044
--- /dev/null
+++ b/Triangle/triangle.h
@@ -0,0 +1,284 @@
+/*****************************************************************************/
+/*                                                                           */
+/*  (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 */
diff --git a/Triangle/tricall.c b/Triangle/tricall.c
new file mode 100644
index 000000000..6beccdc81
--- /dev/null
+++ b/Triangle/tricall.c
@@ -0,0 +1,279 @@
+/*****************************************************************************/
+/*                                                                           */
+/*  (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;
+}

From af4e04b9df83d3a653db32c151a81306b454f30c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 29 Oct 1997 23:05:14 +0000
Subject: [PATCH 003/283] Initial revision.

---
 Tri2obj/Makefile  |  74 +++++++++++++++++++++++
 Tri2obj/depend    |   1 +
 Tri2obj/tri2obj.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++
 Tri2obj/tri2obj.h |  56 ++++++++++++++++++
 4 files changed, 277 insertions(+)
 create mode 100644 Tri2obj/Makefile
 create mode 100644 Tri2obj/depend
 create mode 100644 Tri2obj/tri2obj.c
 create mode 100644 Tri2obj/tri2obj.h

diff --git a/Tri2obj/Makefile b/Tri2obj/Makefile
new file mode 100644
index 000000000..074139b2f
--- /dev/null
+++ b/Tri2obj/Makefile
@@ -0,0 +1,74 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started October 1997.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+TARGET = tri2obj
+
+CFILES = tri2obj.c
+OFILES = $(CFILES:.c=.o)
+
+
+include ../make.inc
+
+
+CFLAGS = $(FG_CFLAGS) -g
+
+
+#---------------------------------------------------------------------------
+# Primary Targets
+#---------------------------------------------------------------------------
+
+all: $(TARGET)
+
+$(TARGET): $(OFILES)
+	$(CC) $(OFILES) -o $(TARGET)
+
+clean:
+	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
+
+realclean: clean
+
+
+#---------------------------------------------------------------------------
+# Secondary Targets
+#---------------------------------------------------------------------------
+
+makedepend:
+	$(CC) -MM *.c > depend
+
+include depend
+
+tri2obj.o: tri2obj.c
+	$(CC) $(CFLAGS) -c tri2obj.c -o $@
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1997/10/29 23:05:14  curt
+# Initial revision.
+#
+# Revision 1.1  1997/10/23 23:12:09  curt
+# Initial revision.
+#
diff --git a/Tri2obj/depend b/Tri2obj/depend
new file mode 100644
index 000000000..4f9aa4b15
--- /dev/null
+++ b/Tri2obj/depend
@@ -0,0 +1 @@
+triload.o: triload.c triload.h
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
new file mode 100644
index 000000000..55268f320
--- /dev/null
+++ b/Tri2obj/tri2obj.c
@@ -0,0 +1,146 @@
+/* tri2obj.c -- read in a .ele/.node file pair generated by the triangle 
+ *              program and output a simple Wavefront .obj file.
+ *
+ * Written by Curtis Olson, started October 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "tri2obj.h"
+
+
+int nodecount, tricount;
+double nodes[MAX_NODES][3];
+int tris[MAX_TRIS][3];
+int new_tris[MAX_TRIS][3];
+
+
+/* Initialize a new mesh structure */
+void triload(char *basename) {
+    char nodename[256], elename[256];
+    FILE *node, *ele;
+    int dim, junk1, junk2;
+    int i;
+
+    strcpy(nodename, basename);
+    strcat(nodename, ".node");
+    strcpy(elename, basename);
+    strcat(elename, ".ele");
+
+    printf("Loading node file:  %s ...\n", nodename);
+    if ( (node = fopen(nodename, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", nodename);
+	exit(-1);
+    }
+
+    fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
+
+    if ( nodecount > MAX_NODES - 1 ) {
+	printf("Error, too many nodes, need to increase array size\n");
+	exit(-1);
+    } else {
+	printf("    Expecting %d nodes\n", nodecount);
+    }
+
+    for ( i = 1; i <= nodecount; i++ ) {
+	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
+	       &nodes[i][0], &nodes[i][1], &nodes[i][2], &junk2);
+	/* printf("%d %.2f %.2f %.2f\n", 
+	       junk1, nodes[i][0], nodes[i][1], nodes[i][2]); */
+    }
+
+    fclose(node);
+
+    printf("Loading element file:  %s ...\n", elename);
+    if ( (ele = fopen(elename, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", elename);
+	exit(-1);
+    }
+
+    fscanf(ele, "%d %d %d", &tricount, &junk1, &junk2);
+
+    if ( tricount > MAX_TRIS - 1 ) {
+	printf("Error, too many elements, need to increase array size\n");
+	exit(-1);
+    } else {
+	printf("    Expecting %d elements\n", tricount);
+    }
+
+    for ( i = 1; i <= tricount; i++ ) {
+	fscanf(ele, "%d %d %d %d\n", &junk1, 
+	       &tris[i][0], &tris[i][1], &tris[i][2]);
+	/* printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
+    }
+
+    fclose(ele);
+}
+
+
+/* dump in WaveFront .obj format */
+void dump_obj(char *basename) {
+    char objname[256];
+    FILE *obj;
+    int i;
+
+    strcpy(objname, basename);
+    strcat(objname, ".obj");
+
+    printf("Dumping to file:  %s ...\n", objname);
+
+    obj = fopen(objname, "w");
+
+    /* dump vertices */
+    for ( i = 1; i <= nodecount; i++ ) {
+	fprintf(obj, "v %.2f %.2f %.2f\n", 
+		nodes[i][0], nodes[i][1], nodes[i][2]);
+    }
+
+    /* dump faces */
+    for ( i = 1; i <= tricount; i++ ) {
+	fprintf(obj, "f %d %d %d\n", tris[i][0], tris[i][1], tris[i][2]);
+    }
+
+    fclose(obj);
+}
+
+int main(int argc, char **argv) {
+    char basename[256];
+
+    strcpy(basename, argv[1]);
+
+    /* load the input data files */
+    triload(basename);
+
+    /* dump in WaveFront .obj format */
+    dump_obj(basename);
+
+    return(0);
+}
+
+
+/* $Log$
+/* Revision 1.1  1997/10/29 23:05:15  curt
+/* Initial revision.
+/*
+ */
diff --git a/Tri2obj/tri2obj.h b/Tri2obj/tri2obj.h
new file mode 100644
index 000000000..6c2b14269
--- /dev/null
+++ b/Tri2obj/tri2obj.h
@@ -0,0 +1,56 @@
+/* tri2obj.h -- read in a .ele/.node file pair generated by the triangle 
+ *              program and output a Wavefront .obj file.
+ *
+ * Written by Curtis Olson, started October 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#ifndef TRI2OBJ_H
+#define TRI2OBJ_H
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+#define MAX_NODES 100000
+#define MAX_TRIS  200000
+
+
+extern int nodecount, tricount;
+extern double nodes[MAX_NODES][3];
+extern int tris[MAX_TRIS][3];
+extern int new_tris[MAX_TRIS][3];
+
+
+/* Initialize a new mesh structure */
+void triload(char *basename);
+
+
+#endif /* TRI2OBJ_H */
+
+
+/* $Log$
+/* Revision 1.1  1997/10/29 23:05:15  curt
+/* Initial revision.
+/*
+ */

From 177d6d3021a95373bd0d2e2da1e9b8c958494ea6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 14 Nov 1997 00:29:13 +0000
Subject: [PATCH 004/283] Transform scenery coordinates at this point in
 pipeline when scenery is being translated to .obj format, not when it is
 being loaded into the end renderer.  Precalculate normals for each node as
 average of the normals of each containing polygon so Garoude shading is now
 supportable.

---
 Tri2obj/Makefile  |   8 ++-
 Tri2obj/tri2obj.c | 129 ++++++++++++++++++++++++++++++++++++++++++----
 Tri2obj/tri2obj.h |  12 +++--
 3 files changed, 136 insertions(+), 13 deletions(-)

diff --git a/Tri2obj/Makefile b/Tri2obj/Makefile
index 074139b2f..9e4025bf1 100644
--- a/Tri2obj/Makefile
+++ b/Tri2obj/Makefile
@@ -43,7 +43,7 @@ CFLAGS = $(FG_CFLAGS) -g
 all: $(TARGET)
 
 $(TARGET): $(OFILES)
-	$(CC) $(OFILES) -o $(TARGET)
+	$(CC) $(OFILES) -o $(TARGET) ../../Src/Math/libMath.a -lm
 
 clean:
 	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
@@ -66,6 +66,12 @@ tri2obj.o: tri2obj.c
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1997/11/14 00:29:13  curt
+# Transform scenery coordinates at this point in pipeline when scenery is
+# being translated to .obj format, not when it is being loaded into the end
+# renderer.  Precalculate normals for each node as average of the normals
+# of each containing polygon so Garoude shading is now supportable.
+#
 # Revision 1.1  1997/10/29 23:05:14  curt
 # Initial revision.
 #
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 55268f320..d0c84870a 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -29,16 +29,85 @@
 
 #include "tri2obj.h"
 
+#include "../../Src/constants.h"
+#include "../../Src/types.h"
+#include "../../Src/Math/fg_geodesy.h"
+#include "../../Src/Math/mat3.h"
+#include "../../Src/Math/polar.h"
+
 
 int nodecount, tricount;
-double nodes[MAX_NODES][3];
+struct fgCartesianPoint nodes[MAX_NODES];
 int tris[MAX_TRIS][3];
 int new_tris[MAX_TRIS][3];
 
 
+/* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
+ * a cartesian point */
+struct fgCartesianPoint geod_to_cart(double geod[3]) {
+    struct fgCartesianPoint p;
+    double gc_lon, gc_lat, sl_radius;
+
+    /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
+	   geod[0], geod[1], geod[2]); */
+
+    gc_lon = geod[0]*ARCSEC_TO_RAD;
+    fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
+
+    /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
+	   gc_lat, sl_radius+geod[2]); */
+
+    p = fgPolarToCart(gc_lon, gc_lat, sl_radius+geod[2]);
+    
+    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", p.x, p.y, p.z); */
+
+    return(p);
+}
+
+
+/* given three points defining a triangle, calculate the normal */
+void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2, 
+		 struct fgCartesianPoint p3, double normal[3])
+{
+    double v1[3], v2[3];
+    float temp;
+
+    v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
+    v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
+
+    MAT3cross_product(normal, v1, v2);
+    MAT3_NORMALIZE_VEC(normal,temp);
+
+    /* printf("Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
+}
+
+
+/* return the index of all triangles containing the specified node */
+void find_tris(int n, int *t1, int *t2, int *t3) {
+    int i;
+
+    *t1 = *t2 = *t3 = 0;
+
+    i = 1;
+    while ( i <= tricount ) {
+        if ( (n == tris[i][0]) || (n == tris[i][1]) || (n == tris[i][2]) ) {
+            if ( *t1 == 0 ) {
+		*t1 = i;
+            } else if ( *t2 == 0 ) {
+		*t2 = i;
+	    } else {
+		*t3 = i;
+	    }
+        }
+        i++;
+    }
+}
+
+
 /* Initialize a new mesh structure */
 void triload(char *basename) {
     char nodename[256], elename[256];
+    double n[3];
     FILE *node, *ele;
     int dim, junk1, junk2;
     int i;
@@ -65,9 +134,11 @@ void triload(char *basename) {
 
     for ( i = 1; i <= nodecount; i++ ) {
 	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
-	       &nodes[i][0], &nodes[i][1], &nodes[i][2], &junk2);
-	/* printf("%d %.2f %.2f %.2f\n", 
-	       junk1, nodes[i][0], nodes[i][1], nodes[i][2]); */
+	       &n[0], &n[1], &n[2], &junk2);
+	printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]);
+	nodes[i] = geod_to_cart(n);
+	printf("%d %.2f %.2f %.2f\n", 
+	       junk1, nodes[i].x, nodes[i].y, nodes[i].z);
     }
 
     fclose(node);
@@ -100,8 +171,9 @@ void triload(char *basename) {
 /* dump in WaveFront .obj format */
 void dump_obj(char *basename) {
     char objname[256];
+    double n1[3], n2[3], n3[3];
     FILE *obj;
-    int i;
+    int i, t1, t2, t3, count;
 
     strcpy(objname, basename);
     strcat(objname, ".obj");
@@ -113,12 +185,45 @@ void dump_obj(char *basename) {
     /* dump vertices */
     for ( i = 1; i <= nodecount; i++ ) {
 	fprintf(obj, "v %.2f %.2f %.2f\n", 
-		nodes[i][0], nodes[i][1], nodes[i][2]);
+		nodes[i].x, nodes[i].y, nodes[i].z);
+    }
+
+    /* calculate and generate normals */
+    for ( i = 1; i <= nodecount; i++ ) {
+	find_tris(i, &t1, &t2, &t3);
+
+	n1[0] = n1[1] = n1[2] = 0.0;
+	n2[0] = n2[1] = n2[2] = 0.0;
+	n3[0] = n3[1] = n3[3] = 0.0;
+
+	count = 1;
+	calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], nodes[tris[t1][2]], 
+		    n1);
+
+	if ( t2 > 0 ) {
+	    calc_normal(nodes[tris[t2][0]], nodes[tris[t2][1]], 
+			nodes[tris[t2][2]], n2);
+	    count = 2;
+	}
+
+	if ( t3 > 0 ) {
+	    calc_normal(nodes[tris[t3][0]], nodes[tris[t3][1]],
+			nodes[tris[t3][2]], n3);
+	    count = 3;
+	}
+
+	fprintf(obj, "vn %.4f %.4f %.4f\n", 
+		( n1[0] + n2[0] + n3[0] ) / (double)count,
+		( n1[1] + n2[1] + n3[1] ) / (double)count,
+		( n1[2] + n2[2] + n3[2] ) / (double)count );
     }
 
     /* dump faces */
     for ( i = 1; i <= tricount; i++ ) {
-	fprintf(obj, "f %d %d %d\n", tris[i][0], tris[i][1], tris[i][2]);
+	fprintf(obj, "f %d//%d %d//%d %d//%d\n", 
+		tris[i][0], tris[i][0], 
+		tris[i][1], tris[i][1], 
+		tris[i][2], tris[i][2]);
     }
 
     fclose(obj);
@@ -140,7 +245,13 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.1  1997/10/29 23:05:15  curt
-/* Initial revision.
+/* Revision 1.2  1997/11/14 00:29:13  curt
+/* Transform scenery coordinates at this point in pipeline when scenery is
+/* being translated to .obj format, not when it is being loaded into the end
+/* renderer.  Precalculate normals for each node as average of the normals
+/* of each containing polygon so Garoude shading is now supportable.
 /*
+ * Revision 1.1  1997/10/29 23:05:15  curt
+ * Initial revision.
+ *
  */
diff --git a/Tri2obj/tri2obj.h b/Tri2obj/tri2obj.h
index 6c2b14269..361168988 100644
--- a/Tri2obj/tri2obj.h
+++ b/Tri2obj/tri2obj.h
@@ -37,7 +37,7 @@
 
 
 extern int nodecount, tricount;
-extern double nodes[MAX_NODES][3];
+extern struct fgCartesianPoint nodes[MAX_NODES];
 extern int tris[MAX_TRIS][3];
 extern int new_tris[MAX_TRIS][3];
 
@@ -50,7 +50,13 @@ void triload(char *basename);
 
 
 /* $Log$
-/* Revision 1.1  1997/10/29 23:05:15  curt
-/* Initial revision.
+/* Revision 1.2  1997/11/14 00:29:13  curt
+/* Transform scenery coordinates at this point in pipeline when scenery is
+/* being translated to .obj format, not when it is being loaded into the end
+/* renderer.  Precalculate normals for each node as average of the normals
+/* of each containing polygon so Garoude shading is now supportable.
 /*
+ * Revision 1.1  1997/10/29 23:05:15  curt
+ * Initial revision.
+ *
  */

From a3bb4bc12297b3316d07f53d6090581c9dac6365 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 14 Nov 1997 00:31:06 +0000
Subject: [PATCH 005/283] Abandon Tri2terrain ... replace with Tri2obj so we
 can use an existing tri-stripper.

---
 Tools/Makefile | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Tools/Makefile b/Tools/Makefile
index 34b2a5254..b82e2d1a3 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,7 +27,7 @@
 include make.inc
 
 
-SUBDIRS = Dem2node Tri2terrain Triangle
+SUBDIRS = Dem2node Tri2obj Triangle
 
 
 all: 
@@ -86,6 +86,10 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1997/11/14 00:31:06  curt
+# Abandon Tri2terrain ... replace with Tri2obj so we can use an existing
+# tri-stripper.
+#
 # Revision 1.1  1997/10/20 19:52:18  curt
 # Initial revision.
 #

From 6ec192a890cde998cb1f63790d2afd8321135b47 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 15 Nov 1997 18:05:05 +0000
Subject: [PATCH 006/283] minor tweaks ...

---
 Tri2obj/depend    |  4 +++-
 Tri2obj/tri2obj.c | 22 ++++++++++++++--------
 Tri2obj/tri2obj.h | 17 ++++++++++-------
 3 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/Tri2obj/depend b/Tri2obj/depend
index 4f9aa4b15..5e652e883 100644
--- a/Tri2obj/depend
+++ b/Tri2obj/depend
@@ -1 +1,3 @@
-triload.o: triload.c triload.h
+tri2obj.o: tri2obj.c tri2obj.h ../../Src/constants.h ../../Src/types.h \
+ ../../Src/Math/fg_geodesy.h ../../Src/Math/mat3.h \
+ ../../Src/Math/polar.h ../../Src/Math/../types.h
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index d0c84870a..cc529dd1d 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -135,10 +135,10 @@ void triload(char *basename) {
     for ( i = 1; i <= nodecount; i++ ) {
 	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
 	       &n[0], &n[1], &n[2], &junk2);
-	printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]);
+	/* printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); */
 	nodes[i] = geod_to_cart(n);
-	printf("%d %.2f %.2f %.2f\n", 
-	       junk1, nodes[i].x, nodes[i].y, nodes[i].z);
+	/* printf("%d %.2f %.2f %.2f\n", 
+	       junk1, nodes[i].x, nodes[i].y, nodes[i].z); */
     }
 
     fclose(node);
@@ -183,11 +183,13 @@ void dump_obj(char *basename) {
     obj = fopen(objname, "w");
 
     /* dump vertices */
+    printf("  writing vertices\n");
     for ( i = 1; i <= nodecount; i++ ) {
 	fprintf(obj, "v %.2f %.2f %.2f\n", 
 		nodes[i].x, nodes[i].y, nodes[i].z);
     }
 
+    printf("  calculating and writing normals\n");
     /* calculate and generate normals */
     for ( i = 1; i <= nodecount; i++ ) {
 	find_tris(i, &t1, &t2, &t3);
@@ -219,6 +221,7 @@ void dump_obj(char *basename) {
     }
 
     /* dump faces */
+    printf("  writing faces\n");
     for ( i = 1; i <= tricount; i++ ) {
 	fprintf(obj, "f %d//%d %d//%d %d//%d\n", 
 		tris[i][0], tris[i][0], 
@@ -245,12 +248,15 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.2  1997/11/14 00:29:13  curt
-/* Transform scenery coordinates at this point in pipeline when scenery is
-/* being translated to .obj format, not when it is being loaded into the end
-/* renderer.  Precalculate normals for each node as average of the normals
-/* of each containing polygon so Garoude shading is now supportable.
+/* Revision 1.3  1997/11/15 18:05:05  curt
+/* minor tweaks ...
 /*
+ * Revision 1.2  1997/11/14 00:29:13  curt
+ * Transform scenery coordinates at this point in pipeline when scenery is
+ * being translated to .obj format, not when it is being loaded into the end
+ * renderer.  Precalculate normals for each node as average of the normals
+ * of each containing polygon so Garoude shading is now supportable.
+ *
  * Revision 1.1  1997/10/29 23:05:15  curt
  * Initial revision.
  *
diff --git a/Tri2obj/tri2obj.h b/Tri2obj/tri2obj.h
index 361168988..3d3584010 100644
--- a/Tri2obj/tri2obj.h
+++ b/Tri2obj/tri2obj.h
@@ -32,8 +32,8 @@
 #include <string.h>
 
 
-#define MAX_NODES 100000
-#define MAX_TRIS  200000
+#define MAX_NODES 200000
+#define MAX_TRIS  400000
 
 
 extern int nodecount, tricount;
@@ -50,12 +50,15 @@ void triload(char *basename);
 
 
 /* $Log$
-/* Revision 1.2  1997/11/14 00:29:13  curt
-/* Transform scenery coordinates at this point in pipeline when scenery is
-/* being translated to .obj format, not when it is being loaded into the end
-/* renderer.  Precalculate normals for each node as average of the normals
-/* of each containing polygon so Garoude shading is now supportable.
+/* Revision 1.3  1997/11/15 18:05:06  curt
+/* minor tweaks ...
 /*
+ * Revision 1.2  1997/11/14 00:29:13  curt
+ * Transform scenery coordinates at this point in pipeline when scenery is
+ * being translated to .obj format, not when it is being loaded into the end
+ * renderer.  Precalculate normals for each node as average of the normals
+ * of each containing polygon so Garoude shading is now supportable.
+ *
  * Revision 1.1  1997/10/29 23:05:15  curt
  * Initial revision.
  *

From 7808e7ee73fefaedc60a76639db6d4f3e0e412f0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 27 Nov 1997 00:17:32 +0000
Subject: [PATCH 007/283] Initial revision.

---
 FixNode/Makefile  | 80 +++++++++++++++++++++++++++++++++++++++++
 FixNode/fixnode.c | 55 ++++++++++++++++++++++++++++
 FixNode/fixnode.h | 49 +++++++++++++++++++++++++
 FixNode/main.c    | 57 +++++++++++++++++++++++++++++
 FixNode/triload.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
 FixNode/triload.h | 54 ++++++++++++++++++++++++++++
 6 files changed, 386 insertions(+)
 create mode 100644 FixNode/Makefile
 create mode 100644 FixNode/fixnode.c
 create mode 100644 FixNode/fixnode.h
 create mode 100644 FixNode/main.c
 create mode 100644 FixNode/triload.c
 create mode 100644 FixNode/triload.h

diff --git a/FixNode/Makefile b/FixNode/Makefile
new file mode 100644
index 000000000..236c6acc9
--- /dev/null
+++ b/FixNode/Makefile
@@ -0,0 +1,80 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started October 1997.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+TARGET = fixnode
+
+CFILES = ../Dem2node/demparse.c fixnode.c main.c ../Dem2node/mesh.c triload.c
+OFILES = $(CFILES:.c=.o)
+
+
+include ../make.inc
+
+
+CFLAGS = $(FG_CFLAGS) -g
+
+
+#---------------------------------------------------------------------------
+# Primary Targets
+#---------------------------------------------------------------------------
+
+all: $(TARGET)
+
+$(TARGET): $(OFILES)
+	$(CC) $(OFILES) -o $(TARGET)
+
+clean:
+	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
+
+realclean: clean
+
+
+#---------------------------------------------------------------------------
+# Secondary Targets
+#---------------------------------------------------------------------------
+
+makedepend:
+	$(CC) -MM *.c > depend
+
+include depend
+
+../Dem2node/demparse.o: ../Dem2node/demparse.c
+	$(CC) $(CFLAGS) -c ../Dem2node/demparse.c -o $@
+
+main.o: main.c
+	$(CC) $(CFLAGS) -c main.c -o $@
+
+mesh.o: mesh.c
+	$(CC) $(CFLAGS) -c mesh.c -o $@
+
+triload.o: triload.c
+	$(CC) $(CFLAGS) -c triload.c -o $@
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1997/11/27 00:17:32  curt
+# Initial revision.
+#
diff --git a/FixNode/fixnode.c b/FixNode/fixnode.c
new file mode 100644
index 000000000..274e5627c
--- /dev/null
+++ b/FixNode/fixnode.c
@@ -0,0 +1,55 @@
+/* fixnode.c -- traverse the node file and fix the elevation of all the new
+ *              interpolated points.
+ *
+ * Written by Curtis Olson, started November 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "fixnode.h"
+#include "../Dem2node/mesh.h"
+#include "triload.h"
+
+
+/* load the node information */
+void fixnodes(struct MESH *m) {
+    int i;
+
+    for ( i = origcount + 1; i <= nodecount; i++ ) {
+	printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0],
+	       nodes[i][1], nodes[i][2]);
+
+	nodes[i][2] = mesh_altitude(m, nodes[i][0], nodes[i][1]);
+
+	printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
+	       nodes[i][1], nodes[i][2]);
+    }
+}
+
+
+/* $Log$
+/* Revision 1.1  1997/11/27 00:17:33  curt
+/* Initial revision.
+/*
+ */
diff --git a/FixNode/fixnode.h b/FixNode/fixnode.h
new file mode 100644
index 000000000..3c514b974
--- /dev/null
+++ b/FixNode/fixnode.h
@@ -0,0 +1,49 @@
+/* fixnode.h -- traverse the node file and fix the elevation of all the new
+ *              interpolated points.
+ *
+ * Written by Curtis Olson, started November 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#ifndef FIXNODE_H
+#define FIXNODE_H
+
+
+#include <stdio.h>
+#include <string.h>
+
+/* #include "fixnode.h" */
+#include "../Dem2node/mesh.h"
+
+
+/* load the node information */
+void fixnodes(struct MESH *m);
+
+
+#endif /* FIXNODE_H */
+
+
+/* $Log$
+/* Revision 1.1  1997/11/27 00:17:33  curt
+/* Initial revision.
+/*
+ */
diff --git a/FixNode/main.c b/FixNode/main.c
new file mode 100644
index 000000000..67f47a9d1
--- /dev/null
+++ b/FixNode/main.c
@@ -0,0 +1,57 @@
+/* triload.c -- read in a .node file and fix the z values of the interpolated 
+ *              points
+ *
+ * Written by Curtis Olson, started November 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../Dem2node/demparse.h"
+#include "fixnode.h"
+#include "triload.h"
+
+
+int main(int argc, char **argv) {
+    char basename[256];
+    struct MESH dem_mesh;
+
+    strcpy(basename, argv[1]);
+
+    /* load the input data files */
+    triload(basename);
+
+    /* load the corresponding dem file so we can interpolate elev values */
+    dem_parse(basename, &dem_mesh);
+
+    fixnodes(&dem_mesh);
+
+    return(0);
+}
+
+
+/* $Log$
+/* Revision 1.1  1997/11/27 00:17:34  curt
+/* Initial revision.
+/*
+ */
diff --git a/FixNode/triload.c b/FixNode/triload.c
new file mode 100644
index 000000000..2d6d670d7
--- /dev/null
+++ b/FixNode/triload.c
@@ -0,0 +1,91 @@
+/* triload.c -- read in a .node file and fix the z values of the interpolated 
+ *              points
+ *
+ * Written by Curtis Olson, started November 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "triload.h"
+
+
+int origcount;
+int nodecount;
+double nodes[MAX_NODES][3];
+
+
+/* load the node information */
+void triload(char *basename) {
+    char origname[256], nodename[256];
+    FILE *orig, *node;
+    int dim, junk1, junk2;
+    int i;
+
+    strcpy(origname, basename);
+    strcat(origname, ".node");
+
+    strcpy(nodename, basename);
+    strcat(nodename, ".1.node");
+
+    /* open original node file to see number of original nodes */
+
+    printf("Checking original node file:  %s ...\n", origname);
+    if ( (orig = fopen(origname, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", origname);
+	exit(-1);
+    }
+    fscanf(orig, "%d %d %d %d", &origcount, &dim, &junk1, &junk2);
+    printf("    Found %d nodes\n", origcount);
+
+    printf("Loading node file:  %s ...\n", nodename);
+    if ( (node = fopen(nodename, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", nodename);
+	exit(-1);
+    }
+
+    fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
+
+    if ( nodecount > MAX_NODES - 1 ) {
+	printf("Error, too many nodes, need to increase array size\n");
+	exit(-1);
+    } else {
+	printf("    Expecting %d nodes\n", nodecount);
+    }
+
+    for ( i = 1; i <= nodecount; i++ ) {
+	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
+	       &nodes[i][0], &nodes[i][1], &nodes[i][2], &junk2);
+	/* printf("%d %.2f %.2f %.2f\n", junk1, nodes[i][0], nodes[i][1], 
+	   nodes[i][2]); */
+    }
+
+    fclose(node);
+}
+
+
+/* $Log$
+/* Revision 1.1  1997/11/27 00:17:35  curt
+/* Initial revision.
+/*
+ */
diff --git a/FixNode/triload.h b/FixNode/triload.h
new file mode 100644
index 000000000..058c01869
--- /dev/null
+++ b/FixNode/triload.h
@@ -0,0 +1,54 @@
+/* triload.h -- read in a .node file and fix the z values of the interpolated 
+ *              points
+ *
+ * Written by Curtis Olson, started November 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#ifndef TRILOAD_H
+#define TRILOAD_H
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+#define MAX_NODES 200000
+#define MAX_TRIS  400000
+
+
+extern int origcount, nodecount, tricount;
+double nodes[MAX_NODES][3];
+
+
+/* Initialize a new mesh structure */
+void triload(char *basename);
+
+
+#endif /* TRILOAD_H */
+
+
+/* $Log$
+/* Revision 1.1  1997/11/27 00:17:35  curt
+/* Initial revision.
+/*
+ */

From 19f88388072369b9a98a7d9d224cc5583326cd62 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 27 Nov 1997 00:18:26 +0000
Subject: [PATCH 008/283] Added FixNode

---
 Tools/Makefile | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Tools/Makefile b/Tools/Makefile
index b82e2d1a3..d04297d1f 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,7 +27,7 @@
 include make.inc
 
 
-SUBDIRS = Dem2node Tri2obj Triangle
+SUBDIRS = Dem2node FixNode Tri2obj Triangle
 
 
 all: 
@@ -86,6 +86,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1997/11/27 00:18:26  curt
+# Added FixNode
+#
 # Revision 1.2  1997/11/14 00:31:06  curt
 # Abandon Tri2terrain ... replace with Tri2obj so we can use an existing
 # tri-stripper.

From 35c3de4cc2d4c307a9277de3909de1d39aa64c60 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Dec 1997 13:12:07 +0000
Subject: [PATCH 009/283] Updated to fix every node.

---
 FixNode/fixnode.c | 42 +++++++++++++++++++++++++++++++++++-------
 FixNode/fixnode.h |  9 ++++++---
 FixNode/main.c    |  9 ++++++---
 3 files changed, 47 insertions(+), 13 deletions(-)

diff --git a/FixNode/fixnode.c b/FixNode/fixnode.c
index 274e5627c..d3feb16c5 100644
--- a/FixNode/fixnode.c
+++ b/FixNode/fixnode.c
@@ -33,23 +33,51 @@
 
 
 /* load the node information */
-void fixnodes(struct MESH *m) {
+void fixnodes(char *basename, struct MESH *m) {
+    char file[256];
+    FILE *fd;
     int i;
 
-    for ( i = origcount + 1; i <= nodecount; i++ ) {
-	printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0],
-	       nodes[i][1], nodes[i][2]);
+    printf("Fixing up node elevations\n");
+
+    /* we could just fix the new nodes as the first "for" statement
+     * would do, but that leads to funny results (I need to figure out
+     * why.)  So, let's try fixing all of them */
+
+    /* for ( i = origcount + 1; i <= nodecount; i++ ) { */
+    for ( i = 1; i <= nodecount; i++ ) {
+	/* printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0],
+	       nodes[i][1], nodes[i][2]); */
 
 	nodes[i][2] = mesh_altitude(m, nodes[i][0], nodes[i][1]);
 
-	printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
+	/* printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
+	       nodes[i][1], nodes[i][2]); */
+    }
+
+    strcpy(file, basename);
+    strcat(file, ".1.node");
+
+    printf("Overwriting original node file: %s\n", file);
+
+    fd = fopen(file, "w");
+
+    fprintf(fd, "%d 2 1 0\n", nodecount);
+
+    for ( i = 1; i <= nodecount; i++ ) {
+	fprintf(fd, "%d %.2f %.2f %.2f 0\n", i, nodes[i][0],
 	       nodes[i][1], nodes[i][2]);
     }
+
+    fclose(fd);
 }
 
 
 /* $Log$
-/* Revision 1.1  1997/11/27 00:17:33  curt
-/* Initial revision.
+/* Revision 1.2  1997/12/02 13:12:07  curt
+/* Updated to fix every node.
 /*
+ * Revision 1.1  1997/11/27 00:17:33  curt
+ * Initial revision.
+ *
  */
diff --git a/FixNode/fixnode.h b/FixNode/fixnode.h
index 3c514b974..303eb6286 100644
--- a/FixNode/fixnode.h
+++ b/FixNode/fixnode.h
@@ -36,14 +36,17 @@
 
 
 /* load the node information */
-void fixnodes(struct MESH *m);
+void fixnodes(char *basename, struct MESH *m);
 
 
 #endif /* FIXNODE_H */
 
 
 /* $Log$
-/* Revision 1.1  1997/11/27 00:17:33  curt
-/* Initial revision.
+/* Revision 1.2  1997/12/02 13:12:07  curt
+/* Updated to fix every node.
 /*
+ * Revision 1.1  1997/11/27 00:17:33  curt
+ * Initial revision.
+ *
  */
diff --git a/FixNode/main.c b/FixNode/main.c
index 67f47a9d1..7ebd5d7e5 100644
--- a/FixNode/main.c
+++ b/FixNode/main.c
@@ -44,14 +44,17 @@ int main(int argc, char **argv) {
     /* load the corresponding dem file so we can interpolate elev values */
     dem_parse(basename, &dem_mesh);
 
-    fixnodes(&dem_mesh);
+    fixnodes(basename, &dem_mesh);
 
     return(0);
 }
 
 
 /* $Log$
-/* Revision 1.1  1997/11/27 00:17:34  curt
-/* Initial revision.
+/* Revision 1.2  1997/12/02 13:12:07  curt
+/* Updated to fix every node.
 /*
+ * Revision 1.1  1997/11/27 00:17:34  curt
+ * Initial revision.
+ *
  */

From aa605d17e8f15127d203122cea21e3d7c151494c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Dec 1997 13:13:32 +0000
Subject: [PATCH 010/283] Fixed problem with averaged vertex normals.

---
 Tri2obj/Makefile  |  5 ++++-
 Tri2obj/tri2obj.c | 20 +++++++++++++-------
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/Tri2obj/Makefile b/Tri2obj/Makefile
index 9e4025bf1..87ddbbd49 100644
--- a/Tri2obj/Makefile
+++ b/Tri2obj/Makefile
@@ -33,7 +33,7 @@ OFILES = $(CFILES:.c=.o)
 include ../make.inc
 
 
-CFLAGS = $(FG_CFLAGS) -g
+CFLAGS = $(FG_CFLAGS) -O3 -fomit-frame-pointer -funroll-all-loops -ffast-math
 
 
 #---------------------------------------------------------------------------
@@ -66,6 +66,9 @@ tri2obj.o: tri2obj.c
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1997/12/02 13:13:32  curt
+# Fixed problem with averaged vertex normals.
+#
 # Revision 1.2  1997/11/14 00:29:13  curt
 # Transform scenery coordinates at this point in pipeline when scenery is
 # being translated to .obj format, not when it is being loaded into the end
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index cc529dd1d..ef1007e67 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -171,7 +171,7 @@ void triload(char *basename) {
 /* dump in WaveFront .obj format */
 void dump_obj(char *basename) {
     char objname[256];
-    double n1[3], n2[3], n3[3];
+    double n1[3], n2[3], n3[3], norm[3], temp;
     FILE *obj;
     int i, t1, t2, t3, count;
 
@@ -214,10 +214,13 @@ void dump_obj(char *basename) {
 	    count = 3;
 	}
 
-	fprintf(obj, "vn %.4f %.4f %.4f\n", 
-		( n1[0] + n2[0] + n3[0] ) / (double)count,
-		( n1[1] + n2[1] + n3[1] ) / (double)count,
-		( n1[2] + n2[2] + n3[2] ) / (double)count );
+	norm[0] = ( n1[0] + n2[0] + n3[0] ) / (double)count;
+	norm[1] = ( n1[1] + n2[1] + n3[1] ) / (double)count;
+	norm[2] = ( n1[2] + n2[2] + n3[2] ) / (double)count;
+
+	MAT3_NORMALIZE_VEC(norm, temp);
+	
+	fprintf(obj, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
     }
 
     /* dump faces */
@@ -248,9 +251,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.3  1997/11/15 18:05:05  curt
-/* minor tweaks ...
+/* Revision 1.4  1997/12/02 13:13:32  curt
+/* Fixed problem with averaged vertex normals.
 /*
+ * Revision 1.3  1997/11/15 18:05:05  curt
+ * minor tweaks ...
+ *
  * Revision 1.2  1997/11/14 00:29:13  curt
  * Transform scenery coordinates at this point in pipeline when scenery is
  * being translated to .obj format, not when it is being loaded into the end

From 0234a6a5f959a6fedfabc80c5ba37d4efcc5ff4c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Dec 1997 19:17:50 +0000
Subject: [PATCH 011/283] Fixed a type in the normal generation code.

---
 Tri2obj/tri2obj.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index ef1007e67..0737899ae 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -78,7 +78,7 @@ void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2,
     MAT3cross_product(normal, v1, v2);
     MAT3_NORMALIZE_VEC(normal,temp);
 
-    /* printf("Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
+/*  printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
 }
 
 
@@ -192,11 +192,13 @@ void dump_obj(char *basename) {
     printf("  calculating and writing normals\n");
     /* calculate and generate normals */
     for ( i = 1; i <= nodecount; i++ ) {
+/* 	printf("Finding normal\n"); */
+
 	find_tris(i, &t1, &t2, &t3);
 
 	n1[0] = n1[1] = n1[2] = 0.0;
 	n2[0] = n2[1] = n2[2] = 0.0;
-	n3[0] = n3[1] = n3[3] = 0.0;
+	n3[0] = n3[1] = n3[2] = 0.0;
 
 	count = 1;
 	calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], nodes[tris[t1][2]], 
@@ -214,11 +216,17 @@ void dump_obj(char *basename) {
 	    count = 3;
 	}
 
+/* 	printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
+
 	norm[0] = ( n1[0] + n2[0] + n3[0] ) / (double)count;
 	norm[1] = ( n1[1] + n2[1] + n3[1] ) / (double)count;
 	norm[2] = ( n1[2] + n2[2] + n3[2] ) / (double)count;
-
+	
+/* 	printf("  count = %d\n", count); */
+/* 	printf("  Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);*/
 	MAT3_NORMALIZE_VEC(norm, temp);
+/* 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
+/* 	       norm[0], norm[1], norm[2]); */
 	
 	fprintf(obj, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
     }
@@ -251,9 +259,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.4  1997/12/02 13:13:32  curt
-/* Fixed problem with averaged vertex normals.
+/* Revision 1.5  1997/12/08 19:17:50  curt
+/* Fixed a type in the normal generation code.
 /*
+ * Revision 1.4  1997/12/02 13:13:32  curt
+ * Fixed problem with averaged vertex normals.
+ *
  * Revision 1.3  1997/11/15 18:05:05  curt
  * minor tweaks ...
  *

From 417d73fc39d12bf80f9156543ff477b02904161e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Dec 1997 19:28:54 +0000
Subject: [PATCH 012/283] Initial revision.

---
 FixObj/Makefile |  76 +++++++++++++
 FixObj/main.c   |  47 ++++++++
 FixObj/obj.c    | 296 ++++++++++++++++++++++++++++++++++++++++++++++++
 FixObj/obj.h    |  49 ++++++++
 4 files changed, 468 insertions(+)
 create mode 100644 FixObj/Makefile
 create mode 100644 FixObj/main.c
 create mode 100644 FixObj/obj.c
 create mode 100644 FixObj/obj.h

diff --git a/FixObj/Makefile b/FixObj/Makefile
new file mode 100644
index 000000000..0061b1213
--- /dev/null
+++ b/FixObj/Makefile
@@ -0,0 +1,76 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started October 1997.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+TARGET = fixobj
+
+CFILES = main.c obj.c
+OFILES = $(CFILES:.c=.o)
+
+
+include ../make.inc
+
+
+CFLAGS = $(FG_CFLAGS) -g
+
+LIBS = ../../Src/Math/libMath.a -lm
+
+
+#---------------------------------------------------------------------------
+# Primary Targets
+#---------------------------------------------------------------------------
+
+all: $(TARGET)
+
+$(TARGET): $(OFILES)
+	$(CC) $(OFILES) -o $(TARGET) $(LIBS)
+
+clean:
+	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
+
+realclean: clean
+
+
+#---------------------------------------------------------------------------
+# Secondary Targets
+#---------------------------------------------------------------------------
+
+makedepend:
+	$(CC) -MM *.c > depend
+
+include depend
+
+main.o: main.c
+	$(CC) $(CFLAGS) -c main.c -o $@
+
+obj.o: obj.c
+	$(CC) $(CFLAGS) -c obj.c -o $@
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1997/12/08 19:28:54  curt
+# Initial revision.
+#
diff --git a/FixObj/main.c b/FixObj/main.c
new file mode 100644
index 000000000..0a499f1f9
--- /dev/null
+++ b/FixObj/main.c
@@ -0,0 +1,47 @@
+/* main.c -- read and fix the stripping order of a .obj file
+ *
+ * Written by Curtis Olson, started December 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <stdio.h>
+
+#include "obj.h"
+
+
+int main(int argc, char **argv) {
+    char basename[256];
+
+    strcpy(basename, argv[1]);
+
+    /* load the input data files */
+    obj_fix(basename);
+
+    return(0);
+}
+
+
+/* $Log$
+/* Revision 1.1  1997/12/08 19:28:54  curt
+/* Initial revision.
+/*
+ */
diff --git a/FixObj/obj.c b/FixObj/obj.c
new file mode 100644
index 000000000..55201f0fd
--- /dev/null
+++ b/FixObj/obj.c
@@ -0,0 +1,296 @@
+/**************************************************************************
+ * obj.c -- routines to handle WaveFront .obj format files.
+ *
+ * Written by Curtis Olson, started October 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "obj.h"
+
+#include "../../Src/Math/mat3.h"
+
+
+/* what do ya' know, here's some global variables */
+float nodes[MAXNODES][3];
+float normals[MAXNODES][3];
+
+int ccw_list[MAXNODES];
+int ccw_list_ptr;
+
+int cw_list[MAXNODES];
+int cw_list_ptr;
+
+FILE *in, *out;
+
+
+/* some simple list routines */
+
+/* reset the list */
+void list_init(int *list_ptr) {
+    *list_ptr = 0;
+}
+
+
+/* add to list */
+void list_add(int *list, int *list_ptr, int node) {
+    if ( *list_ptr >= MAXNODES ) {
+	printf("ERROR: list overflow in list_add()\n");
+	exit(-1);
+    }
+
+    list[*list_ptr] = node;
+    *list_ptr += 1;
+
+    printf("list pointer = %d  adding %d\n", *list_ptr, node); 
+}
+
+
+/* dump list */
+void dump_list(int *list, int list_ptr) {
+    int i;
+
+    if ( list_ptr < 3 ) {
+	printf("List is empty ... skipping\n");
+	return;
+    }
+
+    printf("Dumping list, size = %d\n", list_ptr);
+
+    i = 0;
+    while ( i < list_ptr ) { 
+	/* do next strip */
+
+	/* dump header */
+	fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]);
+	printf("t %d %d %d\n", list[i], list[i+1], list[i+2]);
+	i += 3;
+
+	/* dump rest of strip (until -1) */
+	while ( (i < list_ptr) && (list[i] != -1) ) { 
+	    fprintf(out, "q %d", list[i]);
+	    i++;
+	    if ( (i < list_ptr) && (list[i] != -1) ) { 
+		fprintf(out, " %d", list[i]);
+		i++;
+	    }
+	    fprintf(out, "\n");
+	}
+
+	i++;
+    }
+}
+
+
+/* Check the direction the current triangle faces, compared to it's
+ * pregenerated normal.  Returns the dot product between the target
+ * normal and actual normal.  If the dot product is close to 1.0, they
+ * nearly match.  If the are close to -1.0, the are nearly
+ * opposite. */
+double check_cur_face(int n1, int n2, int n3) {
+    double v1[3], v2[3], approx_normal[3], dot_prod, temp;
+
+    /* check for the proper rotation by calculating an approximate
+     * normal and seeing if it is close to the precalculated normal */
+    v1[0] = nodes[n2][0] - nodes[n1][0];
+    v1[1] = nodes[n2][1] - nodes[n1][1];
+    v1[2] = nodes[n2][2] - nodes[n1][2];
+    v2[0] = nodes[n3][0] - nodes[n1][0];
+    v2[1] = nodes[n3][1] - nodes[n1][1];
+    v2[2] = nodes[n3][2] - nodes[n1][2];
+
+    MAT3cross_product(approx_normal, v1, v2);
+    MAT3_NORMALIZE_VEC(approx_normal,temp);
+    dot_prod = MAT3_DOT_PRODUCT(normals[n1], approx_normal);
+
+    /* not first triangle */
+    /* if ( ((dot_prod < -0.5) && !is_backwards) ||
+	 ((dot_prod >  0.5) && is_backwards) ) {
+	printf("    Approx normal = %.2f %.2f %.2f\n", approx_normal[0], 
+	       approx_normal[1], approx_normal[2]);
+	printf("    Dot product = %.4f\n", dot_prod);
+    } */
+    /* angle = acos(dot_prod); */
+    /* printf("Normal ANGLE = %.3f rads.\n", angle); */
+
+    return(dot_prod);
+}
+
+
+/* Load a .obj file */
+void obj_fix(char *basename) {
+    char line[256];
+    char inpath[256], outpath[256];
+    double dot_prod;
+    int first, ncount, vncount, n1, n2, n3, n4;
+    int is_ccw;
+
+    strcpy(inpath, basename);
+    strcat(inpath, ".obj");
+
+    strcpy(outpath, basename);
+    strcat(outpath, ".1.obj");
+
+    if ( (in = fopen(inpath, "r")) == NULL ) {
+	printf("Cannot open file: %s\n", inpath);
+	exit(-1);
+    }
+
+    if ( (out = fopen(outpath, "w")) == NULL ) {
+	printf("Cannot open file: %s\n", outpath);
+	exit(-1);
+    }
+
+    list_init(&ccw_list_ptr);
+    list_init(&cw_list_ptr);
+
+    first = 1;
+    ncount = 1;
+    vncount = 1;
+
+    printf("Reading file:  %s\n", inpath);
+
+    while ( fgets(line, 250, in) != NULL ) {
+	if ( line[0] == '#' ) {
+	    /* pass along the comments verbatim */
+	    fprintf(out, "%s", line);
+	} else if ( strlen(line) <= 1 ) {
+	    /* pass along empty lines */
+	    fprintf(out, "%s", line);
+	} else if ( strncmp(line, "v ", 2) == 0 ) {
+	    /* save vertex to memory and output to file */
+            if ( ncount < MAXNODES ) {
+                /* printf("vertex = %s", line); */
+                sscanf(line, "v %f %f %f\n", 
+                       &nodes[ncount][0], &nodes[ncount][1], &nodes[ncount][2]);
+		fprintf(out, "v %.2f %.2f %.2f\n", 
+		       nodes[ncount][0], nodes[ncount][1], nodes[ncount][2]);
+		ncount++;
+            } else {
+                printf("Read too many nodes ... dying :-(\n");
+                exit(-1);
+            }
+	} else if ( strncmp(line, "vn ", 3) == 0 ) {
+	    /* save vertex normals to memory and output to file */
+            if ( vncount < MAXNODES ) {
+                /* printf("vertex normal = %s", line); */
+                sscanf(line, "vn %f %f %f\n", 
+                       &normals[vncount][0], &normals[vncount][1], 
+                       &normals[vncount][2]);
+		fprintf(out, "vn %.4f %.4f %.4f\n", normals[vncount][0], 
+			normals[vncount][1], normals[vncount][2]);
+                vncount++;
+            } else {
+                printf("Read too many vertex normals ... dying :-(\n");
+                exit(-1);
+            }
+	} else if ( line[0] == 't' ) {
+	    /* starting a new triangle strip */
+
+	    printf("Starting a new triangle strip\n");
+
+	    n1 = n2 = n3 = n4 = 0;
+
+	    printf("new tri strip = %s", line);
+	    sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
+
+	    dot_prod = check_cur_face(n1, n2, n3);
+	    if ( dot_prod < -0.5 ) {
+		/* this stripe is backwards (CW) */
+		is_ccw = 0;
+		printf(" -> Starting a backwards stripe\n");
+	    } else {
+		/* this stripe is normal (CCW) */
+		is_ccw = 1;
+	    }
+
+	    if ( is_ccw ) {
+		if ( ccw_list_ptr ) {
+		    list_add(ccw_list, &ccw_list_ptr, -1);
+		}
+
+		list_add(ccw_list, &ccw_list_ptr, n1);
+		list_add(ccw_list, &ccw_list_ptr, n2);
+		list_add(ccw_list, &ccw_list_ptr, n3);
+	    } else {
+		if ( cw_list_ptr ) {
+		    list_add(cw_list, &cw_list_ptr, -1);
+		}
+
+		list_add(cw_list, &cw_list_ptr, n1);
+		list_add(cw_list, &cw_list_ptr, n2);
+		list_add(cw_list, &cw_list_ptr, n3);
+	    }
+
+	    if ( n4 > 0 ) {
+		if ( is_ccw ) {
+		    list_add(ccw_list, &ccw_list_ptr, n4);
+		} else {
+		    list_add(cw_list, &cw_list_ptr, n4);
+		}
+	    }
+	} else if ( line[0] == 'f' ) {
+	    /* pass along the unoptimized faces verbatim */
+	    fprintf(out, "%s", line);
+	} else if ( line[0] == 'q' ) {
+	    /* continue a triangle strip */
+	    n1 = n2 = 0;
+
+	    /* printf("continued tri strip = %s ", line); */
+	    sscanf(line, "q %d %d\n", &n1, &n2);
+
+	    if ( is_ccw ) {
+		list_add(ccw_list, &ccw_list_ptr, n1);
+	    } else {
+		list_add(cw_list, &cw_list_ptr, n1);
+	    }
+
+	    if ( n2 > 0 ) {
+		if ( is_ccw ) {
+		    list_add(ccw_list, &ccw_list_ptr, n2);
+		} else {
+		    list_add(cw_list, &cw_list_ptr, n2);
+		}
+	    }
+	} else {
+	    printf("Unknown line in %s = %s\n", inpath, line);
+	}
+    }
+
+    fprintf(out, "winding ccw\n");
+    dump_list(ccw_list, ccw_list_ptr);
+
+    fprintf(out, "winding cw\n");
+    dump_list(cw_list, cw_list_ptr);
+
+    fclose(in);
+    fclose(out);
+}
+
+
+/* $Log$
+/* Revision 1.1  1997/12/08 19:28:54  curt
+/* Initial revision.
+/*
+ */
diff --git a/FixObj/obj.h b/FixObj/obj.h
new file mode 100644
index 000000000..c0ecf801c
--- /dev/null
+++ b/FixObj/obj.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ * obj.h -- routines to handle WaveFront .obj format files.
+ *
+ * Written by Curtis Olson, started October 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#ifndef OBJ_H
+#define OBJ_H
+
+
+#define MAXNODES 100000
+
+extern float nodes[MAXNODES][3];
+extern float normals[MAXNODES][3];
+extern int stack[MAXNODES];
+
+
+/* Load a .obj file */
+void obj_fix(char *basename);
+
+
+#endif /* OBJ_H */
+
+
+/* $Log$
+/* Revision 1.1  1997/12/08 19:28:55  curt
+/* Initial revision.
+/*
+ */

From a4a0e63dbf18ef2767d595d1210af25684d47665 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Dec 1997 22:30:45 +0000
Subject: [PATCH 013/283] Initial revision.

---
 Tools/README | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 Tools/README

diff --git a/Tools/README b/Tools/README
new file mode 100644
index 000000000..21133e438
--- /dev/null
+++ b/Tools/README
@@ -0,0 +1,15 @@
+1.  Start with file.dem
+
+2.  dem2node file tolerance^2 (meters)
+
+    - dem2node file 160000
+
+3.  fixnode file.1
+
+4.  tri2obj file.1
+
+5.  strip file.1.obj
+
+6.  cp bands.d file.new.obj
+
+7.  fixobj file.new

From c3d53226765fff4d69e8a0b9fcd2e6f487ea4a59 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Dec 1997 22:32:24 +0000
Subject: [PATCH 014/283] Added -L/usr/X11R6/lib to link command.

---
 Triangle/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Triangle/Makefile b/Triangle/Makefile
index e048c5a67..66afd63cd 100644
--- a/Triangle/Makefile
+++ b/Triangle/Makefile
@@ -103,7 +103,7 @@ $(BIN)triangle.o: $(SRC)triangle.c $(SRC)triangle.h
 		$(SRC)triangle.c
 
 $(BIN)showme: $(SRC)showme.c
-	$(CC) $(CSWITCHES) -o $(BIN)showme $(SRC)showme.c -lX11
+	$(CC) $(CSWITCHES) -o $(BIN)showme $(SRC)showme.c -L/usr/X11R6/lib -lX11
 
 clean: distclean
 

From 0b3701e0c2d30a2e7606f6d05104f2ab0c2cf121 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 10 Dec 1997 01:18:25 +0000
Subject: [PATCH 015/283] Initial revision.

---
 Tools/Makefile | 19 ++++++++++++-------
 Tools/TODO     |  2 ++
 Tools/make.inc |  5 ++++-
 3 files changed, 18 insertions(+), 8 deletions(-)
 create mode 100644 Tools/TODO

diff --git a/Tools/Makefile b/Tools/Makefile
index d04297d1f..060bc5d22 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,7 +27,7 @@
 include make.inc
 
 
-SUBDIRS = Dem2node FixNode Tri2obj Triangle
+SUBDIRS = Dem2node FixNode FixObj Stripe_u Tri2obj Triangle
 
 
 all: 
@@ -58,15 +58,17 @@ clean:
 
 source-tar: clean
 	echo "need to fix this"
-#	(cd ../..; \
-#	tar cvzf source-$(VERSION).tar.gz FlightGear/fgtop FlightGear/COPYING \
-#	FlightGear/Docs FlightGear/Src FlightGear/Thanks)
+	(cd ..; \
+	tar cvzf demtools-$(VERSION).tar.gz Tools/Makefile Tools/README \
+	Tools/TODO Tools/make.inc Tools/Dem2node Tools/FixNode Tools/FixObj \
+	Tools/Stripe_u Tools/Tri2obj Tools/Triangle Tools/mesa-e.dem)
 
 source-zip: clean
 	echo "need to fix this"
-#	(cd ../..; \
-#	zip -r source-$(VERSION).zip FlightGear/fgtop FlightGear/COPYING \
-#	FlightGear/Docs FlightGear/Src FlightGear/Thanks)
+	(cd ..; \
+	zip -r demtools-$(VERSION).zip Tools/Makefile Tools/README \
+	Tools/TODO Tools/make.inc Tools/Dem2node Tools/FixNode Tools/FixObj \
+	Tools/Stripe_u Tools/Tri2obj Tools/Triangle Tools/mesa-e.dem)
 
 bin-tar: all
 	echo "need to fix this"
@@ -86,6 +88,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1997/12/10 01:18:25  curt
+# Initial revision.
+#
 # Revision 1.3  1997/11/27 00:18:26  curt
 # Added FixNode
 #
diff --git a/Tools/TODO b/Tools/TODO
new file mode 100644
index 000000000..d6b419d24
--- /dev/null
+++ b/Tools/TODO
@@ -0,0 +1,2 @@
+- Try reversing cw-wound strips rather than calling glFrontFace() in the 
+  display list.
diff --git a/Tools/make.inc b/Tools/make.inc
index 47b06d67b..da1c732bc 100644
--- a/Tools/make.inc
+++ b/Tools/make.inc
@@ -25,7 +25,7 @@
 #---------------------------------------------------------------------------
 
 
-VERSION = 0.01
+VERSION = 0.02
 
 #---------------------------------------------------------------------------
 # Choose your weapons
@@ -120,6 +120,9 @@ FG_CFLAGS = $(GLOBAL_CFLAGS)
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1997/12/10 01:18:26  curt
+# Initial revision.
+#
 # Revision 1.1  1997/10/20 19:52:18  curt
 # Initial revision.
 #

From 0e813d878b7fd856a73f26fd4fff0cbe12536141 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 9 Jan 1998 23:03:05 +0000
Subject: [PATCH 016/283] Restructured to split 1deg x 1deg dem's into 64
 subsections.

---
 FixNode/fixnode.c | 22 ++++++++++------
 FixNode/main.c    | 67 ++++++++++++++++++++++++++++++++++++++++-------
 FixNode/triload.c | 35 +++++++------------------
 FixNode/triload.h |  9 ++++---
 FixObj/main.c     | 18 +++++++++----
 FixObj/obj.c      | 32 ++++++++++------------
 FixObj/obj.h      |  9 ++++---
 Tools/README      | 18 ++++++++-----
 Tri2obj/depend    |  7 ++---
 Tri2obj/tri2obj.c | 16 +++++------
 Triangle/Makefile |  2 +-
 11 files changed, 145 insertions(+), 90 deletions(-)

diff --git a/FixNode/fixnode.c b/FixNode/fixnode.c
index d3feb16c5..8c3aee33a 100644
--- a/FixNode/fixnode.c
+++ b/FixNode/fixnode.c
@@ -26,6 +26,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "fixnode.h"
 #include "../Dem2node/mesh.h"
@@ -33,8 +34,8 @@
 
 
 /* load the node information */
-void fixnodes(char *basename, struct MESH *m) {
-    char file[256];
+void fixnodes(char *filename, struct MESH *m) {
+    char toname[256];
     FILE *fd;
     int i;
 
@@ -55,12 +56,14 @@ void fixnodes(char *basename, struct MESH *m) {
 	       nodes[i][1], nodes[i][2]); */
     }
 
-    strcpy(file, basename);
-    strcat(file, ".1.node");
 
-    printf("Overwriting original node file: %s\n", file);
+    sprintf(toname, "%s.orig", filename);
+    printf("Moving %s to %s\n", filename, toname);
+    rename(filename, toname);
 
-    fd = fopen(file, "w");
+    printf("Saving new node file: %s\n", filename);
+
+    fd = fopen(filename, "w");
 
     fprintf(fd, "%d 2 1 0\n", nodecount);
 
@@ -74,9 +77,12 @@ void fixnodes(char *basename, struct MESH *m) {
 
 
 /* $Log$
-/* Revision 1.2  1997/12/02 13:12:07  curt
-/* Updated to fix every node.
+/* Revision 1.3  1998/01/09 23:03:08  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.2  1997/12/02 13:12:07  curt
+ * Updated to fix every node.
+ *
  * Revision 1.1  1997/11/27 00:17:33  curt
  * Initial revision.
  *
diff --git a/FixNode/main.c b/FixNode/main.c
index 7ebd5d7e5..002c495cf 100644
--- a/FixNode/main.c
+++ b/FixNode/main.c
@@ -24,36 +24,85 @@
  */
 
 
+#include <dirent.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
 
 #include "../Dem2node/demparse.h"
 #include "fixnode.h"
 #include "triload.h"
 
 
+/* Original DEM which is used to interpolate z values */
+struct MESH dem_mesh;
+
+
+/* find all the matching files in the specified directory and fix them */
+void process_files(char *root_path) {
+    DIR *d;
+    struct dirent *de;
+    char file_path[256];
+    char *ptr;
+    int len;
+
+    if ( (d = opendir(root_path)) == NULL ) {
+        printf("cannot open directory '%s'.", root_path);
+	exit(-1);
+    }
+
+    while ( (de = readdir(d)) != NULL ) {
+	len = strlen(de->d_name);
+	if ( len > 7 ) {
+	    ptr = de->d_name;
+	    ptr += (len - 7);
+	    /* printf("--> %s \n", ptr); */
+
+	    if ( strcmp(ptr, ".1.node") == 0 ) {
+		strcpy(file_path, root_path);
+		strcat(file_path, "/");
+		strcat(file_path, de->d_name);
+		printf("File = %s\n", file_path);
+
+		/* load the input data files */
+		triload(file_path);
+
+		fixnodes(file_path, &dem_mesh);
+	    }
+	}
+    }
+}
+
+
+/* main */
 int main(int argc, char **argv) {
-    char basename[256];
-    struct MESH dem_mesh;
+    char demfile[256], root_path[256];
 
-    strcpy(basename, argv[1]);
+    if ( argc != 3 ) {
+	printf("Usage %s demfile root_path\n", argv[0]);
+	exit(-1);
+    }
 
-    /* load the input data files */
-    triload(basename);
+    strcpy(demfile, argv[1]);
+    strcpy(root_path, argv[2]);
 
     /* load the corresponding dem file so we can interpolate elev values */
-    dem_parse(basename, &dem_mesh);
+    dem_parse(demfile, &dem_mesh);
 
-    fixnodes(basename, &dem_mesh);
+    /* process all the *.1.node files in the specified directory */
+    process_files(root_path);
 
     return(0);
 }
 
 
 /* $Log$
-/* Revision 1.2  1997/12/02 13:12:07  curt
-/* Updated to fix every node.
+/* Revision 1.3  1998/01/09 23:03:08  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.2  1997/12/02 13:12:07  curt
+ * Updated to fix every node.
+ *
  * Revision 1.1  1997/11/27 00:17:34  curt
  * Initial revision.
  *
diff --git a/FixNode/triload.c b/FixNode/triload.c
index 2d6d670d7..f0510bd27 100644
--- a/FixNode/triload.c
+++ b/FixNode/triload.c
@@ -30,37 +30,19 @@
 #include "triload.h"
 
 
-int origcount;
 int nodecount;
 double nodes[MAX_NODES][3];
 
 
 /* load the node information */
-void triload(char *basename) {
-    char origname[256], nodename[256];
-    FILE *orig, *node;
+void triload(char *filename) {
+    FILE *node;
     int dim, junk1, junk2;
     int i;
 
-    strcpy(origname, basename);
-    strcat(origname, ".node");
-
-    strcpy(nodename, basename);
-    strcat(nodename, ".1.node");
-
-    /* open original node file to see number of original nodes */
-
-    printf("Checking original node file:  %s ...\n", origname);
-    if ( (orig = fopen(origname, "r")) == NULL ) {
-	printf("Cannot open file '%s'\n", origname);
-	exit(-1);
-    }
-    fscanf(orig, "%d %d %d %d", &origcount, &dim, &junk1, &junk2);
-    printf("    Found %d nodes\n", origcount);
-
-    printf("Loading node file:  %s ...\n", nodename);
-    if ( (node = fopen(nodename, "r")) == NULL ) {
-	printf("Cannot open file '%s'\n", nodename);
+    printf("Loading node file:  %s ...\n", filename);
+    if ( (node = fopen(filename, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", filename);
 	exit(-1);
     }
 
@@ -85,7 +67,10 @@ void triload(char *basename) {
 
 
 /* $Log$
-/* Revision 1.1  1997/11/27 00:17:35  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/09 23:03:09  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.1  1997/11/27 00:17:35  curt
+ * Initial revision.
+ *
  */
diff --git a/FixNode/triload.h b/FixNode/triload.h
index 058c01869..2d84f8e74 100644
--- a/FixNode/triload.h
+++ b/FixNode/triload.h
@@ -36,7 +36,7 @@
 #define MAX_TRIS  400000
 
 
-extern int origcount, nodecount, tricount;
+extern int nodecount, tricount;
 double nodes[MAX_NODES][3];
 
 
@@ -48,7 +48,10 @@ void triload(char *basename);
 
 
 /* $Log$
-/* Revision 1.1  1997/11/27 00:17:35  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/09 23:03:09  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.1  1997/11/27 00:17:35  curt
+ * Initial revision.
+ *
  */
diff --git a/FixObj/main.c b/FixObj/main.c
index 0a499f1f9..bb20a0e37 100644
--- a/FixObj/main.c
+++ b/FixObj/main.c
@@ -29,19 +29,27 @@
 
 
 int main(int argc, char **argv) {
-    char basename[256];
+    char infile[256], outfile[256];
 
-    strcpy(basename, argv[1]);
+    if ( argc != 3 ) {
+	printf("Usage %s: infile outfile\n", argv[0]);
+    }
+
+    strcpy(infile, argv[1]);
+    strcpy(outfile, argv[2]);
 
     /* load the input data files */
-    obj_fix(basename);
+    obj_fix(infile, outfile);
 
     return(0);
 }
 
 
 /* $Log$
-/* Revision 1.1  1997/12/08 19:28:54  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/09 23:03:12  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.1  1997/12/08 19:28:54  curt
+ * Initial revision.
+ *
  */
diff --git a/FixObj/obj.c b/FixObj/obj.c
index 55201f0fd..19b87d4b1 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -63,7 +63,7 @@ void list_add(int *list, int *list_ptr, int node) {
     list[*list_ptr] = node;
     *list_ptr += 1;
 
-    printf("list pointer = %d  adding %d\n", *list_ptr, node); 
+    /* printf("list pointer = %d  adding %d\n", *list_ptr, node); */
 }
 
 
@@ -84,7 +84,7 @@ void dump_list(int *list, int list_ptr) {
 
 	/* dump header */
 	fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]);
-	printf("t %d %d %d\n", list[i], list[i+1], list[i+2]);
+	/* printf("t %d %d %d\n", list[i], list[i+1], list[i+2]); */
 	i += 3;
 
 	/* dump rest of strip (until -1) */
@@ -139,26 +139,19 @@ double check_cur_face(int n1, int n2, int n3) {
 
 
 /* Load a .obj file */
-void obj_fix(char *basename) {
+void obj_fix(char *infile, char *outfile) {
     char line[256];
-    char inpath[256], outpath[256];
     double dot_prod;
     int first, ncount, vncount, n1, n2, n3, n4;
     int is_ccw;
 
-    strcpy(inpath, basename);
-    strcat(inpath, ".obj");
-
-    strcpy(outpath, basename);
-    strcat(outpath, ".1.obj");
-
-    if ( (in = fopen(inpath, "r")) == NULL ) {
-	printf("Cannot open file: %s\n", inpath);
+    if ( (in = fopen(infile, "r")) == NULL ) {
+	printf("Cannot open file: %s\n", infile);
 	exit(-1);
     }
 
-    if ( (out = fopen(outpath, "w")) == NULL ) {
-	printf("Cannot open file: %s\n", outpath);
+    if ( (out = fopen(outfile, "w")) == NULL ) {
+	printf("Cannot open file: %s\n", outfile);
 	exit(-1);
     }
 
@@ -169,7 +162,7 @@ void obj_fix(char *basename) {
     ncount = 1;
     vncount = 1;
 
-    printf("Reading file:  %s\n", inpath);
+    printf("Reading file:  %s\n", infile);
 
     while ( fgets(line, 250, in) != NULL ) {
 	if ( line[0] == '#' ) {
@@ -274,7 +267,7 @@ void obj_fix(char *basename) {
 		}
 	    }
 	} else {
-	    printf("Unknown line in %s = %s\n", inpath, line);
+	    printf("Unknown line in %s = %s\n", infile, line);
 	}
     }
 
@@ -290,7 +283,10 @@ void obj_fix(char *basename) {
 
 
 /* $Log$
-/* Revision 1.1  1997/12/08 19:28:54  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/09 23:03:12  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.1  1997/12/08 19:28:54  curt
+ * Initial revision.
+ *
  */
diff --git a/FixObj/obj.h b/FixObj/obj.h
index c0ecf801c..54689de06 100644
--- a/FixObj/obj.h
+++ b/FixObj/obj.h
@@ -36,14 +36,17 @@ extern int stack[MAXNODES];
 
 
 /* Load a .obj file */
-void obj_fix(char *basename);
+void obj_fix(char *infile, char *outfile);
 
 
 #endif /* OBJ_H */
 
 
 /* $Log$
-/* Revision 1.1  1997/12/08 19:28:55  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/09 23:03:13  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.1  1997/12/08 19:28:55  curt
+ * Initial revision.
+ *
  */
diff --git a/Tools/README b/Tools/README
index 21133e438..fa4bf7290 100644
--- a/Tools/README
+++ b/Tools/README
@@ -1,15 +1,19 @@
 1.  Start with file.dem
 
-2.  dem2node file tolerance^2 (meters)
+2.  dem2node file.dem tolerance^2 (meters)
 
-    - dem2node file 160000
+    - dem2node file.dem 160000
 
-3.  fixnode file.1
+3.  triangle -q file
 
-4.  tri2obj file.1
+4.  fixnode file
 
-5.  strip file.1.obj
+5.  tri2obj file.1
 
-6.  cp bands.d file.new.obj
+6.  strip file.1.obj
 
-7.  fixobj file.new
+7.  cp bands.d file-new.obj
+
+8.  fixobj file-new
+
+9.  cp file-new.1.obj .../Scenery/...
diff --git a/Tri2obj/depend b/Tri2obj/depend
index 5e652e883..73c133713 100644
--- a/Tri2obj/depend
+++ b/Tri2obj/depend
@@ -1,3 +1,4 @@
-tri2obj.o: tri2obj.c tri2obj.h ../../Src/constants.h ../../Src/types.h \
- ../../Src/Math/fg_geodesy.h ../../Src/Math/mat3.h \
- ../../Src/Math/polar.h ../../Src/Math/../types.h
+tri2obj.o: tri2obj.c tri2obj.h ../../Src/Include/constants.h \
+ ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
+ ../../Src/Math/mat3.h ../../Src/Math/polar.h \
+ ../../Src/Math/../Include/types.h
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 0737899ae..b38b07438 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -29,8 +29,8 @@
 
 #include "tri2obj.h"
 
-#include "../../Src/constants.h"
-#include "../../Src/types.h"
+#include "../../Src/Include/constants.h"
+#include "../../Src/Include/types.h"
 #include "../../Src/Math/fg_geodesy.h"
 #include "../../Src/Math/mat3.h"
 #include "../../Src/Math/polar.h"
@@ -234,10 +234,7 @@ void dump_obj(char *basename) {
     /* dump faces */
     printf("  writing faces\n");
     for ( i = 1; i <= tricount; i++ ) {
-	fprintf(obj, "f %d//%d %d//%d %d//%d\n", 
-		tris[i][0], tris[i][0], 
-		tris[i][1], tris[i][1], 
-		tris[i][2], tris[i][2]);
+	fprintf(obj, "f %d %d %d\n", tris[i][0], tris[i][1], tris[i][2]);
     }
 
     fclose(obj);
@@ -259,9 +256,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.5  1997/12/08 19:17:50  curt
-/* Fixed a type in the normal generation code.
+/* Revision 1.6  1998/01/09 23:03:15  curt
+/* Restructured to split 1deg x 1deg dem's into 64 subsections.
 /*
+ * Revision 1.5  1997/12/08 19:17:50  curt
+ * Fixed a type in the normal generation code.
+ *
  * Revision 1.4  1997/12/02 13:13:32  curt
  * Fixed problem with averaged vertex normals.
  *
diff --git a/Triangle/Makefile b/Triangle/Makefile
index 66afd63cd..cccdf2b1c 100644
--- a/Triangle/Makefile
+++ b/Triangle/Makefile
@@ -83,7 +83,7 @@ TRILIBDEFS = -DTRILIBRARY
 
 # RM should be set to the name of your favorite rm (file deletion program).
 
-RM = /bin/rm
+RM = /bin/rm -f
 
 # The action starts here.
 

From 35b9b8a36072a971bddc9733f8dea1531c7faa25 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 9 Jan 1998 23:06:46 +0000
Subject: [PATCH 017/283] Initial revision.

---
 Tools/process-dem.pl | 218 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 218 insertions(+)
 create mode 100755 Tools/process-dem.pl

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
new file mode 100755
index 000000000..55d870a0b
--- /dev/null
+++ b/Tools/process-dem.pl
@@ -0,0 +1,218 @@
+#!/usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Toplevel script to automate DEM file processing and conversion
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+$| = 1;                         # flush buffers after every write
+
+
+# return the file name root (ending at last ".")
+sub file_root {
+    my($file) = @_;
+    my($pos);
+
+    $pos = rindex($file, ".");
+    return substr($file, 0, $pos);
+}
+
+
+# set the FG_ROOT environment variable if it hasn't already been set.
+if ( $ENV{FG_ROOT} eq "" ) {
+    # look for a file called fgtop as a place marker
+    if ( -e "fgtop" ) {
+        $ENV{FG_ROOT} = ".";
+    } elsif ( -e "../fgtop" ) {
+        $ENV{FG_ROOT} = "..";
+    }
+}
+
+
+# 1.  Start with file.dem
+
+$dem_file = shift(@ARGV);
+$error = shift(@ARGV);
+$error += 0.0;
+
+print "Source file = $dem_file  Error tolerance = $error\n";
+
+if ( $error < 0.5 ) {
+    die "I doubt you'll be happy with an error tolerance as low as $error.\n";
+}
+
+# 2.  dem2node $FG_ROOT dem_file tolerance^2 (meters)
+# 
+#     - dem2node .. dem_file 160000
+#
+#     splits dem file into 64 file.node's which contain the
+#     irregularly fitted vertices
+
+$command = "./Dem2node/demfit $ENV{FG_ROOT} $dem_file $error";
+
+print "Running '$command'\n";
+
+open(OUT, "$command |");
+while ( <OUT> ) {
+    print $_;
+    if ( m/Scenery/ ) {
+	$subdir = $_;
+	$subdir =~ s/Dir = //;
+    }
+}
+close(OUT);
+
+
+# 3.  triangle -q file (Takes file.node and produces file.1.node and
+#                      file.1.ele)
+
+$subdir = "../Scenery/w120n030/w111n033";
+print "Subdirectory for this dem file is $subdir\n";
+
+@FILES = `ls $subdir`;
+foreach $file ( @FILES ) {
+    print $file;
+    chop($file);
+    if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
+	$command = "./Triangle/triangle -q $subdir/$file";
+	print "Running '$command'\n";
+	open(OUT, "$command |");
+	while ( <OUT> ) {
+	    print $_;
+	}
+	close(OUT);
+
+	# remove input file.node
+	unlink("$subdir/$file");
+    }
+}
+
+
+# 4.  fixnode file.dem subdir
+#
+#     Take the original .dem file (for interpolating Z values) and the
+#     subdirecotry containing all the file.1.node's and replace with
+#     fixed file.1.node
+
+$command = "./FixNode/fixnode $dem_file $subdir";
+print "Running '$command'\n";
+open(OUT, "$command |");
+while ( <OUT> ) {
+    print $_;
+}
+close(OUT);
+
+
+# 5.  tri2obj file (.1.node)
+#
+#     Take the file.1.node and file.1.ele and produce file.1.obj
+
+@FILES = `ls $subdir`;
+foreach $file ( @FILES ) {
+    chop($file);
+    if ( $file =~ m/\.1\.node$/ ) {
+	$file =~ s/\.node$//;  # strip off the ".node"
+
+	$command = "./Tri2obj/tri2obj $subdir/$file";
+	print "Running '$command'\n";
+	open(OUT, "$command |");
+	while ( <OUT> ) {
+	    print $_;
+	}
+	close(OUT);
+
+	unlink("$subdir/$file.node");
+	unlink("$subdir/$file.node.orig");
+	unlink("$subdir/$file.ele");
+
+    }
+}
+
+
+# 6.  strip file.1.obj
+# 
+#     Strip the file.1.obj's
+#
+# 7.  cp bands.d file.2.obj
+#
+#     strips produces a file called "bands.d" ... copy this to file.2.obj
+
+@FILES = `ls $subdir`;
+foreach $file ( @FILES ) {
+    chop($file);
+    if ( $file =~ m/\.1\.obj$/ ) {
+	$command = "./Stripe_u/strips $subdir/$file";
+	print "Running '$command'\n";
+	open(OUT, "$command |");
+	while ( <OUT> ) {
+	    print $_;
+	}
+	close(OUT);
+
+	# copy to destination file
+	$newfile = $file;
+	$newfile =~ s/\.1\.obj$//;
+	print "Copying to $subdir/$newfile.2.obj\n";
+	open(IN, "<bands.d");
+	open(OUT, ">$subdir/$newfile.2.obj");
+	while ( <IN> ) {
+	    print OUT $_;
+	}
+	close(IN);
+	close(OUT);
+
+	unlink("$subdir/$file");
+    }
+}
+
+
+# 8.  fixobj file-new
+#
+#     Sort file.2.obj by strip winding
+
+@FILES = `ls $subdir`;
+foreach $file ( @FILES ) {
+    chop($file);
+    if ( $file =~ m/\.2\.obj$/ ) {
+	$newfile = $file;
+	$newfile =~ s/\.2\.obj$/.obj/;
+
+	$command = "./FixObj/fixobj $subdir/$file $subdir/$newfile";
+	print "Running '$command'\n";
+	open(OUT, "$command |");
+	while ( <OUT> ) {
+	    print $_;
+	}
+	close(OUT);
+
+	unlink("$subdir/$file");
+    }
+}
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/01/09 23:06:46  curt
+# Initial revision.
+#

From 1ebd34bbe4275b0bbde1f8bb9807c2fb3e7b0ee6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 12 Jan 1998 02:42:00 +0000
Subject: [PATCH 018/283] Average up to five triangles per vertex instead of
 three.

---
 Tri2obj/tri2obj.c | 43 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index b38b07438..9e4e72b9f 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -83,10 +83,10 @@ void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2,
 
 
 /* return the index of all triangles containing the specified node */
-void find_tris(int n, int *t1, int *t2, int *t3) {
+void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
     int i;
 
-    *t1 = *t2 = *t3 = 0;
+    *t1 = *t2 = *t3 = *t4 = *t5 = 0;
 
     i = 1;
     while ( i <= tricount ) {
@@ -95,8 +95,12 @@ void find_tris(int n, int *t1, int *t2, int *t3) {
 		*t1 = i;
             } else if ( *t2 == 0 ) {
 		*t2 = i;
-	    } else {
+            } else if ( *t3 == 0 ) {
 		*t3 = i;
+            } else if ( *t4 == 0 ) {
+		*t4 = i;
+	    } else {
+		*t5 = i;
 	    }
         }
         i++;
@@ -171,9 +175,9 @@ void triload(char *basename) {
 /* dump in WaveFront .obj format */
 void dump_obj(char *basename) {
     char objname[256];
-    double n1[3], n2[3], n3[3], norm[3], temp;
+    double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
     FILE *obj;
-    int i, t1, t2, t3, count;
+    int i, t1, t2, t3, t4, t5, count;
 
     strcpy(objname, basename);
     strcat(objname, ".obj");
@@ -194,11 +198,13 @@ void dump_obj(char *basename) {
     for ( i = 1; i <= nodecount; i++ ) {
 /* 	printf("Finding normal\n"); */
 
-	find_tris(i, &t1, &t2, &t3);
+	find_tris(i, &t1, &t2, &t3, &t4, &t5);
 
 	n1[0] = n1[1] = n1[2] = 0.0;
 	n2[0] = n2[1] = n2[2] = 0.0;
 	n3[0] = n3[1] = n3[2] = 0.0;
+	n4[0] = n4[1] = n4[2] = 0.0;
+	n5[0] = n5[1] = n5[2] = 0.0;
 
 	count = 1;
 	calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], nodes[tris[t1][2]], 
@@ -216,11 +222,23 @@ void dump_obj(char *basename) {
 	    count = 3;
 	}
 
+	if ( t4 > 0 ) {
+	    calc_normal(nodes[tris[t4][0]], nodes[tris[t4][1]],
+			nodes[tris[t4][2]], n4);
+	    count = 4;
+	}
+
+	if ( t5 > 0 ) {
+	    calc_normal(nodes[tris[t5][0]], nodes[tris[t5][1]],
+			nodes[tris[t5][2]], n5);
+	    count = 5;
+	}
+
 /* 	printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
 
-	norm[0] = ( n1[0] + n2[0] + n3[0] ) / (double)count;
-	norm[1] = ( n1[1] + n2[1] + n3[1] ) / (double)count;
-	norm[2] = ( n1[2] + n2[2] + n3[2] ) / (double)count;
+	norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count;
+	norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count;
+	norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count;
 	
 /* 	printf("  count = %d\n", count); */
 /* 	printf("  Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);*/
@@ -256,9 +274,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.6  1998/01/09 23:03:15  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
+/* Revision 1.7  1998/01/12 02:42:00  curt
+/* Average up to five triangles per vertex instead of three.
 /*
+ * Revision 1.6  1998/01/09 23:03:15  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
  * Revision 1.5  1997/12/08 19:17:50  curt
  * Fixed a type in the normal generation code.
  *

From 4ce57e5d5aae4e1d5fbded2df51488b89b4998e6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 12 Jan 1998 20:42:07 +0000
Subject: [PATCH 019/283] Working on fitting tiles together in a seamless
 manner.

---
 Tools/TODO           |  4 ++++
 Tools/process-dem.pl | 42 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/Tools/TODO b/Tools/TODO
index d6b419d24..6f1f342ed 100644
--- a/Tools/TODO
+++ b/Tools/TODO
@@ -1,2 +1,6 @@
 - Try reversing cw-wound strips rather than calling glFrontFace() in the 
   display list.
+
+- Generate a face adjacency matrix
+
+- Split areas into smaller chunks
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 55d870a0b..7a9842a42 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -124,7 +124,43 @@ while ( <OUT> ) {
 close(OUT);
 
 
-# 5.  tri2obj file (.1.node)
+# 4.1 findedges file (.1.node) (.1.ele)
+
+#     Extract the edge vertices (in original geodetic coordinates) and
+#     normals (in cartesian coordinates) and save them in something
+#     very close to the .obj format as file.north, file.south,
+#     file.east file.west.
+
+@FILES = `ls $subdir`;
+foreach $file ( @FILES ) {
+    chop($file);
+    if ( $file =~ m/\.1\.node$/ ) {
+	$file =~ s/\.node$//;  # strip off the ".node"
+
+	$command = "./FindEdges/findedges $subdir/$file";
+	print "Running '$command'\n";
+	open(OUT, "$command |");
+	while ( <OUT> ) {
+	    print $_;
+	}
+	close(OUT);
+    }
+}
+
+
+exit(1);
+
+
+# 4.2 read in tri files (node/ele) skipping edges, read edges out of
+#     edge files, save including proper shared edges (as node/ele)
+#     files.  If my edge and adjacent edge both exist, use other,
+#     delete mine.  If only mine exists, use it.
+
+
+# 4.3 Retriangulate fixed up files (without -q option)
+
+
+# 5.  tri2obj file (.1.node) (.1.ele)
 #
 #     Take the file.1.node and file.1.ele and produce file.1.obj
 
@@ -145,7 +181,6 @@ foreach $file ( @FILES ) {
 	unlink("$subdir/$file.node");
 	unlink("$subdir/$file.node.orig");
 	unlink("$subdir/$file.ele");
-
     }
 }
 
@@ -213,6 +248,9 @@ foreach $file ( @FILES ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/01/12 20:42:08  curt
+# Working on fitting tiles together in a seamless manner.
+#
 # Revision 1.1  1998/01/09 23:06:46  curt
 # Initial revision.
 #

From 419b95f5646b8d170b161a01e271c5426960f0c7 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 14 Jan 1998 02:11:30 +0000
Subject: [PATCH 020/283] Initial revision.

---
 SplitTris/Makefile    |  71 ++++++
 SplitTris/depend      |   4 +
 SplitTris/splittris.c | 492 ++++++++++++++++++++++++++++++++++++++++++
 SplitTris/splittris.h |  56 +++++
 4 files changed, 623 insertions(+)
 create mode 100644 SplitTris/Makefile
 create mode 100644 SplitTris/depend
 create mode 100644 SplitTris/splittris.c
 create mode 100644 SplitTris/splittris.h

diff --git a/SplitTris/Makefile b/SplitTris/Makefile
new file mode 100644
index 000000000..b2cb41531
--- /dev/null
+++ b/SplitTris/Makefile
@@ -0,0 +1,71 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+TARGET = splittris
+
+CFILES = splittris.c ../../Src/Scenery/tileutils.c
+OFILES = $(CFILES:.c=.o)
+
+
+include ../make.inc
+
+
+CFLAGS = $(FG_CFLAGS)
+
+
+#---------------------------------------------------------------------------
+# Primary Targets
+#---------------------------------------------------------------------------
+
+all: $(TARGET)
+
+$(TARGET): $(OFILES)
+	$(CC) $(OFILES) -o $(TARGET) ../../Src/Math/libMath.a -lm
+
+clean:
+	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
+
+realclean: clean
+
+
+#---------------------------------------------------------------------------
+# Secondary Targets
+#---------------------------------------------------------------------------
+
+makedepend:
+	$(CC) -MM *.c > depend
+
+include depend
+
+splittris.o: splittris.c
+	$(CC) $(CFLAGS) -c splittris.c -o $@
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/01/14 02:11:30  curt
+# Initial revision.
+#
diff --git a/SplitTris/depend b/SplitTris/depend
new file mode 100644
index 000000000..73c133713
--- /dev/null
+++ b/SplitTris/depend
@@ -0,0 +1,4 @@
+tri2obj.o: tri2obj.c tri2obj.h ../../Src/Include/constants.h \
+ ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
+ ../../Src/Math/mat3.h ../../Src/Math/polar.h \
+ ../../Src/Math/../Include/types.h
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
new file mode 100644
index 000000000..bfef51689
--- /dev/null
+++ b/SplitTris/splittris.c
@@ -0,0 +1,492 @@
+/* splittris.c -- read in a .ele/.node file pair generated by the
+ *                triangle program and output a simple Wavefront .obj
+ *                file for the north, south, east, and west edge
+ *                verticies ... including the normals.
+ *
+ * Written by Curtis Olson, started January 1998.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file) */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>   /* for atoi() */
+#include <string.h>
+#include <sys/stat.h> /* for stat() */
+#include <unistd.h>   /* for stat() */
+
+#include "splittris.h"
+
+#include "../../Src/Include/constants.h"
+#include "../../Src/Include/types.h"
+#include "../../Src/Math/fg_geodesy.h"
+#include "../../Src/Math/mat3.h"
+#include "../../Src/Math/polar.h"
+#include "../../Src/Scenery/tileutils.h"
+
+
+int nodecount, tricount;
+double xmin, xmax, ymin, ymax;
+
+double nodes_orig[MAX_NODES][3];
+int tris[MAX_TRIS][3];
+int new_tris[MAX_TRIS][3];
+
+struct fgCartesianPoint nodes_cart[MAX_NODES];
+
+long int ne_index, nw_index, sw_index, se_index;
+long int north_index, south_index, east_index, west_index;
+
+/* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
+ * a cartesian point */
+struct fgCartesianPoint geod_to_cart(double geod[3]) {
+    struct fgCartesianPoint p;
+    double gc_lon, gc_lat, sl_radius;
+
+    /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
+	   geod[0], geod[1], geod[2]); */
+
+    gc_lon = geod[0]*ARCSEC_TO_RAD;
+    fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
+
+    /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
+	   gc_lat, sl_radius+geod[2]); */
+
+    p = fgPolarToCart(gc_lon, gc_lat, sl_radius+geod[2]);
+    
+    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", p.x, p.y, p.z); */
+
+    return(p);
+}
+
+
+/* given three points defining a triangle, calculate the normal */
+void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2, 
+		 struct fgCartesianPoint p3, double normal[3])
+{
+    double v1[3], v2[3];
+    float temp;
+
+    v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
+    v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
+
+    MAT3cross_product(normal, v1, v2);
+    MAT3_NORMALIZE_VEC(normal,temp);
+
+/*  printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
+}
+
+
+/* return the file base name ( foo/bar/file.ext = file.ext ) */
+void extract_file(char *in, char *base) {
+    int len, i;
+
+    len = strlen(in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    in += (i + 1);
+    strcpy(base, in);
+}
+
+
+/* return the file path name ( foo/bar/file.ext = foo/bar ) */
+void extract_path(char *in, char *base) {
+    int len, i;
+
+    len = strlen(in);
+    strcpy(base, in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    base[i] = '\0';
+}
+
+
+/* return the index of all triangles containing the specified node */
+void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
+    int i;
+
+    *t1 = *t2 = *t3 = *t4 = *t5 = 0;
+
+    i = 1;
+    while ( i <= tricount ) {
+        if ( (n == tris[i][0]) || (n == tris[i][1]) || (n == tris[i][2]) ) {
+            if ( *t1 == 0 ) {
+		*t1 = i;
+            } else if ( *t2 == 0 ) {
+		*t2 = i;
+            } else if ( *t3 == 0 ) {
+		*t3 = i;
+            } else if ( *t4 == 0 ) {
+		*t4 = i;
+	    } else {
+		*t5 = i;
+	    }
+        }
+        i++;
+    }
+}
+
+
+/* Initialize a new mesh structure */
+void triload(char *basename) {
+    char nodename[256], elename[256];
+    FILE *node, *ele;
+    int dim, junk1, junk2;
+    int i;
+
+    strcpy(nodename, basename);
+    strcat(nodename, ".node");
+    strcpy(elename, basename);
+    strcat(elename, ".ele");
+
+    printf("Loading node file:  %s ...\n", nodename);
+    if ( (node = fopen(nodename, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", nodename);
+	exit(-1);
+    }
+
+    fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
+
+    if ( nodecount > MAX_NODES - 1 ) {
+	printf("Error, too many nodes, need to increase array size\n");
+	exit(-1);
+    } else {
+	printf("    Expecting %d nodes\n", nodecount);
+    }
+
+    for ( i = 1; i <= nodecount; i++ ) {
+	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
+	       &nodes_orig[i][0], &nodes_orig[i][1], &nodes_orig[i][2], &junk2);
+	/* printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); */
+	nodes_cart[i] = geod_to_cart(nodes_orig[i]);
+	/* printf("%d %.2f %.2f %.2f\n", 
+	       junk1, nodes_cart[i].x, nodes_cart[i].y, nodes_cart[i].z); */
+
+	if ( i == 1 ) {
+	    xmin = xmax = nodes_orig[i][0];
+	    ymin = ymax = nodes_orig[i][1];
+	} else {
+	    if ( nodes_orig[i][0] < xmin ) {
+		xmin = nodes_orig[i][0];
+	    }
+	    if ( nodes_orig[i][0] > xmax ) {
+		xmax = nodes_orig[i][0];
+	    }
+	    if ( nodes_orig[i][1] < ymin ) {
+		ymin = nodes_orig[i][1];
+	    }
+	    if ( nodes_orig[i][1] > ymax ) {
+		ymax = nodes_orig[i][1];
+	    }
+	}
+    }
+
+    fclose(node);
+
+    printf("Loading element file:  %s ...\n", elename);
+    if ( (ele = fopen(elename, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", elename);
+	exit(-1);
+    }
+
+    fscanf(ele, "%d %d %d", &tricount, &junk1, &junk2);
+
+    if ( tricount > MAX_TRIS - 1 ) {
+	printf("Error, too many elements, need to increase array size\n");
+	exit(-1);
+    } else {
+	printf("    Expecting %d elements\n", tricount);
+    }
+
+    for ( i = 1; i <= tricount; i++ ) {
+	fscanf(ele, "%d %d %d %d\n", &junk1, 
+	       &tris[i][0], &tris[i][1], &tris[i][2]);
+	/* printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
+    }
+
+    fclose(ele);
+}
+
+
+/* check if a file exists */
+int file_exists(char *file) {
+    struct stat stat_buf;
+
+    result = stat(file, &stat_buf);
+
+    if ( result != 0 ) {
+	/* stat failed, no file */
+	return(0);
+    } else {
+	/* stat succeeded, file exists */
+	return(1);
+    }
+}
+
+
+/* my custom file opening routine ... don't open if a shared edge or
+ * vertex alread exists */
+FILE *my_open(char *basename, char *basepath, char *ext) {
+    FILE *fp;
+    char filename[256];
+
+    /* create the output file name */
+    strcpy(filename, basename);
+    strcpy(filename, ext);
+
+    /* check if a shared object already exist from a different tile */
+
+    if ( 0 ) {
+	/* not an actual file open error, but we've already got the
+         * shared edge, so we don't want to create another one */
+	return(NULL);
+    } else {
+	/* open the file */
+	fp = fopen(filename, "w");
+	return(fp);
+    }
+}
+
+
+/* dump in WaveFront .obj format */
+void dump_obj(char *basename, char *basepath) {
+    char sw_name[256], se_name[256], ne_name[256], nw_name[256];
+    char north_name[256], south_name[256], east_name[256], west_name[256];
+    char body_name[256];
+    double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
+    FILE *sw, *se, *ne, *nw, *north, *south, *east, *west, *body;
+    int i, t1, t2, t3, t4, t5, count;
+
+    sw = my_open(basename, basepath, ".sw");
+    se = my_open(basename, basepath, ".se");
+    ne = my_open(basename, basepath, ".ne");
+    nw = my_open(basename, basepath, ".nw");
+
+    north = my_open(basename, basepath, ".north");
+    south = my_open(basename, basepath, ".south");
+    east = my_open(basename, basepath, ".east");
+    west = my_open(basename, basepath, ".west");
+
+    body = my_open(basename, basepath, ".body");
+
+    printf("Dumping edges file basename:  %s ...\n", basename);
+
+    sw = fopen(sw_name, "w");
+    se = fopen(se_name, "w");
+    ne = fopen(ne_name, "w");
+    nw = fopen(nw_name, "w");
+
+    north = fopen(north_name, "w");
+    south = fopen(south_name, "w");
+    east = fopen(east_name, "w");
+    west = fopen(west_name, "w");
+
+    body = fopen(body_name, "w");
+
+    /* dump vertices */
+    printf("  writing vertices\n");
+    for ( i = 1; i <= nodecount; i++ ) {
+
+	if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) && 
+	     (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+	    fprintf(sw, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON) ) {
+	    fprintf(se, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON)) {
+	    fprintf(ne, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+	    fprintf(nw, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else if ( fabs(nodes_orig[i][0] - xmin) < FG_EPSILON ) {
+	    fprintf(west, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else if ( fabs(nodes_orig[i][0] - xmax) < FG_EPSILON ) {
+	    fprintf(east, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else if ( fabs(nodes_orig[i][1] - ymin) < FG_EPSILON ) {
+	    fprintf(south, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else if ( fabs(nodes_orig[i][1] - ymax) < FG_EPSILON ) {
+	    fprintf(north, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	} else {
+	    fprintf(body, "geodn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	}
+
+    }
+
+    printf("  calculating and writing normals\n");
+    /* calculate and generate normals */
+    for ( i = 1; i <= nodecount; i++ ) {
+/* 	printf("Finding normal\n"); */
+
+	find_tris(i, &t1, &t2, &t3, &t4, &t5);
+
+	n1[0] = n1[1] = n1[2] = 0.0;
+	n2[0] = n2[1] = n2[2] = 0.0;
+	n3[0] = n3[1] = n3[2] = 0.0;
+	n4[0] = n4[1] = n4[2] = 0.0;
+	n5[0] = n5[1] = n5[2] = 0.0;
+
+	count = 1;
+	calc_normal(nodes_cart[tris[t1][0]], nodes_cart[tris[t1][1]], 
+		    nodes_cart[tris[t1][2]], n1);
+
+	if ( t2 > 0 ) {
+	    calc_normal(nodes_cart[tris[t2][0]], nodes_cart[tris[t2][1]], 
+			nodes_cart[tris[t2][2]], n2);
+	    count = 2;
+	}
+
+	if ( t3 > 0 ) {
+	    calc_normal(nodes_cart[tris[t3][0]], nodes_cart[tris[t3][1]],
+			nodes_cart[tris[t3][2]], n3);
+	    count = 3;
+	}
+
+	if ( t4 > 0 ) {
+	    calc_normal(nodes_cart[tris[t4][0]], nodes_cart[tris[t4][1]],
+			nodes_cart[tris[t4][2]], n4);
+	    count = 4;
+	}
+
+	if ( t5 > 0 ) {
+	    calc_normal(nodes_cart[tris[t5][0]], nodes_cart[tris[t5][1]],
+			nodes_cart[tris[t5][2]], n5);
+	    count = 5;
+	}
+
+/* 	printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
+
+	norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count;
+	norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count;
+	norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count;
+	
+/* 	printf("  count = %d\n", count); */
+/* 	printf("  Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);*/
+	MAT3_NORMALIZE_VEC(norm, temp);
+/* 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
+/* 	       norm[0], norm[1], norm[2]); */
+	
+	if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) && 
+	     (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+	    fprintf(sw, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	} else if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON) ) {
+	    fprintf(se, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON)) {
+	    fprintf(ne, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+	    fprintf(nw, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	} else if ( fabs(nodes_orig[i][0] - xmin) < FG_EPSILON ) {
+	    fprintf(west, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	} else if ( fabs(nodes_orig[i][0] - xmax) < FG_EPSILON ) {
+	    fprintf(east, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	} else if ( fabs(nodes_orig[i][1] - ymin) < FG_EPSILON ) {
+	    fprintf(south, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	} else if ( fabs(nodes_orig[i][1] - ymax) < FG_EPSILON ) {
+	    fprintf(north, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	}
+    }
+
+    fclose(sw);
+    fclose(se);
+    fclose(ne);
+    fclose(nw);
+
+    fclose(north);
+    fclose(south);
+    fclose(east);
+    fclose(west);
+}
+
+
+int main(int argc, char **argv) {
+    char basename[256], basepath[256], temp[256];
+    struct bucket p1, p2;
+    long int index;
+    int len;
+
+    strcpy(basename, argv[1]);
+
+    /* find the base path of the file */
+    extract_path(basename, basepath);
+    extract_path(basepath, basepath);
+    extract_path(basepath, basepath);
+    printf("%s\n", basepath);
+
+    /* find the index of the current file */
+    extract_file(basename, temp);
+    len = strlen(temp);
+    if ( len >= 2 ) {
+	temp[len-2] = '\0';
+    }
+    index = atoi(temp);
+    printf("%ld\n", index);
+    parse_index(index, &p1);
+
+    /* generate the indexes of the neighbors */
+    offset_bucket(&p1, &p2,  1,  1); ne_index = gen_index(&p2);
+    offset_bucket(&p1, &p2,  1, -1); nw_index = gen_index(&p2);
+    offset_bucket(&p1, &p2, -1,  1); se_index = gen_index(&p2);
+    offset_bucket(&p1, &p2, -1, -1); sw_index = gen_index(&p2);
+
+    offset_bucket(&p1, &p2,  0,  1); north_index = gen_index(&p2);
+    offset_bucket(&p1, &p2,  0, -1); south_index = gen_index(&p2);
+    offset_bucket(&p1, &p2,  1,  0); east_index  = gen_index(&p2);
+    offset_bucket(&p1, &p2, -1,  1); west_index  = gen_index(&p2);
+
+    printf("Corner indexes = %ld %ld %ld %ld\n", 
+	   ne_index, nw_index, sw_index, se_index);
+    printf("Edge indexes = %ld %ld %ld %ld\n",
+	   north_index, south_index, east_index, west_index);
+
+    /* load the input data files */
+    triload(basename);
+
+    /* dump in WaveFront .obj format */
+    dump_obj(basename, basepath);
+
+    return(0);
+}
+
+
+/* $Log$
+/* Revision 1.1  1998/01/14 02:11:31  curt
+/* Initial revision.
+/*
+ */
diff --git a/SplitTris/splittris.h b/SplitTris/splittris.h
new file mode 100644
index 000000000..cb20583c0
--- /dev/null
+++ b/SplitTris/splittris.h
@@ -0,0 +1,56 @@
+/* splittris.h -- read in a .ele/.node file pair generated by the triangle 
+ *                program and output edge vertices w/ normals.
+ *
+ * Written by Curtis Olson, started January 1998.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#ifndef FINDEDGES_H
+#define FINDEDGES_H
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+#define MAX_NODES 200000
+#define MAX_TRIS  400000
+
+
+extern int nodecount, tricount;
+extern struct fgCartesianPoint nodes[MAX_NODES];
+extern int tris[MAX_TRIS][3];
+extern int new_tris[MAX_TRIS][3];
+
+
+/* Initialize a new mesh structure */
+void triload(char *basename);
+
+
+#endif /* FINDEDGES_H */
+
+
+/* $Log$
+/* Revision 1.1  1998/01/14 02:11:32  curt
+/* Initial revision.
+/*
+ */

From 9f8ffba6a7101a44f0e95b718acd0c15981244d2 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 14 Jan 1998 02:15:51 +0000
Subject: [PATCH 021/283] Updated front end script to keep plugging away on
 tile fitting.

---
 Tools/TODO           |  19 +++-
 Tools/process-dem.pl | 239 ++++++++++++++++++++++++-------------------
 2 files changed, 149 insertions(+), 109 deletions(-)

diff --git a/Tools/TODO b/Tools/TODO
index 6f1f342ed..12d620269 100644
--- a/Tools/TODO
+++ b/Tools/TODO
@@ -1,6 +1,17 @@
-- Try reversing cw-wound strips rather than calling glFrontFace() in the 
-  display list.
+--------------------------------------------------------------------------
+| Done
+--------------------------------------------------------------------------
 
-- Generate a face adjacency matrix
+1/10/98 -  Split areas into smaller tiles
 
-- Split areas into smaller chunks
+
+--------------------------------------------------------------------------
+| Todo 
+--------------------------------------------------------------------------
+
+1/12/98 -  Try reversing cw-wound strips rather than calling glFrontFace() 
+           in the display list.
+
+1/12/98 -  Generate a face adjacency matrix
+
+1/12/98 -  Don't create shared corners or edges if one already exists.
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 7a9842a42..29b95637b 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -28,6 +28,15 @@
 
 $| = 1;                         # flush buffers after every write
 
+$do_demfit = 0;
+$do_triangle_1 = 0;
+$do_fixnode = 0;
+$do_splittris = 1;
+
+$do_tri2obj = 0;
+$do_strips = 0;
+$do_fixobj = 0;
+
 
 # return the file name root (ending at last ".")
 sub file_root {
@@ -69,20 +78,21 @@ if ( $error < 0.5 ) {
 #     splits dem file into 64 file.node's which contain the
 #     irregularly fitted vertices
 
-$command = "./Dem2node/demfit $ENV{FG_ROOT} $dem_file $error";
+if ( $do_demfit ) {
+    $command = "./Dem2node/demfit $ENV{FG_ROOT} $dem_file $error";
 
-print "Running '$command'\n";
+    print "Running '$command'\n";
 
-open(OUT, "$command |");
-while ( <OUT> ) {
-    print $_;
-    if ( m/Scenery/ ) {
-	$subdir = $_;
-	$subdir =~ s/Dir = //;
+    open(OUT, "$command |");
+    while ( <OUT> ) {
+	print $_;
+	if ( m/Scenery/ ) {
+	    $subdir = $_;
+	    $subdir =~ s/Dir = //;
+	}
     }
+    close(OUT);
 }
-close(OUT);
-
 
 # 3.  triangle -q file (Takes file.node and produces file.1.node and
 #                      file.1.ele)
@@ -90,68 +100,78 @@ close(OUT);
 $subdir = "../Scenery/w120n030/w111n033";
 print "Subdirectory for this dem file is $subdir\n";
 
-@FILES = `ls $subdir`;
-foreach $file ( @FILES ) {
-    print $file;
-    chop($file);
-    if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
-	$command = "./Triangle/triangle -q $subdir/$file";
-	print "Running '$command'\n";
-	open(OUT, "$command |");
-	while ( <OUT> ) {
-	    print $_;
-	}
-	close(OUT);
+if ( $do_triangle_1 ) {
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	print $file;
+	chop($file);
+	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
+	    $command = "./Triangle/triangle -q $subdir/$file";
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
 
-	# remove input file.node
-	unlink("$subdir/$file");
+	    # remove input file.node
+	    unlink("$subdir/$file");
+	}
     }
 }
 
-
 # 4.  fixnode file.dem subdir
 #
 #     Take the original .dem file (for interpolating Z values) and the
 #     subdirecotry containing all the file.1.node's and replace with
 #     fixed file.1.node
 
-$command = "./FixNode/fixnode $dem_file $subdir";
-print "Running '$command'\n";
-open(OUT, "$command |");
-while ( <OUT> ) {
-    print $_;
+if ( $do_fixnode ) {
+    $command = "./FixNode/fixnode $dem_file $subdir";
+    print "Running '$command'\n";
+    open(OUT, "$command |");
+    while ( <OUT> ) {
+	print $_;
+    }
+    close(OUT);
 }
-close(OUT);
 
 
-# 4.1 findedges file (.1.node) (.1.ele)
+# 4.1 splittris file (.1.node) (.1.ele)
 
-#     Extract the edge vertices (in original geodetic coordinates) and
-#     normals (in cartesian coordinates) and save them in something
-#     very close to the .obj format as file.north, file.south,
-#     file.east file.west.
+#     Extract the corner, edge, and body vertices (in original
+#     geodetic coordinates) and normals (in cartesian coordinates) and
+#     save them in something very close to the .obj format as file.se,
+#     file.sw, file.nw, file.ne, file.north, file.south, file.east,
+#     file.west, and file.body.  This way we can reconstruct the
+#     region using consistant edges and corners.  
 
-@FILES = `ls $subdir`;
-foreach $file ( @FILES ) {
-    chop($file);
-    if ( $file =~ m/\.1\.node$/ ) {
-	$file =~ s/\.node$//;  # strip off the ".node"
+#     Arbitration rules: If an opposite edge file already exists,
+#     don't create our matching edge.  If a corner already exists,
+#     don't create ours.  Basically, the early bird gets the worm and
+#     gets to define the edge verticies and normals.  All the other
+#     adjacent tiles must use these.
 
-	$command = "./FindEdges/findedges $subdir/$file";
-	print "Running '$command'\n";
-	open(OUT, "$command |");
-	while ( <OUT> ) {
-	    print $_;
+if ( $do_splittris ) {
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	chop($file);
+	if ( $file =~ m/\.1\.node$/ ) {
+	    $file =~ s/\.node$//;  # strip off the ".node"
+	
+	    $command = "./SplitTris/splittris $subdir/$file";
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
 	}
-	close(OUT);
     }
 }
 
 
-exit(1);
-
-
-# 4.2 read in tri files (node/ele) skipping edges, read edges out of
+# 4.2 read in tile sections/ele) skipping edges, read edges out of
 #     edge files, save including proper shared edges (as node/ele)
 #     files.  If my edge and adjacent edge both exist, use other,
 #     delete mine.  If only mine exists, use it.
@@ -164,23 +184,25 @@ exit(1);
 #
 #     Take the file.1.node and file.1.ele and produce file.1.obj
 
-@FILES = `ls $subdir`;
-foreach $file ( @FILES ) {
-    chop($file);
-    if ( $file =~ m/\.1\.node$/ ) {
-	$file =~ s/\.node$//;  # strip off the ".node"
-
-	$command = "./Tri2obj/tri2obj $subdir/$file";
-	print "Running '$command'\n";
-	open(OUT, "$command |");
-	while ( <OUT> ) {
-	    print $_;
+if ( $do_tri2obj ) {
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	chop($file);
+	if ( $file =~ m/\.1\.node$/ ) {
+	    $file =~ s/\.node$//;  # strip off the ".node"
+	    
+	    $command = "./Tri2obj/tri2obj $subdir/$file";
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
+	    
+	    unlink("$subdir/$file.node");
+	    unlink("$subdir/$file.node.orig");
+	    unlink("$subdir/$file.ele");
 	}
-	close(OUT);
-
-	unlink("$subdir/$file.node");
-	unlink("$subdir/$file.node.orig");
-	unlink("$subdir/$file.ele");
     }
 }
 
@@ -193,31 +215,33 @@ foreach $file ( @FILES ) {
 #
 #     strips produces a file called "bands.d" ... copy this to file.2.obj
 
-@FILES = `ls $subdir`;
-foreach $file ( @FILES ) {
-    chop($file);
-    if ( $file =~ m/\.1\.obj$/ ) {
-	$command = "./Stripe_u/strips $subdir/$file";
-	print "Running '$command'\n";
-	open(OUT, "$command |");
-	while ( <OUT> ) {
-	    print $_;
+if ( $do_strips ) {
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	chop($file);
+	if ( $file =~ m/\.1\.obj$/ ) {
+	    $command = "./Stripe_u/strips $subdir/$file";
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
+	    
+	    # copy to destination file
+	    $newfile = $file;
+	    $newfile =~ s/\.1\.obj$//;
+	    print "Copying to $subdir/$newfile.2.obj\n";
+	    open(IN, "<bands.d");
+	    open(OUT, ">$subdir/$newfile.2.obj");
+	    while ( <IN> ) {
+		print OUT $_;
+	    }
+	    close(IN);
+	    close(OUT);
+	    
+	    unlink("$subdir/$file");
 	}
-	close(OUT);
-
-	# copy to destination file
-	$newfile = $file;
-	$newfile =~ s/\.1\.obj$//;
-	print "Copying to $subdir/$newfile.2.obj\n";
-	open(IN, "<bands.d");
-	open(OUT, ">$subdir/$newfile.2.obj");
-	while ( <IN> ) {
-	    print OUT $_;
-	}
-	close(IN);
-	close(OUT);
-
-	unlink("$subdir/$file");
     }
 }
 
@@ -226,28 +250,33 @@ foreach $file ( @FILES ) {
 #
 #     Sort file.2.obj by strip winding
 
-@FILES = `ls $subdir`;
-foreach $file ( @FILES ) {
-    chop($file);
-    if ( $file =~ m/\.2\.obj$/ ) {
-	$newfile = $file;
-	$newfile =~ s/\.2\.obj$/.obj/;
+if ( $do_fixobj ) {
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	chop($file);
+	if ( $file =~ m/\.2\.obj$/ ) {
+	    $newfile = $file;
+	    $newfile =~ s/\.2\.obj$/.obj/;
+	    
+	    $command = "./FixObj/fixobj $subdir/$file $subdir/$newfile";
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
 
-	$command = "./FixObj/fixobj $subdir/$file $subdir/$newfile";
-	print "Running '$command'\n";
-	open(OUT, "$command |");
-	while ( <OUT> ) {
-	    print $_;
+	    unlink("$subdir/$file");
 	}
-	close(OUT);
-
-	unlink("$subdir/$file");
     }
 }
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/01/14 02:15:52  curt
+# Updated front end script to keep plugging away on tile fitting.
+#
 # Revision 1.2  1998/01/12 20:42:08  curt
 # Working on fitting tiles together in a seamless manner.
 #

From 5d50d9eb788db575fa063bcf51a6d39092646beb Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 14 Jan 1998 15:54:42 +0000
Subject: [PATCH 022/283] Initial revision completed.

---
 SplitTris/Makefile    |   5 +-
 SplitTris/depend      |   4 +-
 SplitTris/splittris.c | 244 ++++++++++++++++++++++++++++++++----------
 3 files changed, 191 insertions(+), 62 deletions(-)

diff --git a/SplitTris/Makefile b/SplitTris/Makefile
index b2cb41531..e511d7187 100644
--- a/SplitTris/Makefile
+++ b/SplitTris/Makefile
@@ -33,7 +33,7 @@ OFILES = $(CFILES:.c=.o)
 include ../make.inc
 
 
-CFLAGS = $(FG_CFLAGS)
+CFLAGS = $(FG_CFLAGS) -g
 
 
 #---------------------------------------------------------------------------
@@ -66,6 +66,9 @@ splittris.o: splittris.c
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/01/14 15:54:42  curt
+# Initial revision completed.
+#
 # Revision 1.1  1998/01/14 02:11:30  curt
 # Initial revision.
 #
diff --git a/SplitTris/depend b/SplitTris/depend
index 73c133713..5b95dd978 100644
--- a/SplitTris/depend
+++ b/SplitTris/depend
@@ -1,4 +1,4 @@
-tri2obj.o: tri2obj.c tri2obj.h ../../Src/Include/constants.h \
+splittris.o: splittris.c splittris.h ../../Src/Include/constants.h \
  ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
  ../../Src/Math/mat3.h ../../Src/Math/polar.h \
- ../../Src/Math/../Include/types.h
+ ../../Src/Math/../Include/types.h ../../Src/Scenery/tileutils.h
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index bfef51689..0ef6f9b9d 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -51,8 +51,8 @@ int new_tris[MAX_TRIS][3];
 
 struct fgCartesianPoint nodes_cart[MAX_NODES];
 
-long int ne_index, nw_index, sw_index, se_index;
-long int north_index, south_index, east_index, west_index;
+struct bucket ne_index, nw_index, sw_index, se_index;
+struct bucket north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
@@ -236,19 +236,153 @@ void triload(char *basename) {
 /* check if a file exists */
 int file_exists(char *file) {
     struct stat stat_buf;
+    int result;
+
+    printf("checking %s ... ", file);
 
     result = stat(file, &stat_buf);
 
     if ( result != 0 ) {
 	/* stat failed, no file */
+	printf("not found.\n");
 	return(0);
     } else {
 	/* stat succeeded, file exists */
+	printf("exists.\n");
 	return(1);
     }
 }
 
 
+/* check to see if a shared object exists */
+int shared_object_exists(char *basepath, char *ext) {
+    char file[256], scene_path[256];
+    long int index;
+
+    if ( strcmp(ext, ".sw") == 0 ) {
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&sw_index, scene_path);
+	index = gen_index(&sw_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".se") == 0 ) {
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&se_index, scene_path);
+	index = gen_index(&se_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".ne") == 0 ) {
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&ne_index, scene_path);
+	index = gen_index(&ne_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".nw") == 0 ) {
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&nw_index, scene_path);
+	index = gen_index(&nw_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".south") == 0 ) {
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".north") == 0 ) {
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".west") == 0 ) {
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".east") == 0 ) {
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    return(0);
+}
+
+
 /* my custom file opening routine ... don't open if a shared edge or
  * vertex alread exists */
 FILE *my_open(char *basename, char *basepath, char *ext) {
@@ -257,17 +391,19 @@ FILE *my_open(char *basename, char *basepath, char *ext) {
 
     /* create the output file name */
     strcpy(filename, basename);
-    strcpy(filename, ext);
+    strcat(filename, ext);
 
     /* check if a shared object already exist from a different tile */
 
-    if ( 0 ) {
+    if ( shared_object_exists(basepath, ext) ) {
 	/* not an actual file open error, but we've already got the
          * shared edge, so we don't want to create another one */
+	printf("not opening\n");
 	return(NULL);
     } else {
 	/* open the file */
 	fp = fopen(filename, "w");
+	printf("Opening %s\n", filename);
 	return(fp);
     }
 }
@@ -275,11 +411,8 @@ FILE *my_open(char *basename, char *basepath, char *ext) {
 
 /* dump in WaveFront .obj format */
 void dump_obj(char *basename, char *basepath) {
-    char sw_name[256], se_name[256], ne_name[256], nw_name[256];
-    char north_name[256], south_name[256], east_name[256], west_name[256];
-    char body_name[256];
     double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
-    FILE *sw, *se, *ne, *nw, *north, *south, *east, *west, *body;
+    FILE *fp, *sw, *se, *ne, *nw, *north, *south, *east, *west, *body;
     int i, t1, t2, t3, t4, t5, count;
 
     sw = my_open(basename, basepath, ".sw");
@@ -296,55 +429,35 @@ void dump_obj(char *basename, char *basepath) {
 
     printf("Dumping edges file basename:  %s ...\n", basename);
 
-    sw = fopen(sw_name, "w");
-    se = fopen(se_name, "w");
-    ne = fopen(ne_name, "w");
-    nw = fopen(nw_name, "w");
-
-    north = fopen(north_name, "w");
-    south = fopen(south_name, "w");
-    east = fopen(east_name, "w");
-    west = fopen(west_name, "w");
-
-    body = fopen(body_name, "w");
-
     /* dump vertices */
     printf("  writing vertices\n");
     for ( i = 1; i <= nodecount; i++ ) {
 
 	if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) && 
 	     (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
-	    fprintf(sw, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = sw;
 	} else if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) &&
 		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON) ) {
-	    fprintf(se, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = se;
 	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
 		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON)) {
-	    fprintf(ne, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = ne;
 	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
 		    (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
-	    fprintf(nw, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = nw;
 	} else if ( fabs(nodes_orig[i][0] - xmin) < FG_EPSILON ) {
-	    fprintf(west, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = west;
 	} else if ( fabs(nodes_orig[i][0] - xmax) < FG_EPSILON ) {
-	    fprintf(east, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = east;
 	} else if ( fabs(nodes_orig[i][1] - ymin) < FG_EPSILON ) {
-	    fprintf(south, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = south;
 	} else if ( fabs(nodes_orig[i][1] - ymax) < FG_EPSILON ) {
-	    fprintf(north, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = north;
 	} else {
-	    fprintf(body, "geodn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fp = body;
 	}
-
+	fprintf(fp, "gdn %.2f %.2f %.2f\n", 
+		nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
     }
 
     printf("  calculating and writing normals\n");
@@ -400,26 +513,31 @@ void dump_obj(char *basename, char *basepath) {
 /* 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
 /* 	       norm[0], norm[1], norm[2]); */
 	
+	fp = NULL;
+
 	if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) && 
 	     (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
-	    fprintf(sw, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = sw;
 	} else if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) &&
 		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON) ) {
-	    fprintf(se, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = se;
 	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
 		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON)) {
-	    fprintf(ne, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = ne;
 	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
 		    (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
-	    fprintf(nw, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = nw;
 	} else if ( fabs(nodes_orig[i][0] - xmin) < FG_EPSILON ) {
-	    fprintf(west, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = west;
 	} else if ( fabs(nodes_orig[i][0] - xmax) < FG_EPSILON ) {
-	    fprintf(east, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = east;
 	} else if ( fabs(nodes_orig[i][1] - ymin) < FG_EPSILON ) {
-	    fprintf(south, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = south;
 	} else if ( fabs(nodes_orig[i][1] - ymax) < FG_EPSILON ) {
-	    fprintf(north, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
+	    fp = north;
+	}
+	if ( fp != NULL ) {
+	    fprintf(fp, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
 	}
     }
 
@@ -432,12 +550,14 @@ void dump_obj(char *basename, char *basepath) {
     fclose(south);
     fclose(east);
     fclose(west);
+
+    fclose(body);
 }
 
 
 int main(int argc, char **argv) {
     char basename[256], basepath[256], temp[256];
-    struct bucket p1, p2;
+    struct bucket p;
     long int index;
     int len;
 
@@ -457,23 +577,26 @@ int main(int argc, char **argv) {
     }
     index = atoi(temp);
     printf("%ld\n", index);
-    parse_index(index, &p1);
+    parse_index(index, &p);
 
+    printf("bucket = %d %d %d %d\n", p.lon, p.lat, p.x, p.y);
     /* generate the indexes of the neighbors */
-    offset_bucket(&p1, &p2,  1,  1); ne_index = gen_index(&p2);
-    offset_bucket(&p1, &p2,  1, -1); nw_index = gen_index(&p2);
-    offset_bucket(&p1, &p2, -1,  1); se_index = gen_index(&p2);
-    offset_bucket(&p1, &p2, -1, -1); sw_index = gen_index(&p2);
+    offset_bucket(&p, &ne_index,  1,  1);
+    offset_bucket(&p, &nw_index, -1,  1);
+    offset_bucket(&p, &se_index,  1, -1);
+    offset_bucket(&p, &sw_index, -1, -1);
 
-    offset_bucket(&p1, &p2,  0,  1); north_index = gen_index(&p2);
-    offset_bucket(&p1, &p2,  0, -1); south_index = gen_index(&p2);
-    offset_bucket(&p1, &p2,  1,  0); east_index  = gen_index(&p2);
-    offset_bucket(&p1, &p2, -1,  1); west_index  = gen_index(&p2);
+    offset_bucket(&p, &north_index,  0,  1);
+    offset_bucket(&p, &south_index,  0, -1);
+    offset_bucket(&p, &east_index,  1,  0);
+    offset_bucket(&p, &west_index, -1,  0);
 
+    /*
     printf("Corner indexes = %ld %ld %ld %ld\n", 
 	   ne_index, nw_index, sw_index, se_index);
     printf("Edge indexes = %ld %ld %ld %ld\n",
 	   north_index, south_index, east_index, west_index);
+	   */
 
     /* load the input data files */
     triload(basename);
@@ -486,7 +609,10 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.1  1998/01/14 02:11:31  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/14 15:54:43  curt
+/* Initial revision completed.
 /*
+ * Revision 1.1  1998/01/14 02:11:31  curt
+ * Initial revision.
+ *
  */

From 019d3ec1953f87cc8e6cafe4d9308cc5da3e0a64 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 14 Jan 1998 15:55:34 +0000
Subject: [PATCH 023/283] Finished splittris, started assemtris.

---
 Tools/Makefile       |  5 ++++-
 Tools/TODO           |  7 +++++--
 Tools/process-dem.pl | 20 +++++++++++++-------
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/Tools/Makefile b/Tools/Makefile
index 060bc5d22..44eb3cdeb 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,7 +27,7 @@
 include make.inc
 
 
-SUBDIRS = Dem2node FixNode FixObj Stripe_u Tri2obj Triangle
+SUBDIRS = AssemTris Dem2node FixNode FixObj SplitTris Stripe_u Tri2obj Triangle
 
 
 all: 
@@ -88,6 +88,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/01/14 15:55:34  curt
+# Finished splittris, started assemtris.
+#
 # Revision 1.4  1997/12/10 01:18:25  curt
 # Initial revision.
 #
diff --git a/Tools/TODO b/Tools/TODO
index 12d620269..bea858e49 100644
--- a/Tools/TODO
+++ b/Tools/TODO
@@ -4,14 +4,17 @@
 
 1/10/98 -  Split areas into smaller tiles
 
+1/14/98 -  Don't create shared corners or edges if one already exists.
+
 
 --------------------------------------------------------------------------
 | Todo 
 --------------------------------------------------------------------------
 
+1/14/98 -  Reassemble triangles using only body, shared corners, and 
+           shared edges.
+
 1/12/98 -  Try reversing cw-wound strips rather than calling glFrontFace() 
            in the display list.
 
 1/12/98 -  Generate a face adjacency matrix
-
-1/12/98 -  Don't create shared corners or edges if one already exists.
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 29b95637b..5f9ad9270 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -28,14 +28,15 @@
 
 $| = 1;                         # flush buffers after every write
 
-$do_demfit = 0;
+$do_demfit =     0;
 $do_triangle_1 = 0;
-$do_fixnode = 0;
-$do_splittris = 1;
+$do_fixnode =    0;
+$do_splittris =  0;
+$do_assemtris =  1;
 
-$do_tri2obj = 0;
-$do_strips = 0;
-$do_fixobj = 0;
+$do_tri2obj =    0;
+$do_strips =     0;
+$do_fixobj =     0;
 
 
 # return the file name root (ending at last ".")
@@ -92,12 +93,14 @@ if ( $do_demfit ) {
 	}
     }
     close(OUT);
+} else {
+    $subdir = "../Scenery/w120n030/w111n033";
+    printf("WARNING:  Hardcoding subdir = $subdir
 }
 
 # 3.  triangle -q file (Takes file.node and produces file.1.node and
 #                      file.1.ele)
 
-$subdir = "../Scenery/w120n030/w111n033";
 print "Subdirectory for this dem file is $subdir\n";
 
 if ( $do_triangle_1 ) {
@@ -274,6 +277,9 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/01/14 15:55:34  curt
+# Finished splittris, started assemtris.
+#
 # Revision 1.3  1998/01/14 02:15:52  curt
 # Updated front end script to keep plugging away on tile fitting.
 #

From 72566953ded09801dbbc1d8ab71f1a065dce3904 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 15 Jan 1998 02:45:25 +0000
Subject: [PATCH 024/283] Initial revision.

---
 AssemTris/Makefile    |  72 +++++++
 AssemTris/assemtris.c | 454 ++++++++++++++++++++++++++++++++++++++++++
 AssemTris/assemtris.h |  45 +++++
 AssemTris/depend      |   4 +
 4 files changed, 575 insertions(+)
 create mode 100644 AssemTris/Makefile
 create mode 100644 AssemTris/assemtris.c
 create mode 100644 AssemTris/assemtris.h
 create mode 100644 AssemTris/depend

diff --git a/AssemTris/Makefile b/AssemTris/Makefile
new file mode 100644
index 000000000..3876ad272
--- /dev/null
+++ b/AssemTris/Makefile
@@ -0,0 +1,72 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+TARGET = assemtris
+
+CFILES = assemtris.c ../../Src/Scenery/tileutils.c
+OFILES = $(CFILES:.c=.o)
+
+
+include ../make.inc
+
+
+CFLAGS = $(FG_CFLAGS) -g
+
+
+#---------------------------------------------------------------------------
+# Primary Targets
+#---------------------------------------------------------------------------
+
+all: $(TARGET)
+
+$(TARGET): $(OFILES)
+	$(CC) $(OFILES) -o $(TARGET) ../../Src/Math/libMath.a -lm
+
+clean:
+	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
+
+realclean: clean
+
+
+#---------------------------------------------------------------------------
+# Secondary Targets
+#---------------------------------------------------------------------------
+
+makedepend:
+	$(CC) -MM *.c > depend
+
+include depend
+
+assemtris.o: assemtris.c
+	$(CC) $(CFLAGS) -c assemtris.c -o $@
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/01/15 02:45:25  curt
+# Initial revision.
+#
+
diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
new file mode 100644
index 000000000..2541da125
--- /dev/null
+++ b/AssemTris/assemtris.c
@@ -0,0 +1,454 @@
+/* splittris.c -- reassemble the pieces produced by splittris
+ *
+ * Written by Curtis Olson, started January 1998.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file) */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>   /* for atoi() */
+#include <string.h>
+#include <sys/stat.h> /* for stat() */
+#include <unistd.h>   /* for stat() */
+
+#include "assemtris.h"
+
+#include "../../Src/Include/constants.h"
+#include "../../Src/Include/types.h"
+#include "../../Src/Math/fg_geodesy.h"
+#include "../../Src/Math/mat3.h"
+#include "../../Src/Math/polar.h"
+#include "../../Src/Scenery/tileutils.h"
+
+
+int nodecount = 0;
+
+float nodes[MAX_NODES][3];
+
+
+struct bucket my_index;
+struct bucket ne_index, nw_index, sw_index, se_index;
+struct bucket north_index, south_index, east_index, west_index;
+
+
+/* return the file base name ( foo/bar/file.ext = file.ext ) */
+void extract_file(char *in, char *base) {
+    int len, i;
+
+    len = strlen(in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    in += (i + 1);
+    strcpy(base, in);
+}
+
+
+/* return the file path name ( foo/bar/file.ext = foo/bar ) */
+void extract_path(char *in, char *base) {
+    int len, i;
+
+    len = strlen(in);
+    strcpy(base, in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    base[i] = '\0';
+}
+
+
+/* check if a file exists */
+int file_exists(char *file) {
+    struct stat stat_buf;
+    int result;
+
+    printf("checking %s ... ", file);
+
+    result = stat(file, &stat_buf);
+
+    if ( result != 0 ) {
+	/* stat failed, no file */
+	printf("not found.\n");
+	return(0);
+    } else {
+	/* stat succeeded, file exists */
+	printf("exists.\n");
+	return(1);
+    }
+}
+
+
+/* check to see if a shared object exists */
+int shared_object_exists(char *basepath, char *ext, char *file) {
+    char scene_path[256];
+    long int index;
+
+    if ( strcmp(ext, ".sw") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&sw_index, scene_path);
+	index = gen_index(&sw_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".se") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&se_index, scene_path);
+	index = gen_index(&se_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".ne") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&ne_index, scene_path);
+	index = gen_index(&ne_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".nw") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&nw_index, scene_path);
+	index = gen_index(&nw_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".south") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".north") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".west") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".east") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".body") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    return(0);
+}
+
+
+/* my custom file opening routine ... don't open if a shared edge or
+ * vertex alread exists */
+FILE *my_open(char *basename, char *basepath, char *ext) {
+    FILE *fp;
+    char filename[256];
+
+    /* check if a shared object already exists */
+    if ( shared_object_exists(basepath, ext, filename) ) {
+	/* not an actual file open error, but we've already got the
+         * shared edge, so we don't want to create another one */
+	fp = fopen(filename, "r");
+	printf("Opening %s\n", filename);
+	return(fp);
+    } else {
+	/* open the file */
+	printf("not opening\n");
+	return(NULL);
+    }
+}
+
+
+/* given a file pointer, read all the gdn (geodetic nodes from it) */
+void read_nodes(FILE *fp) {
+    char line[256];
+
+    while ( fgets(line, 250, fp) != NULL ) {
+	if ( strncmp(line, "gdn ", 4) == 0 ) {
+	    sscanf(line, "gdn %f %f %f\n", &nodes[nodecount][0], 
+		   &nodes[nodecount][1], &nodes[nodecount][2]);
+	    /*
+	    printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
+		   nodes[nodecount][0], nodes[nodecount][1], 
+		   nodes[nodecount][2], line);
+		   */
+	    nodecount++;
+	}
+    }
+}
+
+
+/* load in nodes from the various split and shared pieces to
+ * reconstruct a tile */
+void build_node_list(char *basename, char *basepath) {
+    FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
+
+    ne = my_open(basename, basepath, ".ne");
+    read_nodes(ne);
+    fclose(ne);
+
+    nw = my_open(basename, basepath, ".nw");
+    read_nodes(nw);
+    fclose(nw);
+
+    se = my_open(basename, basepath, ".se");
+    read_nodes(se);
+    fclose(se);
+
+    sw = my_open(basename, basepath, ".sw");
+    read_nodes(sw);
+    fclose(sw);
+
+    north = my_open(basename, basepath, ".north");
+    read_nodes(north);
+    fclose(north);
+
+    south = my_open(basename, basepath, ".south");
+    read_nodes(south);
+    fclose(south);
+
+    east = my_open(basename, basepath, ".east");
+    read_nodes(east);
+    fclose(east);
+
+    west = my_open(basename, basepath, ".west");
+    read_nodes(west);
+    fclose(west);
+
+    body = my_open(basename, basepath, ".body");
+    read_nodes(body);
+    fclose(body);
+}
+
+
+/* dump in WaveFront .obj format */
+void dump_nodes(char *basename, char *basepath) {
+    FILE *fp;
+    int i;
+
+    /* dump vertices */
+    printf("  writing vertices in .node format\n");
+    /* printf("Creating node file:  %s\n", file);
+    fd = fopen(file, "w"); */
+
+    printf("%d 2 1 0\n", nodecount);
+
+    /* now write out actual node data */
+    for ( i = 0; i < nodecount; i++ ) {
+	printf("%d %.2f %.2f %.2f 0\n", i + 1,
+	       nodes[i][0], nodes[i][1], nodes[i][2]);
+    }
+
+    /* fclose(fd); */
+
+}
+
+
+int main(int argc, char **argv) {
+    char basename[256], basepath[256], temp[256];
+    long int tmp_index;
+    int len;
+
+    strcpy(basename, argv[1]);
+
+    /* find the base path of the file */
+    extract_path(basename, basepath);
+    extract_path(basepath, basepath);
+    extract_path(basepath, basepath);
+    printf("%s\n", basepath);
+
+    /* find the index of the current file */
+    extract_file(basename, temp);
+    len = strlen(temp);
+    if ( len >= 2 ) {
+	temp[len-2] = '\0';
+    }
+    tmp_index = atoi(temp);
+    printf("%ld\n", tmp_index);
+    parse_index(tmp_index, &my_index);
+
+    printf("bucket = %d %d %d %d\n", 
+	   my_index.lon, my_index.lat, my_index.x, my_index.y);
+    /* generate the indexes of the neighbors */
+    offset_bucket(&my_index, &ne_index,  1,  1);
+    offset_bucket(&my_index, &nw_index, -1,  1);
+    offset_bucket(&my_index, &se_index,  1, -1);
+    offset_bucket(&my_index, &sw_index, -1, -1);
+
+    offset_bucket(&my_index, &north_index,  0,  1);
+    offset_bucket(&my_index, &south_index,  0, -1);
+    offset_bucket(&my_index, &east_index,  1,  0);
+    offset_bucket(&my_index, &west_index, -1,  0);
+
+    /*
+    printf("Corner indexes = %ld %ld %ld %ld\n", 
+	   ne_index, nw_index, sw_index, se_index);
+    printf("Edge indexes = %ld %ld %ld %ld\n",
+	   north_index, south_index, east_index, west_index);
+	   */
+
+    /* load the input data files */
+    build_node_list(basename, basepath);
+
+    /* dump in WaveFront .obj format */
+    dump_nodes(basename, basepath);
+
+    return(0);
+}
+
+
+/* $Log$
+/* Revision 1.1  1998/01/15 02:45:26  curt
+/* Initial revision.
+/*
+ */
diff --git a/AssemTris/assemtris.h b/AssemTris/assemtris.h
new file mode 100644
index 000000000..44900c4c7
--- /dev/null
+++ b/AssemTris/assemtris.h
@@ -0,0 +1,45 @@
+/* splittris.h -- reassemble the pieces produced by splittris
+ *
+ * Written by Curtis Olson, started January 1998.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#ifndef ASSEMTRIS_H
+#define ASSEMTRIS_H
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+#define MAX_NODES 200000
+#define MAX_TRIS  400000
+
+
+#endif /* SPLITTRIS_H */
+
+
+/* $Log$
+/* Revision 1.1  1998/01/15 02:45:26  curt
+/* Initial revision.
+/*
+ */
diff --git a/AssemTris/depend b/AssemTris/depend
new file mode 100644
index 000000000..50c56a1f3
--- /dev/null
+++ b/AssemTris/depend
@@ -0,0 +1,4 @@
+assemtris.o: assemtris.c assemtris.h ../../Src/Include/constants.h \
+ ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
+ ../../Src/Math/mat3.h ../../Src/Math/polar.h \
+ ../../Src/Math/../Include/types.h ../../Src/Scenery/tileutils.h

From 9ec4cd8be26c4791de4471577b9153a7aaf43ff7 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 15 Jan 1998 02:49:25 +0000
Subject: [PATCH 025/283] Misc. housekeeping.

---
 SplitTris/splittris.h | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/SplitTris/splittris.h b/SplitTris/splittris.h
index cb20583c0..abd7621b4 100644
--- a/SplitTris/splittris.h
+++ b/SplitTris/splittris.h
@@ -24,8 +24,8 @@
  */
 
 
-#ifndef FINDEDGES_H
-#define FINDEDGES_H
+#ifndef SPLITTRIS_H
+#define SPLITTRIS_H
 
 
 #include <stdio.h>
@@ -46,11 +46,14 @@ extern int new_tris[MAX_TRIS][3];
 void triload(char *basename);
 
 
-#endif /* FINDEDGES_H */
+#endif /* SPLITTRIS_H */
 
 
 /* $Log$
-/* Revision 1.1  1998/01/14 02:11:32  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/15 02:49:25  curt
+/* Misc. housekeeping.
 /*
+ * Revision 1.1  1998/01/14 02:11:32  curt
+ * Initial revision.
+ *
  */

From 955713372917ed2bb1c85f48679f01253dad4bb8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 15 Jan 1998 02:50:08 +0000
Subject: [PATCH 026/283] Tweaked to add next stage.

---
 Tools/process-dem.pl | 39 ++++++++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 5f9ad9270..62915bb71 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -87,15 +87,16 @@ if ( $do_demfit ) {
     open(OUT, "$command |");
     while ( <OUT> ) {
 	print $_;
-	if ( m/Scenery/ ) {
+	if ( m/^Dir = / ) {
 	    $subdir = $_;
-	    $subdir =~ s/Dir = //;
+	    $subdir =~ s/^Dir = //;
+	    chop($subdir);
 	}
     }
     close(OUT);
 } else {
     $subdir = "../Scenery/w120n030/w111n033";
-    printf("WARNING:  Hardcoding subdir = $subdir
+    print "WARNING:  Hardcoding subdir = $subdir\n";
 }
 
 # 3.  triangle -q file (Takes file.node and produces file.1.node and
@@ -169,15 +170,36 @@ if ( $do_splittris ) {
 		print $_;
 	    }
 	    close(OUT);
+
+	    unlink("$subdir/$file.node");
+	    unlink("$subdir/$file.node.orig");
+	    unlink("$subdir/$file.ele");
 	}
     }
 }
 
 
-# 4.2 read in tile sections/ele) skipping edges, read edges out of
-#     edge files, save including proper shared edges (as node/ele)
-#     files.  If my edge and adjacent edge both exist, use other,
-#     delete mine.  If only mine exists, use it.
+# 4.2 read in the split of version of the tiles, reconstruct the tile
+#     using the proper shared corners and edges.  Save as a node file
+#     so we can retriangulate.
+
+if ( $do_assemtris ) {
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	chop($file);
+	if ( $file =~ m/\.1\.body$/ ) {
+	    $file =~ s/\.body$//;  # strip off the ".node"
+	
+	    $command = "./AssemTris/assemtris $subdir/$file";
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
+	}
+    }
+}
 
 
 # 4.3 Retriangulate fixed up files (without -q option)
@@ -277,6 +299,9 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/01/15 02:50:08  curt
+# Tweaked to add next stage.
+#
 # Revision 1.4  1998/01/14 15:55:34  curt
 # Finished splittris, started assemtris.
 #

From 8e59b3debd834cfe2fe10086403e9059c2ab9438 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 15 Jan 1998 21:33:32 +0000
Subject: [PATCH 027/283] Assembling triangles and building a new .node file
 with the proper shared vertices now works.  Now we just have to use the
 shared normals and we'll be all set.

---
 AssemTris/assemtris.c | 35 +++++++++++++++++++++------------
 Tools/TODO            |  7 +++++--
 Tools/process-dem.pl  | 45 +++++++++++++++++++++++++++++++++++++------
 3 files changed, 67 insertions(+), 20 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index 2541da125..523d88e4b 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -372,25 +372,31 @@ void build_node_list(char *basename, char *basepath) {
 
 
 /* dump in WaveFront .obj format */
-void dump_nodes(char *basename, char *basepath) {
+void dump_nodes(char *basename) {
+    char file[256];
     FILE *fp;
-    int i;
+    int i, len;
 
+    /* generate output file name */
+    strcpy(file, basename);
+    len = strlen(file);
+    file[len-2] = '\0';
+    strcat(file, ".node");
+    
     /* dump vertices */
-    printf("  writing vertices in .node format\n");
-    /* printf("Creating node file:  %s\n", file);
-    fd = fopen(file, "w"); */
+    printf("Creating node file:  %s\n", file);
+    printf("  writing vertices in .node format.\n");
+    fp = fopen(file, "w");
 
-    printf("%d 2 1 0\n", nodecount);
+    fprintf(fp, "%d 2 1 0\n", nodecount);
 
     /* now write out actual node data */
     for ( i = 0; i < nodecount; i++ ) {
-	printf("%d %.2f %.2f %.2f 0\n", i + 1,
+	fprintf(fp, "%d %.2f %.2f %.2f 0\n", i + 1,
 	       nodes[i][0], nodes[i][1], nodes[i][2]);
     }
 
-    /* fclose(fd); */
-
+    fclose(fp);
 }
 
 
@@ -441,14 +447,19 @@ int main(int argc, char **argv) {
     build_node_list(basename, basepath);
 
     /* dump in WaveFront .obj format */
-    dump_nodes(basename, basepath);
+    dump_nodes(basename);
 
     return(0);
 }
 
 
 /* $Log$
-/* Revision 1.1  1998/01/15 02:45:26  curt
-/* Initial revision.
+/* Revision 1.2  1998/01/15 21:33:36  curt
+/* Assembling triangles and building a new .node file with the proper shared
+/* vertices now works.  Now we just have to use the shared normals and we'll
+/* be all set.
 /*
+ * Revision 1.1  1998/01/15 02:45:26  curt
+ * Initial revision.
+ *
  */
diff --git a/Tools/TODO b/Tools/TODO
index bea858e49..d0a8ad198 100644
--- a/Tools/TODO
+++ b/Tools/TODO
@@ -6,13 +6,16 @@
 
 1/14/98 -  Don't create shared corners or edges if one already exists.
 
+1/14/98 -  Reassemble triangles using only body, shared corners, and 
+           shared edges.
+
 
 --------------------------------------------------------------------------
 | Todo 
 --------------------------------------------------------------------------
 
-1/14/98 -  Reassemble triangles using only body, shared corners, and 
-           shared edges.
+1/15/98 -  Retro-fit tri2obj to use shared normals rather than regenerating
+           normals for shared vertices.
 
 1/12/98 -  Try reversing cw-wound strips rather than calling glFrontFace() 
            in the display list.
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 62915bb71..7d59eaf73 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -32,9 +32,10 @@ $do_demfit =     0;
 $do_triangle_1 = 0;
 $do_fixnode =    0;
 $do_splittris =  0;
-$do_assemtris =  1;
+$do_assemtris =  0;
+$do_triangle_2 = 0;
 
-$do_tri2obj =    0;
+$do_tri2obj =    1;
 $do_strips =     0;
 $do_fixobj =     0;
 
@@ -202,12 +203,39 @@ if ( $do_assemtris ) {
 }
 
 
-# 4.3 Retriangulate fixed up files (without -q option)
+# 4.3 Retriangulate reassembled files (without -q option) so no new
+#     nodes are generated.
+
+if ( $do_triangle_2 ) {
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	print $file;
+	chop($file);
+	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
+	    $command = "./Triangle/triangle $subdir/$file";
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
+
+	    # remove input file.node
+	    unlink("$subdir/$file");
+	}
+    }
+}
 
 
 # 5.  tri2obj file (.1.node) (.1.ele)
 #
 #     Take the file.1.node and file.1.ele and produce file.1.obj
+#
+#     Extracts normals out of the shared edge/vertex files, and uses
+#     the precalcuated normals for these nodes instead of calculating
+#     new ones.  By sharing normals as well as vertices, not only are
+#     the gaps between tiles eliminated, but the colors and lighting
+#     transition smoothly across tile boundaries.
 
 if ( $do_tri2obj ) {
     @FILES = `ls $subdir`;
@@ -224,9 +252,9 @@ if ( $do_tri2obj ) {
 	    }
 	    close(OUT);
 	    
-	    unlink("$subdir/$file.node");
-	    unlink("$subdir/$file.node.orig");
-	    unlink("$subdir/$file.ele");
+	    # unlink("$subdir/$file.node");
+	    # unlink("$subdir/$file.node.orig");
+	    # unlink("$subdir/$file.ele");
 	}
     }
 }
@@ -299,6 +327,11 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1998/01/15 21:33:33  curt
+# Assembling triangles and building a new .node file with the proper shared
+# vertices now works.  Now we just have to use the shared normals and we'll
+# be all set.
+#
 # Revision 1.5  1998/01/15 02:50:08  curt
 # Tweaked to add next stage.
 #

From 6aaf9bebc7fd32577008866c6a93b507d9f5a0ac Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 17 Jan 1998 01:25:39 +0000
Subject: [PATCH 028/283] Added support for shared normals.

---
 Tri2obj/Makefile  |   5 +-
 Tri2obj/tri2obj.c | 457 +++++++++++++++++++++++++++++++++++++++++-----
 Tri2obj/tri2obj.h |   9 +-
 3 files changed, 422 insertions(+), 49 deletions(-)

diff --git a/Tri2obj/Makefile b/Tri2obj/Makefile
index 87ddbbd49..9cdbaaa61 100644
--- a/Tri2obj/Makefile
+++ b/Tri2obj/Makefile
@@ -26,7 +26,7 @@
 
 TARGET = tri2obj
 
-CFILES = tri2obj.c
+CFILES = tri2obj.c ../../Src/Scenery/tileutils.c
 OFILES = $(CFILES:.c=.o)
 
 
@@ -66,6 +66,9 @@ tri2obj.o: tri2obj.c
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/01/17 01:25:39  curt
+# Added support for shared normals.
+#
 # Revision 1.3  1997/12/02 13:13:32  curt
 # Fixed problem with averaged vertex normals.
 #
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 9e4e72b9f..f6b7970b6 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -25,7 +25,10 @@
 
 
 #include <stdio.h>
+#include <stdlib.h>   /* for atoi() */
 #include <string.h>
+#include <sys/stat.h> /* for stat() */
+#include <unistd.h>   /* for stat() */
 
 #include "tri2obj.h"
 
@@ -34,13 +37,20 @@
 #include "../../Src/Math/fg_geodesy.h"
 #include "../../Src/Math/mat3.h"
 #include "../../Src/Math/polar.h"
+#include "../../Src/Scenery/tileutils.h"
 
 
 int nodecount, tricount;
+int normalcount = 0;
 struct fgCartesianPoint nodes[MAX_NODES];
 int tris[MAX_TRIS][3];
 int new_tris[MAX_TRIS][3];
 
+float normals[MAX_NODES][3];
+
+struct bucket my_index;
+struct bucket ne_index, nw_index, sw_index, se_index;
+struct bucket north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
@@ -108,14 +118,326 @@ void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
 }
 
 
+/* return the file base name ( foo/bar/file.ext = file.ext ) */
+void extract_file(char *in, char *base) {
+    int len, i;
+
+    len = strlen(in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    in += (i + 1);
+    strcpy(base, in);
+}
+
+
+/* return the file path name ( foo/bar/file.ext = foo/bar ) */
+void extract_path(char *in, char *base) {
+    int len, i;
+
+    len = strlen(in);
+    strcpy(base, in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    base[i] = '\0';
+}
+
+
+/* check if a file exists */
+int file_exists(char *file) {
+    struct stat stat_buf;
+    int result;
+
+    printf("checking %s ... ", file);
+
+    result = stat(file, &stat_buf);
+
+    if ( result != 0 ) {
+	/* stat failed, no file */
+	printf("not found.\n");
+	return(0);
+    } else {
+	/* stat succeeded, file exists */
+	printf("exists.\n");
+	return(1);
+    }
+}
+
+
+/* check to see if a shared object exists */
+int shared_object_exists(char *basepath, char *ext, char *file) {
+    char scene_path[256];
+    long int index;
+
+    if ( strcmp(ext, ".sw") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&sw_index, scene_path);
+	index = gen_index(&sw_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".se") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&se_index, scene_path);
+	index = gen_index(&se_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".ne") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&ne_index, scene_path);
+	index = gen_index(&ne_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".nw") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&nw_index, scene_path);
+	index = gen_index(&nw_index);
+	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".south") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&south_index, scene_path);
+	index = gen_index(&south_index);
+	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".north") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&north_index, scene_path);
+	index = gen_index(&north_index);
+	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".west") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&west_index, scene_path);
+	index = gen_index(&west_index);
+	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".east") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+	gen_base_path(&east_index, scene_path);
+	index = gen_index(&east_index);
+	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    if ( strcmp(ext, ".body") == 0 ) {
+	gen_base_path(&my_index, scene_path);
+	index = gen_index(&my_index);
+	sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index);
+	if ( file_exists(file) ) {
+	    return(1);
+	}
+    }
+
+    return(0);
+}
+
+
+/* given a file pointer, read all the vn (normals from it) */
+void read_normals(FILE *fp) {
+    char line[256];
+
+    while ( fgets(line, 250, fp) != NULL ) {
+	if ( strncmp(line, "vn ", 3) == 0 ) {
+	    sscanf(line, "vn %f %f %f\n", &normals[normalcount][0], 
+		   &normals[normalcount][1], &normals[normalcount][2]);
+	    /*
+	    printf("read_normals(%d) %.2f %.2f %.2f %s", normalcount, 
+		   normals[normalcount][0], normals[normalcount][1], 
+		   normals[normalcount][2], line);
+		   */
+	    normalcount++;
+	}
+    }
+}
+
+
+/* my custom file opening routine ... don't open if a shared edge or
+ * vertex alread exists */
+FILE *my_open(char *basename, char *basepath, char *ext) {
+    FILE *fp;
+    char filename[256];
+
+    /* check if a shared object already exists */
+    if ( shared_object_exists(basepath, ext, filename) ) {
+	/* not an actual file open error, but we've already got the
+         * shared edge, so we don't want to create another one */
+	fp = fopen(filename, "r");
+	printf("Opening %s\n", filename);
+	return(fp);
+    } else {
+	/* open the file */
+	printf("not opening\n");
+	return(NULL);
+    }
+}
+
+
 /* Initialize a new mesh structure */
-void triload(char *basename) {
+void triload(char *basename, char *basepath) {
     char nodename[256], elename[256];
     double n[3];
+    FILE *ne, *nw, *se, *sw, *north, *south, *east, *west;
     FILE *node, *ele;
     int dim, junk1, junk2;
     int i;
 
+    ne = my_open(basename, basepath, ".ne");
+    read_normals(ne);
+    fclose(ne);
+
+    nw = my_open(basename, basepath, ".nw");
+    read_normals(nw);
+    fclose(nw);
+
+    se = my_open(basename, basepath, ".se");
+    read_normals(se);
+    fclose(se);
+
+    sw = my_open(basename, basepath, ".sw");
+    read_normals(sw);
+    fclose(sw);
+
+    north = my_open(basename, basepath, ".north");
+    read_normals(north);
+    fclose(north);
+
+    south = my_open(basename, basepath, ".south");
+    read_normals(south);
+    fclose(south);
+
+    east = my_open(basename, basepath, ".east");
+    read_normals(east);
+    fclose(east);
+
+    west = my_open(basename, basepath, ".west");
+    read_normals(west);
+    fclose(west);
+
     strcpy(nodename, basename);
     strcat(nodename, ".node");
     strcpy(elename, basename);
@@ -194,58 +516,69 @@ void dump_obj(char *basename) {
     }
 
     printf("  calculating and writing normals\n");
+    printf("  First %d normals taken from shared files.\n", normalcount);
+						     
     /* calculate and generate normals */
     for ( i = 1; i <= nodecount; i++ ) {
-/* 	printf("Finding normal\n"); */
 
-	find_tris(i, &t1, &t2, &t3, &t4, &t5);
+	if ( i <= normalcount ) {
+	    /* use precalculated (shared) normal */
+	    norm[0] = normals[i-1][0];
+	    norm[1] = normals[i-1][1];
+	    norm[2] = normals[i-1][2];
+	} else {
+	    /* printf("Finding normal\n"); */
 
-	n1[0] = n1[1] = n1[2] = 0.0;
-	n2[0] = n2[1] = n2[2] = 0.0;
-	n3[0] = n3[1] = n3[2] = 0.0;
-	n4[0] = n4[1] = n4[2] = 0.0;
-	n5[0] = n5[1] = n5[2] = 0.0;
+	    find_tris(i, &t1, &t2, &t3, &t4, &t5);
 
-	count = 1;
-	calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], nodes[tris[t1][2]], 
-		    n1);
+	    n1[0] = n1[1] = n1[2] = 0.0;
+	    n2[0] = n2[1] = n2[2] = 0.0;
+	    n3[0] = n3[1] = n3[2] = 0.0;
+	    n4[0] = n4[1] = n4[2] = 0.0;
+	    n5[0] = n5[1] = n5[2] = 0.0;
 
-	if ( t2 > 0 ) {
-	    calc_normal(nodes[tris[t2][0]], nodes[tris[t2][1]], 
-			nodes[tris[t2][2]], n2);
-	    count = 2;
-	}
+	    count = 1;
+	    calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], 
+			nodes[tris[t1][2]], n1);
 
-	if ( t3 > 0 ) {
-	    calc_normal(nodes[tris[t3][0]], nodes[tris[t3][1]],
-			nodes[tris[t3][2]], n3);
-	    count = 3;
-	}
+	    if ( t2 > 0 ) {
+		calc_normal(nodes[tris[t2][0]], nodes[tris[t2][1]], 
+			    nodes[tris[t2][2]], n2);
+		count = 2;
+	    }
 
-	if ( t4 > 0 ) {
-	    calc_normal(nodes[tris[t4][0]], nodes[tris[t4][1]],
-			nodes[tris[t4][2]], n4);
-	    count = 4;
-	}
+	    if ( t3 > 0 ) {
+		calc_normal(nodes[tris[t3][0]], nodes[tris[t3][1]],
+			    nodes[tris[t3][2]], n3);
+		count = 3;
+	    }
 
-	if ( t5 > 0 ) {
-	    calc_normal(nodes[tris[t5][0]], nodes[tris[t5][1]],
-			nodes[tris[t5][2]], n5);
-	    count = 5;
-	}
+	    if ( t4 > 0 ) {
+		calc_normal(nodes[tris[t4][0]], nodes[tris[t4][1]],
+			    nodes[tris[t4][2]], n4);
+		count = 4;
+	    }
 
-/* 	printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
+	    if ( t5 > 0 ) {
+		calc_normal(nodes[tris[t5][0]], nodes[tris[t5][1]],
+			    nodes[tris[t5][2]], n5);
+		count = 5;
+	    }
 
-	norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count;
-	norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count;
-	norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count;
-	
-/* 	printf("  count = %d\n", count); */
-/* 	printf("  Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);*/
-	MAT3_NORMALIZE_VEC(norm, temp);
-/* 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
-/* 	       norm[0], norm[1], norm[2]); */
+	    /* printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
+
+	    norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count;
+	    norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count;
+	    norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count;
 	
+	    /* 	printf("  count = %d\n", count); */
+	    /* 	printf("  Ave. normal = %.4f %.4f %.4f\n", 
+		       norm[0], norm[1], norm[2]);*/
+	    MAT3_NORMALIZE_VEC(norm, temp);
+	    /* 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
+	    /* 	       norm[0], norm[1], norm[2]); */
+	}
+	/* printf("%d vn %.4f %.4f %.4f\n", i, norm[0], norm[1], norm[2]); */
 	fprintf(obj, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
     }
 
@@ -259,12 +592,43 @@ void dump_obj(char *basename) {
 }
 
 int main(int argc, char **argv) {
-    char basename[256];
+    char basename[256], basepath[256], temp[256];
+    long int tmp_index;
+    int len;
 
     strcpy(basename, argv[1]);
 
+    /* find the base path of the file */
+    extract_path(basename, basepath);
+    extract_path(basepath, basepath);
+    extract_path(basepath, basepath);
+    printf("%s\n", basepath);
+
+    /* find the index of the current file */
+    extract_file(basename, temp);
+    len = strlen(temp);
+    if ( len >= 2 ) {
+	temp[len-2] = '\0';
+    }
+    tmp_index = atoi(temp);
+    printf("%ld\n", tmp_index);
+    parse_index(tmp_index, &my_index);
+
+    printf("bucket = %d %d %d %d\n", 
+	   my_index.lon, my_index.lat, my_index.x, my_index.y);
+    /* generate the indexes of the neighbors */
+    offset_bucket(&my_index, &ne_index,  1,  1);
+    offset_bucket(&my_index, &nw_index, -1,  1);
+    offset_bucket(&my_index, &se_index,  1, -1);
+    offset_bucket(&my_index, &sw_index, -1, -1);
+
+    offset_bucket(&my_index, &north_index,  0,  1);
+    offset_bucket(&my_index, &south_index,  0, -1);
+    offset_bucket(&my_index, &east_index,  1,  0);
+    offset_bucket(&my_index, &west_index, -1,  0);
+
     /* load the input data files */
-    triload(basename);
+    triload(basename, basepath);
 
     /* dump in WaveFront .obj format */
     dump_obj(basename);
@@ -274,9 +638,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.7  1998/01/12 02:42:00  curt
-/* Average up to five triangles per vertex instead of three.
+/* Revision 1.8  1998/01/17 01:25:39  curt
+/* Added support for shared normals.
 /*
+ * Revision 1.7  1998/01/12 02:42:00  curt
+ * Average up to five triangles per vertex instead of three.
+ *
  * Revision 1.6  1998/01/09 23:03:15  curt
  * Restructured to split 1deg x 1deg dem's into 64 subsections.
  *
diff --git a/Tri2obj/tri2obj.h b/Tri2obj/tri2obj.h
index 3d3584010..0b867edaf 100644
--- a/Tri2obj/tri2obj.h
+++ b/Tri2obj/tri2obj.h
@@ -43,16 +43,19 @@ extern int new_tris[MAX_TRIS][3];
 
 
 /* Initialize a new mesh structure */
-void triload(char *basename);
+void triload(char *basename, char *basepath);
 
 
 #endif /* TRI2OBJ_H */
 
 
 /* $Log$
-/* Revision 1.3  1997/11/15 18:05:06  curt
-/* minor tweaks ...
+/* Revision 1.4  1998/01/17 01:25:40  curt
+/* Added support for shared normals.
 /*
+ * Revision 1.3  1997/11/15 18:05:06  curt
+ * minor tweaks ...
+ *
  * Revision 1.2  1997/11/14 00:29:13  curt
  * Transform scenery coordinates at this point in pipeline when scenery is
  * being translated to .obj format, not when it is being loaded into the end

From 0fc4892bc602e8ac315761ecb46705ccd017e4e3 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 19 Jan 1998 19:51:06 +0000
Subject: [PATCH 029/283] A couple final pre-release tweaks.

---
 FixObj/obj.c         | 12 ++++++++++--
 Tools/process-dem.pl | 26 +++++++++++++++-----------
 Tri2obj/depend       |  2 +-
 3 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index 19b87d4b1..01d885fdb 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -208,6 +208,11 @@ void obj_fix(char *infile, char *outfile) {
 	    printf("new tri strip = %s", line);
 	    sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
 
+	    /* special case to handle a bug in our beloved tri striper */
+	    if ( (n1 == 4) && (n2 == 2) && (n3 == 2) && (n4 == 1) ) {
+		n2 = 3;
+	    }
+
 	    dot_prod = check_cur_face(n1, n2, n3);
 	    if ( dot_prod < -0.5 ) {
 		/* this stripe is backwards (CW) */
@@ -283,9 +288,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.2  1998/01/09 23:03:12  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
+/* Revision 1.3  1998/01/19 19:51:07  curt
+/* A couple final pre-release tweaks.
 /*
+ * Revision 1.2  1998/01/09 23:03:12  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
  * Revision 1.1  1997/12/08 19:28:54  curt
  * Initial revision.
  *
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 7d59eaf73..513530d7a 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -28,16 +28,16 @@
 
 $| = 1;                         # flush buffers after every write
 
-$do_demfit =     0;
-$do_triangle_1 = 0;
-$do_fixnode =    0;
-$do_splittris =  0;
-$do_assemtris =  0;
-$do_triangle_2 = 0;
+$do_demfit =     1;
+$do_triangle_1 = 1;
+$do_fixnode =    1;
+$do_splittris =  1;
+$do_assemtris =  1;
+$do_triangle_2 = 1;
 
 $do_tri2obj =    1;
-$do_strips =     0;
-$do_fixobj =     0;
+$do_strips =     1;
+$do_fixobj =     1;
 
 
 # return the file name root (ending at last ".")
@@ -96,7 +96,7 @@ if ( $do_demfit ) {
     }
     close(OUT);
 } else {
-    $subdir = "../Scenery/w120n030/w111n033";
+    $subdir = "../Scenery/w100n040/w093n045";
     print "WARNING:  Hardcoding subdir = $subdir\n";
 }
 
@@ -262,7 +262,8 @@ if ( $do_tri2obj ) {
 
 # 6.  strip file.1.obj
 # 
-#     Strip the file.1.obj's
+#     Strip the file.1.obj's.  Note, strips doesn't handle the minimal
+#     case of striping a square correctly.
 #
 # 7.  cp bands.d file.2.obj
 #
@@ -293,7 +294,7 @@ if ( $do_strips ) {
 	    close(IN);
 	    close(OUT);
 	    
-	    unlink("$subdir/$file");
+	    # unlink("$subdir/$file");
 	}
     }
 }
@@ -327,6 +328,9 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.7  1998/01/19 19:51:06  curt
+# A couple final pre-release tweaks.
+#
 # Revision 1.6  1998/01/15 21:33:33  curt
 # Assembling triangles and building a new .node file with the proper shared
 # vertices now works.  Now we just have to use the shared normals and we'll
diff --git a/Tri2obj/depend b/Tri2obj/depend
index 73c133713..06689736e 100644
--- a/Tri2obj/depend
+++ b/Tri2obj/depend
@@ -1,4 +1,4 @@
 tri2obj.o: tri2obj.c tri2obj.h ../../Src/Include/constants.h \
  ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
  ../../Src/Math/mat3.h ../../Src/Math/polar.h \
- ../../Src/Math/../Include/types.h
+ ../../Src/Math/../Include/types.h ../../Src/Scenery/tileutils.h

From 1a501b7e6c7c71e645a36edbc4b153bd66ca99fd Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 21 Jan 1998 02:55:42 +0000
Subject: [PATCH 030/283] Incorporated new make system from Bob Kuehne
 <rpk@sgi.com>.

---
 AssemTris/Makefile | 37 ++++++++++---------------------------
 FixNode/Makefile   | 46 ++++++++++------------------------------------
 FixObj/Makefile    | 40 +++++++++-------------------------------
 SplitTris/Makefile | 37 ++++++++++---------------------------
 Tools/Makefile     | 26 +++++++++++++++-----------
 Tri2obj/Makefile   | 35 +++++++++--------------------------
 6 files changed, 63 insertions(+), 158 deletions(-)

diff --git a/AssemTris/Makefile b/AssemTris/Makefile
index 3876ad272..842396e04 100644
--- a/AssemTris/Makefile
+++ b/AssemTris/Makefile
@@ -26,46 +26,29 @@
 
 TARGET = assemtris
 
-CFILES = assemtris.c ../../Src/Scenery/tileutils.c
-OFILES = $(CFILES:.c=.o)
+CFILES = assemtris.c
+LDLIBS = -lMath -lScenery -lm
 
 
-include ../make.inc
-
-
-CFLAGS = $(FG_CFLAGS) -g
+include $(FG_ROOT_SRC)/commondefs
 
 
 #---------------------------------------------------------------------------
-# Primary Targets
+# Rule for TARGET
 #---------------------------------------------------------------------------
 
-all: $(TARGET)
-
-$(TARGET): $(OFILES)
-	$(CC) $(OFILES) -o $(TARGET) ../../Src/Math/libMath.a -lm
-
-clean:
-	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
-
-realclean: clean
+$(TARGET): $(OBJECTS)
+	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
 
 
-#---------------------------------------------------------------------------
-# Secondary Targets
-#---------------------------------------------------------------------------
-
-makedepend:
-	$(CC) -MM *.c > depend
-
-include depend
-
-assemtris.o: assemtris.c
-	$(CC) $(CFLAGS) -c assemtris.c -o $@
+include $(COMMONRULES)
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/01/21 02:55:46  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
 # Revision 1.1  1998/01/15 02:45:25  curt
 # Initial revision.
 #
diff --git a/FixNode/Makefile b/FixNode/Makefile
index 236c6acc9..80e346cd3 100644
--- a/FixNode/Makefile
+++ b/FixNode/Makefile
@@ -26,55 +26,29 @@
 
 TARGET = fixnode
 
-CFILES = ../Dem2node/demparse.c fixnode.c main.c ../Dem2node/mesh.c triload.c
-OFILES = $(CFILES:.c=.o)
+CFILES = fixnode.c main.c triload.c
+LDLIBS = ../Dem2node/demparse.o ../Dem2node/mesh.o -lm
 
 
-include ../make.inc
-
-
-CFLAGS = $(FG_CFLAGS) -g
+include $(FG_ROOT_SRC)/commondefs
 
 
 #---------------------------------------------------------------------------
-# Primary Targets
+# Rule for TARGET
 #---------------------------------------------------------------------------
 
-all: $(TARGET)
-
-$(TARGET): $(OFILES)
-	$(CC) $(OFILES) -o $(TARGET)
-
-clean:
-	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
-
-realclean: clean
+$(TARGET): $(OBJECTS)
+	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
 
 
-#---------------------------------------------------------------------------
-# Secondary Targets
-#---------------------------------------------------------------------------
-
-makedepend:
-	$(CC) -MM *.c > depend
-
-include depend
-
-../Dem2node/demparse.o: ../Dem2node/demparse.c
-	$(CC) $(CFLAGS) -c ../Dem2node/demparse.c -o $@
-
-main.o: main.c
-	$(CC) $(CFLAGS) -c main.c -o $@
-
-mesh.o: mesh.c
-	$(CC) $(CFLAGS) -c mesh.c -o $@
-
-triload.o: triload.c
-	$(CC) $(CFLAGS) -c triload.c -o $@
+include $(COMMONRULES)
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/01/21 02:55:50  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
 # Revision 1.1  1997/11/27 00:17:32  curt
 # Initial revision.
 #
diff --git a/FixObj/Makefile b/FixObj/Makefile
index 0061b1213..64a5bc17d 100644
--- a/FixObj/Makefile
+++ b/FixObj/Makefile
@@ -27,50 +27,28 @@
 TARGET = fixobj
 
 CFILES = main.c obj.c
-OFILES = $(CFILES:.c=.o)
+LDLIBS = -lMath -lm
 
 
-include ../make.inc
-
-
-CFLAGS = $(FG_CFLAGS) -g
-
-LIBS = ../../Src/Math/libMath.a -lm
+include $(FG_ROOT_SRC)/commondefs
 
 
 #---------------------------------------------------------------------------
-# Primary Targets
+# Rule for TARGET
 #---------------------------------------------------------------------------
 
-all: $(TARGET)
-
-$(TARGET): $(OFILES)
-	$(CC) $(OFILES) -o $(TARGET) $(LIBS)
-
-clean:
-	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
-
-realclean: clean
+$(TARGET): $(OBJECTS)
+	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
 
 
-#---------------------------------------------------------------------------
-# Secondary Targets
-#---------------------------------------------------------------------------
-
-makedepend:
-	$(CC) -MM *.c > depend
-
-include depend
-
-main.o: main.c
-	$(CC) $(CFLAGS) -c main.c -o $@
-
-obj.o: obj.c
-	$(CC) $(CFLAGS) -c obj.c -o $@
+include $(COMMONRULES)
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/01/21 02:55:53  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
 # Revision 1.1  1997/12/08 19:28:54  curt
 # Initial revision.
 #
diff --git a/SplitTris/Makefile b/SplitTris/Makefile
index e511d7187..27313a425 100644
--- a/SplitTris/Makefile
+++ b/SplitTris/Makefile
@@ -26,46 +26,29 @@
 
 TARGET = splittris
 
-CFILES = splittris.c ../../Src/Scenery/tileutils.c
-OFILES = $(CFILES:.c=.o)
+CFILES = splittris.c
+LDLIBS = -lMath -lScenery -lm
 
 
-include ../make.inc
-
-
-CFLAGS = $(FG_CFLAGS) -g
+include $(FG_ROOT_SRC)/commondefs
 
 
 #---------------------------------------------------------------------------
-# Primary Targets
+# Rule for TARGET
 #---------------------------------------------------------------------------
 
-all: $(TARGET)
-
-$(TARGET): $(OFILES)
-	$(CC) $(OFILES) -o $(TARGET) ../../Src/Math/libMath.a -lm
-
-clean:
-	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
-
-realclean: clean
+$(TARGET): $(OBJECTS)
+	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
 
 
-#---------------------------------------------------------------------------
-# Secondary Targets
-#---------------------------------------------------------------------------
-
-makedepend:
-	$(CC) -MM *.c > depend
-
-include depend
-
-splittris.o: splittris.c
-	$(CC) $(CFLAGS) -c splittris.c -o $@
+include $(COMMONRULES)
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/01/21 02:55:55  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
 # Revision 1.2  1998/01/14 15:54:42  curt
 # Initial revision completed.
 #
diff --git a/Tools/Makefile b/Tools/Makefile
index 44eb3cdeb..d28cea3e5 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -24,26 +24,27 @@
 #---------------------------------------------------------------------------
 
 
-include make.inc
+include $(FG_ROOT_SRC)/commondefs
 
 
 SUBDIRS = AssemTris Dem2node FixNode FixObj SplitTris Stripe_u Tri2obj Triangle
+ORDEREDDIRS = $(SUBDIRS)
 
 
 all: 
-	for dir in $(SUBDIRS); do \
+	for dir in $(ORDEREDDIRS); do \
 	    ( cd $$dir; $(MAKE) ) ; \
 	done
 
 depend:
-	for dir in $(SUBDIRS); do \
+	for dir in $(ORDEREDDIRS); do \
 	    ( echo "Making depend in $$dir"; \
 	      cd $$dir; $(CC) -MM *.c > depend ) ; \
 	done
 
 Makefile-os2:
 	cat Makefile | perl mkmfos2.pl > Makefile.os2; \
-	for dir in $(SUBDIRS); do \
+	for dir in $(ORDEREDDIRS); do \
 	    ( echo "Making Makefile.os2 in $$dir"; \
 	      cat $$dir/Makefile | perl mkmfos2.pl > $$dir/Makefile.os2; \
 	      cat $$dir/depend   | perl mkmfos2.pl > $$dir/depend.os2) ; \
@@ -51,24 +52,24 @@ Makefile-os2:
 
 clean:
 	-rm -f *.os2 *~
-	for dir in $(SUBDIRS); do \
+	for dir in $(ORDEREDDIRS); do \
 	    (cd $$dir; $(MAKE) clean) ; \
 	done
 
 
 source-tar: clean
-	echo "need to fix this"
 	(cd ..; \
 	tar cvzf demtools-$(VERSION).tar.gz Tools/Makefile Tools/README \
-	Tools/TODO Tools/make.inc Tools/Dem2node Tools/FixNode Tools/FixObj \
-	Tools/Stripe_u Tools/Tri2obj Tools/Triangle Tools/mesa-e.dem)
+	Tools/TODO Tools/make.inc Tools/AssemTris Tools/Dem2node \
+	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
+	Tools/Tri2obj Tools/Triangle)
 
 source-zip: clean
-	echo "need to fix this"
 	(cd ..; \
 	zip -r demtools-$(VERSION).zip Tools/Makefile Tools/README \
-	Tools/TODO Tools/make.inc Tools/Dem2node Tools/FixNode Tools/FixObj \
-	Tools/Stripe_u Tools/Tri2obj Tools/Triangle Tools/mesa-e.dem)
+	Tools/TODO Tools/make.inc Tools/AssemTris Tools/Dem2node \
+	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
+	Tools/Tri2obj Tools/Triangle)
 
 bin-tar: all
 	echo "need to fix this"
@@ -88,6 +89,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1998/01/21 02:55:42  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
 # Revision 1.5  1998/01/14 15:55:34  curt
 # Finished splittris, started assemtris.
 #
diff --git a/Tri2obj/Makefile b/Tri2obj/Makefile
index 9cdbaaa61..abc733a89 100644
--- a/Tri2obj/Makefile
+++ b/Tri2obj/Makefile
@@ -26,46 +26,29 @@
 
 TARGET = tri2obj
 
-CFILES = tri2obj.c ../../Src/Scenery/tileutils.c
-OFILES = $(CFILES:.c=.o)
+CFILES = tri2obj.c
+LDLIBS = -lMath -lScenery -lm
 
 
-include ../make.inc
-
-
-CFLAGS = $(FG_CFLAGS) -O3 -fomit-frame-pointer -funroll-all-loops -ffast-math
+include $(FG_ROOT_SRC)/commondefs
 
 
 #---------------------------------------------------------------------------
 # Primary Targets
 #---------------------------------------------------------------------------
 
-all: $(TARGET)
-
-$(TARGET): $(OFILES)
-	$(CC) $(OFILES) -o $(TARGET) ../../Src/Math/libMath.a -lm
-
-clean:
-	rm -f *.o $(TARGET) lib*.a *.os2 *~ core
-
-realclean: clean
+$(TARGET): $(OBJECTS)
+	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
 
 
-#---------------------------------------------------------------------------
-# Secondary Targets
-#---------------------------------------------------------------------------
-
-makedepend:
-	$(CC) -MM *.c > depend
-
-include depend
-
-tri2obj.o: tri2obj.c
-	$(CC) $(CFLAGS) -c tri2obj.c -o $@
+include $(COMMONRULES)
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/01/21 02:55:56  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
 # Revision 1.4  1998/01/17 01:25:39  curt
 # Added support for shared normals.
 #

From 5b8374dbb255dab2a8de4d99ddc1057bf08a67b1 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 21 Jan 1998 17:59:05 +0000
Subject: [PATCH 031/283] Uncomment lines to remove several intermediate files.

---
 Tools/process-dem.pl | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 513530d7a..3d5f000f0 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -252,9 +252,9 @@ if ( $do_tri2obj ) {
 	    }
 	    close(OUT);
 	    
-	    # unlink("$subdir/$file.node");
-	    # unlink("$subdir/$file.node.orig");
-	    # unlink("$subdir/$file.ele");
+	    unlink("$subdir/$file.node");
+	    unlink("$subdir/$file.node.orig");
+	    unlink("$subdir/$file.ele");
 	}
     }
 }
@@ -294,7 +294,7 @@ if ( $do_strips ) {
 	    close(IN);
 	    close(OUT);
 	    
-	    # unlink("$subdir/$file");
+	    unlink("$subdir/$file");
 	}
     }
 }
@@ -328,6 +328,9 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.8  1998/01/21 17:59:05  curt
+# Uncomment lines to remove several intermediate files.
+#
 # Revision 1.7  1998/01/19 19:51:06  curt
 # A couple final pre-release tweaks.
 #

From 91d6c58aecd3613ad113d98e0b26ad516a09f1b8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 21 Jan 1998 18:35:10 +0000
Subject: [PATCH 032/283] Renamed TODO to Todo

---
 Tools/{TODO => Todo} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Tools/{TODO => Todo} (100%)

diff --git a/Tools/TODO b/Tools/Todo
similarity index 100%
rename from Tools/TODO
rename to Tools/Todo

From f389ae86de07c4106b88ed7654c05cdc3d8dedf8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 27 Jan 1998 18:36:53 +0000
Subject: [PATCH 033/283] Lots of updates to get back in sync with changes made
 over in .../Src/

---
 AssemTris/assemtris.c | 147 +++++++++++++++++++++---------------------
 SplitTris/splittris.c | 107 +++++++++++++++---------------
 Tools/Makefile        |  15 +++--
 Tools/Todo            |  11 +++-
 Tools/process-dem.pl  |   6 +-
 Tri2obj/tri2obj.c     | 143 ++++++++++++++++++++--------------------
 6 files changed, 225 insertions(+), 204 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index 523d88e4b..3873fb39c 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -31,12 +31,12 @@
 
 #include "assemtris.h"
 
-#include "../../Src/Include/constants.h"
-#include "../../Src/Include/types.h"
-#include "../../Src/Math/fg_geodesy.h"
-#include "../../Src/Math/mat3.h"
-#include "../../Src/Math/polar.h"
-#include "../../Src/Scenery/tileutils.h"
+#include <Include/fg_constants.h>
+#include <Include/fg_types.h>
+#include <Math/fg_geodesy.h>
+#include <Math/mat3.h>
+#include <Math/polar.h>
+#include <Scenery/bucketutils.h>
 
 
 int nodecount = 0;
@@ -44,9 +44,9 @@ int nodecount = 0;
 float nodes[MAX_NODES][3];
 
 
-struct bucket my_index;
-struct bucket ne_index, nw_index, sw_index, se_index;
-struct bucket north_index, south_index, east_index, west_index;
+struct fgBUCKET my_index;
+struct fgBUCKET ne_index, nw_index, sw_index, se_index;
+struct fgBUCKET north_index, south_index, east_index, west_index;
 
 
 /* return the file base name ( foo/bar/file.ext = file.ext ) */
@@ -108,26 +108,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     long int index;
 
     if ( strcmp(ext, ".sw") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&sw_index, scene_path);
-	index = gen_index(&sw_index);
+	fgBucketGenBasePath(&sw_index, scene_path);
+	index = fgBucketGenIndex(&sw_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -135,26 +135,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".se") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&se_index, scene_path);
-	index = gen_index(&se_index);
+	fgBucketGenBasePath(&se_index, scene_path);
+	index = fgBucketGenIndex(&se_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -162,26 +162,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".ne") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&ne_index, scene_path);
-	index = gen_index(&ne_index);
+	fgBucketGenBasePath(&ne_index, scene_path);
+	index = fgBucketGenIndex(&ne_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -189,26 +189,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".nw") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&nw_index, scene_path);
-	index = gen_index(&nw_index);
+	fgBucketGenBasePath(&nw_index, scene_path);
+	index = fgBucketGenIndex(&nw_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -216,14 +216,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".south") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -231,14 +231,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".north") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -246,14 +246,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".west") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -261,14 +261,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".east") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -276,8 +276,8 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".body") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -421,20 +421,20 @@ int main(int argc, char **argv) {
     }
     tmp_index = atoi(temp);
     printf("%ld\n", tmp_index);
-    parse_index(tmp_index, &my_index);
+    fgBucketParseIndex(tmp_index, &my_index);
 
     printf("bucket = %d %d %d %d\n", 
 	   my_index.lon, my_index.lat, my_index.x, my_index.y);
     /* generate the indexes of the neighbors */
-    offset_bucket(&my_index, &ne_index,  1,  1);
-    offset_bucket(&my_index, &nw_index, -1,  1);
-    offset_bucket(&my_index, &se_index,  1, -1);
-    offset_bucket(&my_index, &sw_index, -1, -1);
+    fgBucketOffset(&my_index, &ne_index,  1,  1);
+    fgBucketOffset(&my_index, &nw_index, -1,  1);
+    fgBucketOffset(&my_index, &se_index,  1, -1);
+    fgBucketOffset(&my_index, &sw_index, -1, -1);
 
-    offset_bucket(&my_index, &north_index,  0,  1);
-    offset_bucket(&my_index, &south_index,  0, -1);
-    offset_bucket(&my_index, &east_index,  1,  0);
-    offset_bucket(&my_index, &west_index, -1,  0);
+    fgBucketOffset(&my_index, &north_index,  0,  1);
+    fgBucketOffset(&my_index, &south_index,  0, -1);
+    fgBucketOffset(&my_index, &east_index,  1,  0);
+    fgBucketOffset(&my_index, &west_index, -1,  0);
 
     /*
     printf("Corner indexes = %ld %ld %ld %ld\n", 
@@ -454,11 +454,14 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.2  1998/01/15 21:33:36  curt
-/* Assembling triangles and building a new .node file with the proper shared
-/* vertices now works.  Now we just have to use the shared normals and we'll
-/* be all set.
+/* Revision 1.3  1998/01/27 18:37:00  curt
+/* Lots of updates to get back in sync with changes made over in .../Src/
 /*
+ * Revision 1.2  1998/01/15 21:33:36  curt
+ * Assembling triangles and building a new .node file with the proper shared
+ * vertices now works.  Now we just have to use the shared normals and we'll
+ * be all set.
+ *
  * Revision 1.1  1998/01/15 02:45:26  curt
  * Initial revision.
  *
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index 0ef6f9b9d..827e26746 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -34,12 +34,12 @@
 
 #include "splittris.h"
 
-#include "../../Src/Include/constants.h"
-#include "../../Src/Include/types.h"
-#include "../../Src/Math/fg_geodesy.h"
-#include "../../Src/Math/mat3.h"
-#include "../../Src/Math/polar.h"
-#include "../../Src/Scenery/tileutils.h"
+#include <Include/fg_constants.h>
+#include <Include/fg_types.h>
+#include <Math/fg_geodesy.h>
+#include <Math/mat3.h>
+#include <Math/polar.h>
+#include <Scenery/bucketutils.h>
 
 
 int nodecount, tricount;
@@ -51,8 +51,8 @@ int new_tris[MAX_TRIS][3];
 
 struct fgCartesianPoint nodes_cart[MAX_NODES];
 
-struct bucket ne_index, nw_index, sw_index, se_index;
-struct bucket north_index, south_index, east_index, west_index;
+struct fgBUCKET ne_index, nw_index, sw_index, se_index;
+struct fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
@@ -260,20 +260,20 @@ int shared_object_exists(char *basepath, char *ext) {
     long int index;
 
     if ( strcmp(ext, ".sw") == 0 ) {
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&sw_index, scene_path);
-	index = gen_index(&sw_index);
+	fgBucketGenBasePath(&sw_index, scene_path);
+	index = fgBucketGenIndex(&sw_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -281,20 +281,20 @@ int shared_object_exists(char *basepath, char *ext) {
     }
 
     if ( strcmp(ext, ".se") == 0 ) {
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&se_index, scene_path);
-	index = gen_index(&se_index);
+	fgBucketGenBasePath(&se_index, scene_path);
+	index = fgBucketGenIndex(&se_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -302,20 +302,20 @@ int shared_object_exists(char *basepath, char *ext) {
     }
 
     if ( strcmp(ext, ".ne") == 0 ) {
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&ne_index, scene_path);
-	index = gen_index(&ne_index);
+	fgBucketGenBasePath(&ne_index, scene_path);
+	index = fgBucketGenIndex(&ne_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -323,20 +323,20 @@ int shared_object_exists(char *basepath, char *ext) {
     }
 
     if ( strcmp(ext, ".nw") == 0 ) {
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&nw_index, scene_path);
-	index = gen_index(&nw_index);
+	fgBucketGenBasePath(&nw_index, scene_path);
+	index = fgBucketGenIndex(&nw_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -344,8 +344,8 @@ int shared_object_exists(char *basepath, char *ext) {
     }
 
     if ( strcmp(ext, ".south") == 0 ) {
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -353,8 +353,8 @@ int shared_object_exists(char *basepath, char *ext) {
     }
 
     if ( strcmp(ext, ".north") == 0 ) {
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -362,8 +362,8 @@ int shared_object_exists(char *basepath, char *ext) {
     }
 
     if ( strcmp(ext, ".west") == 0 ) {
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -371,8 +371,8 @@ int shared_object_exists(char *basepath, char *ext) {
     }
 
     if ( strcmp(ext, ".east") == 0 ) {
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -557,7 +557,7 @@ void dump_obj(char *basename, char *basepath) {
 
 int main(int argc, char **argv) {
     char basename[256], basepath[256], temp[256];
-    struct bucket p;
+    struct fgBUCKET p;
     long int index;
     int len;
 
@@ -577,19 +577,19 @@ int main(int argc, char **argv) {
     }
     index = atoi(temp);
     printf("%ld\n", index);
-    parse_index(index, &p);
+    fgBucketParseIndex(index, &p);
 
     printf("bucket = %d %d %d %d\n", p.lon, p.lat, p.x, p.y);
     /* generate the indexes of the neighbors */
-    offset_bucket(&p, &ne_index,  1,  1);
-    offset_bucket(&p, &nw_index, -1,  1);
-    offset_bucket(&p, &se_index,  1, -1);
-    offset_bucket(&p, &sw_index, -1, -1);
+    fgBucketOffset(&p, &ne_index,  1,  1);
+    fgBucketOffset(&p, &nw_index, -1,  1);
+    fgBucketOffset(&p, &se_index,  1, -1);
+    fgBucketOffset(&p, &sw_index, -1, -1);
 
-    offset_bucket(&p, &north_index,  0,  1);
-    offset_bucket(&p, &south_index,  0, -1);
-    offset_bucket(&p, &east_index,  1,  0);
-    offset_bucket(&p, &west_index, -1,  0);
+    fgBucketOffset(&p, &north_index,  0,  1);
+    fgBucketOffset(&p, &south_index,  0, -1);
+    fgBucketOffset(&p, &east_index,  1,  0);
+    fgBucketOffset(&p, &west_index, -1,  0);
 
     /*
     printf("Corner indexes = %ld %ld %ld %ld\n", 
@@ -609,9 +609,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.2  1998/01/14 15:54:43  curt
-/* Initial revision completed.
+/* Revision 1.3  1998/01/27 18:37:04  curt
+/* Lots of updates to get back in sync with changes made over in .../Src/
 /*
+ * Revision 1.2  1998/01/14 15:54:43  curt
+ * Initial revision completed.
+ *
  * Revision 1.1  1998/01/14 02:11:31  curt
  * Initial revision.
  *
diff --git a/Tools/Makefile b/Tools/Makefile
index d28cea3e5..dd6f7e4dc 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -59,15 +59,15 @@ clean:
 
 source-tar: clean
 	(cd ..; \
-	tar cvzf demtools-$(VERSION).tar.gz Tools/Makefile Tools/README \
-	Tools/TODO Tools/make.inc Tools/AssemTris Tools/Dem2node \
+	tar cvzf demtools-$(FG_VERSION).tar.gz Tools/Makefile Tools/README \
+	Tools/Todo Tools/make.inc Tools/AssemTris Tools/Dem2node \
 	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
 	Tools/Tri2obj Tools/Triangle)
 
 source-zip: clean
 	(cd ..; \
-	zip -r demtools-$(VERSION).zip Tools/Makefile Tools/README \
-	Tools/TODO Tools/make.inc Tools/AssemTris Tools/Dem2node \
+	zip -r demtools-$(FG_VERSION).zip Tools/Makefile Tools/README \
+	Tools/Todo Tools/make.inc Tools/AssemTris Tools/Dem2node \
 	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
 	Tools/Tri2obj Tools/Triangle)
 
@@ -75,20 +75,23 @@ bin-tar: all
 	echo "need to fix this"
 #	cp GLUT/fg0 GLUT/runfg ..
 #	(cd ../..; \
-#	tar cvzf bin-$(VERSION).tar.gz FlightGear/fgtop FlightGear/fg0 \
+#	tar cvzf bin-$(FG_VERSION).tar.gz FlightGear/fgtop FlightGear/fg0 \
 #	FlightGear/runfg FlightGear/COPYING FlightGear/Docs FlightGear/Thanks)
 
 bin-zip: 
 	echo "need to fix this"
 #	cp GLUT/fg0.exe GLUT/runfg.bat GLUT/cygwin.dll ..
 #	(cd ../..; \
-#	zip -r bin-$(VERSION).zip FlightGear/fgtop FlightGear/fg0.exe \
+#	zip -r bin-$(FG_VERSION).zip FlightGear/fgtop FlightGear/fg0.exe \
 #	FlightGear/runfg.bat FlightGear/cygwin.dll FlightGear/COPYING \
 #	FlightGear/Docs FlightGear/Thanks)
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.7  1998/01/27 18:36:53  curt
+# Lots of updates to get back in sync with changes made over in .../Src/
+#
 # Revision 1.6  1998/01/21 02:55:42  curt
 # Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
 #
diff --git a/Tools/Todo b/Tools/Todo
index d0a8ad198..81f0abad5 100644
--- a/Tools/Todo
+++ b/Tools/Todo
@@ -9,15 +9,20 @@
 1/14/98 -  Reassemble triangles using only body, shared corners, and 
            shared edges.
 
+1/19/98 -  Retro-fit tri2obj to use shared normals rather than regenerating
+           normals for shared vertices.
+
 
 --------------------------------------------------------------------------
 | Todo 
 --------------------------------------------------------------------------
 
-1/15/98 -  Retro-fit tri2obj to use shared normals rather than regenerating
-           normals for shared vertices.
-
 1/12/98 -  Try reversing cw-wound strips rather than calling glFrontFace() 
            in the display list.
 
+1/21/98 -  Generate an elevation quad tree.
+
 1/12/98 -  Generate a face adjacency matrix
+
+1/21/98 -  Remove internal shared edges and corners that are not needed
+           after an area is generated.
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 3d5f000f0..209df364b 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -189,7 +189,7 @@ if ( $do_assemtris ) {
     foreach $file ( @FILES ) {
 	chop($file);
 	if ( $file =~ m/\.1\.body$/ ) {
-	    $file =~ s/\.body$//;  # strip off the ".node"
+	    $file =~ s/\.body$//;  # strip off the ".body"
 	
 	    $command = "./AssemTris/assemtris $subdir/$file";
 	    print "Running '$command'\n";
@@ -199,6 +199,7 @@ if ( $do_assemtris ) {
 	    }
 	    close(OUT);
 	}
+	unlink("$subdir/$file.body");
     }
 }
 
@@ -328,6 +329,9 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.9  1998/01/27 18:36:54  curt
+# Lots of updates to get back in sync with changes made over in .../Src/
+#
 # Revision 1.8  1998/01/21 17:59:05  curt
 # Uncomment lines to remove several intermediate files.
 #
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index f6b7970b6..ef71af389 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -32,12 +32,12 @@
 
 #include "tri2obj.h"
 
-#include "../../Src/Include/constants.h"
-#include "../../Src/Include/types.h"
-#include "../../Src/Math/fg_geodesy.h"
-#include "../../Src/Math/mat3.h"
-#include "../../Src/Math/polar.h"
-#include "../../Src/Scenery/tileutils.h"
+#include <Include/fg_constants.h>
+#include <Include/fg_types.h>
+#include <Math/fg_geodesy.h>
+#include <Math/mat3.h>
+#include <Math/polar.h>
+#include <Scenery/bucketutils.h>
 
 
 int nodecount, tricount;
@@ -48,9 +48,9 @@ int new_tris[MAX_TRIS][3];
 
 float normals[MAX_NODES][3];
 
-struct bucket my_index;
-struct bucket ne_index, nw_index, sw_index, se_index;
-struct bucket north_index, south_index, east_index, west_index;
+struct fgBUCKET my_index;
+struct fgBUCKET ne_index, nw_index, sw_index, se_index;
+struct fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
@@ -177,26 +177,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     long int index;
 
     if ( strcmp(ext, ".sw") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&sw_index, scene_path);
-	index = gen_index(&sw_index);
+	fgBucketGenBasePath(&sw_index, scene_path);
+	index = fgBucketGenIndex(&sw_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -204,26 +204,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".se") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&se_index, scene_path);
-	index = gen_index(&se_index);
+	fgBucketGenBasePath(&se_index, scene_path);
+	index = fgBucketGenIndex(&se_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -231,26 +231,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".ne") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&ne_index, scene_path);
-	index = gen_index(&ne_index);
+	fgBucketGenBasePath(&ne_index, scene_path);
+	index = fgBucketGenIndex(&ne_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -258,26 +258,26 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".nw") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&nw_index, scene_path);
-	index = gen_index(&nw_index);
+	fgBucketGenBasePath(&nw_index, scene_path);
+	index = fgBucketGenIndex(&nw_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -285,14 +285,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".south") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&south_index, scene_path);
-	index = gen_index(&south_index);
+	fgBucketGenBasePath(&south_index, scene_path);
+	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -300,14 +300,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".north") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&north_index, scene_path);
-	index = gen_index(&north_index);
+	fgBucketGenBasePath(&north_index, scene_path);
+	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -315,14 +315,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".west") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&west_index, scene_path);
-	index = gen_index(&west_index);
+	fgBucketGenBasePath(&west_index, scene_path);
+	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -330,14 +330,14 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".east") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
 	}
-	gen_base_path(&east_index, scene_path);
-	index = gen_index(&east_index);
+	fgBucketGenBasePath(&east_index, scene_path);
+	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -345,8 +345,8 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
     }
 
     if ( strcmp(ext, ".body") == 0 ) {
-	gen_base_path(&my_index, scene_path);
-	index = gen_index(&my_index);
+	fgBucketGenBasePath(&my_index, scene_path);
+	index = fgBucketGenIndex(&my_index);
 	sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index);
 	if ( file_exists(file) ) {
 	    return(1);
@@ -612,20 +612,20 @@ int main(int argc, char **argv) {
     }
     tmp_index = atoi(temp);
     printf("%ld\n", tmp_index);
-    parse_index(tmp_index, &my_index);
+    fgBucketParseIndex(tmp_index, &my_index);
 
     printf("bucket = %d %d %d %d\n", 
 	   my_index.lon, my_index.lat, my_index.x, my_index.y);
     /* generate the indexes of the neighbors */
-    offset_bucket(&my_index, &ne_index,  1,  1);
-    offset_bucket(&my_index, &nw_index, -1,  1);
-    offset_bucket(&my_index, &se_index,  1, -1);
-    offset_bucket(&my_index, &sw_index, -1, -1);
+    fgBucketOffset(&my_index, &ne_index,  1,  1);
+    fgBucketOffset(&my_index, &nw_index, -1,  1);
+    fgBucketOffset(&my_index, &se_index,  1, -1);
+    fgBucketOffset(&my_index, &sw_index, -1, -1);
 
-    offset_bucket(&my_index, &north_index,  0,  1);
-    offset_bucket(&my_index, &south_index,  0, -1);
-    offset_bucket(&my_index, &east_index,  1,  0);
-    offset_bucket(&my_index, &west_index, -1,  0);
+    fgBucketOffset(&my_index, &north_index,  0,  1);
+    fgBucketOffset(&my_index, &south_index,  0, -1);
+    fgBucketOffset(&my_index, &east_index,  1,  0);
+    fgBucketOffset(&my_index, &west_index, -1,  0);
 
     /* load the input data files */
     triload(basename, basepath);
@@ -638,9 +638,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.8  1998/01/17 01:25:39  curt
-/* Added support for shared normals.
+/* Revision 1.9  1998/01/27 18:37:04  curt
+/* Lots of updates to get back in sync with changes made over in .../Src/
 /*
+ * Revision 1.8  1998/01/17 01:25:39  curt
+ * Added support for shared normals.
+ *
  * Revision 1.7  1998/01/12 02:42:00  curt
  * Average up to five triangles per vertex instead of three.
  *

From 2b1b396ef5e6fb0cdfcd3c36e06d0c6784a828ba Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 31 Jan 1998 00:41:19 +0000
Subject: [PATCH 034/283] Made a few changes converting floats to doubles.

---
 AssemTris/assemtris.c | 11 +++++++----
 FixObj/obj.c          | 15 +++++++++------
 FixObj/obj.h          | 11 +++++++----
 SplitTris/splittris.c |  9 ++++++---
 Tools/Makefile        | 15 +++++++++------
 Tools/Todo            |  5 +++++
 Tri2obj/tri2obj.c     | 19 ++++++++++++-------
 7 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index 3873fb39c..e1e1413a1 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -41,7 +41,7 @@
 
 int nodecount = 0;
 
-float nodes[MAX_NODES][3];
+double nodes[MAX_NODES][3];
 
 
 struct fgBUCKET my_index;
@@ -315,7 +315,7 @@ void read_nodes(FILE *fp) {
 
     while ( fgets(line, 250, fp) != NULL ) {
 	if ( strncmp(line, "gdn ", 4) == 0 ) {
-	    sscanf(line, "gdn %f %f %f\n", &nodes[nodecount][0], 
+	    sscanf(line, "gdn %lf %lf %lf\n", &nodes[nodecount][0], 
 		   &nodes[nodecount][1], &nodes[nodecount][2]);
 	    /*
 	    printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
@@ -454,9 +454,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.3  1998/01/27 18:37:00  curt
-/* Lots of updates to get back in sync with changes made over in .../Src/
+/* Revision 1.4  1998/01/31 00:41:23  curt
+/* Made a few changes converting floats to doubles.
 /*
+ * Revision 1.3  1998/01/27 18:37:00  curt
+ * Lots of updates to get back in sync with changes made over in .../Src/
+ *
  * Revision 1.2  1998/01/15 21:33:36  curt
  * Assembling triangles and building a new .node file with the proper shared
  * vertices now works.  Now we just have to use the shared normals and we'll
diff --git a/FixObj/obj.c b/FixObj/obj.c
index 01d885fdb..fde62bbbc 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -33,8 +33,8 @@
 
 
 /* what do ya' know, here's some global variables */
-float nodes[MAXNODES][3];
-float normals[MAXNODES][3];
+double nodes[MAXNODES][3];
+double normals[MAXNODES][3];
 
 int ccw_list[MAXNODES];
 int ccw_list_ptr;
@@ -175,7 +175,7 @@ void obj_fix(char *infile, char *outfile) {
 	    /* save vertex to memory and output to file */
             if ( ncount < MAXNODES ) {
                 /* printf("vertex = %s", line); */
-                sscanf(line, "v %f %f %f\n", 
+                sscanf(line, "v %lf %lf %lf\n", 
                        &nodes[ncount][0], &nodes[ncount][1], &nodes[ncount][2]);
 		fprintf(out, "v %.2f %.2f %.2f\n", 
 		       nodes[ncount][0], nodes[ncount][1], nodes[ncount][2]);
@@ -188,7 +188,7 @@ void obj_fix(char *infile, char *outfile) {
 	    /* save vertex normals to memory and output to file */
             if ( vncount < MAXNODES ) {
                 /* printf("vertex normal = %s", line); */
-                sscanf(line, "vn %f %f %f\n", 
+                sscanf(line, "vn %lf %lf %lf\n", 
                        &normals[vncount][0], &normals[vncount][1], 
                        &normals[vncount][2]);
 		fprintf(out, "vn %.4f %.4f %.4f\n", normals[vncount][0], 
@@ -288,9 +288,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.3  1998/01/19 19:51:07  curt
-/* A couple final pre-release tweaks.
+/* Revision 1.4  1998/01/31 00:41:25  curt
+/* Made a few changes converting floats to doubles.
 /*
+ * Revision 1.3  1998/01/19 19:51:07  curt
+ * A couple final pre-release tweaks.
+ *
  * Revision 1.2  1998/01/09 23:03:12  curt
  * Restructured to split 1deg x 1deg dem's into 64 subsections.
  *
diff --git a/FixObj/obj.h b/FixObj/obj.h
index 54689de06..954a088a7 100644
--- a/FixObj/obj.h
+++ b/FixObj/obj.h
@@ -30,8 +30,8 @@
 
 #define MAXNODES 100000
 
-extern float nodes[MAXNODES][3];
-extern float normals[MAXNODES][3];
+extern double nodes[MAXNODES][3];
+extern double normals[MAXNODES][3];
 extern int stack[MAXNODES];
 
 
@@ -43,9 +43,12 @@ void obj_fix(char *infile, char *outfile);
 
 
 /* $Log$
-/* Revision 1.2  1998/01/09 23:03:13  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
+/* Revision 1.3  1998/01/31 00:41:25  curt
+/* Made a few changes converting floats to doubles.
 /*
+ * Revision 1.2  1998/01/09 23:03:13  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
  * Revision 1.1  1997/12/08 19:28:55  curt
  * Initial revision.
  *
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index 827e26746..3646e22cc 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -82,7 +82,7 @@ void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2,
 		 struct fgCartesianPoint p3, double normal[3])
 {
     double v1[3], v2[3];
-    float temp;
+    double temp;
 
     v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
     v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
@@ -609,9 +609,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.3  1998/01/27 18:37:04  curt
-/* Lots of updates to get back in sync with changes made over in .../Src/
+/* Revision 1.4  1998/01/31 00:41:26  curt
+/* Made a few changes converting floats to doubles.
 /*
+ * Revision 1.3  1998/01/27 18:37:04  curt
+ * Lots of updates to get back in sync with changes made over in .../Src/
+ *
  * Revision 1.2  1998/01/14 15:54:43  curt
  * Initial revision completed.
  *
diff --git a/Tools/Makefile b/Tools/Makefile
index dd6f7e4dc..893088b5b 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -60,16 +60,16 @@ clean:
 source-tar: clean
 	(cd ..; \
 	tar cvzf demtools-$(FG_VERSION).tar.gz Tools/Makefile Tools/README \
-	Tools/Todo Tools/make.inc Tools/AssemTris Tools/Dem2node \
-	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
-	Tools/Tri2obj Tools/Triangle)
+	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
+        Tools/Dem2node Tools/FixNode Tools/FixObj Tools/SplitTris \
+	Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
 
 source-zip: clean
 	(cd ..; \
 	zip -r demtools-$(FG_VERSION).zip Tools/Makefile Tools/README \
-	Tools/Todo Tools/make.inc Tools/AssemTris Tools/Dem2node \
-	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
-	Tools/Tri2obj Tools/Triangle)
+	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
+        Tools/Dem2node Tools/FixNode Tools/FixObj Tools/SplitTris \
+	Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
 
 bin-tar: all
 	echo "need to fix this"
@@ -89,6 +89,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.8  1998/01/31 00:41:19  curt
+# Made a few changes converting floats to doubles.
+#
 # Revision 1.7  1998/01/27 18:36:53  curt
 # Lots of updates to get back in sync with changes made over in .../Src/
 #
diff --git a/Tools/Todo b/Tools/Todo
index 81f0abad5..96d0bd539 100644
--- a/Tools/Todo
+++ b/Tools/Todo
@@ -20,6 +20,11 @@
 1/12/98 -  Try reversing cw-wound strips rather than calling glFrontFace() 
            in the display list.
 
+           gnuplot> set label "1" at 1,1
+           gnuplot> set label "2" at 2,2
+
+           gnuplot> plot x
+
 1/21/98 -  Generate an elevation quad tree.
 
 1/12/98 -  Generate a face adjacency matrix
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index ef71af389..93fb4f9b6 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -46,7 +46,7 @@ struct fgCartesianPoint nodes[MAX_NODES];
 int tris[MAX_TRIS][3];
 int new_tris[MAX_TRIS][3];
 
-float normals[MAX_NODES][3];
+double normals[MAX_NODES][3];
 
 struct fgBUCKET my_index;
 struct fgBUCKET ne_index, nw_index, sw_index, se_index;
@@ -80,13 +80,13 @@ void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2,
 		 struct fgCartesianPoint p3, double normal[3])
 {
     double v1[3], v2[3];
-    float temp;
+    double temp;
 
     v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
     v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
 
     MAT3cross_product(normal, v1, v2);
-    MAT3_NORMALIZE_VEC(normal,temp);
+    MAT3_NORMALIZE_VEC(normal, temp);
 
 /*  printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
 }
@@ -363,8 +363,10 @@ void read_normals(FILE *fp) {
 
     while ( fgets(line, 250, fp) != NULL ) {
 	if ( strncmp(line, "vn ", 3) == 0 ) {
-	    sscanf(line, "vn %f %f %f\n", &normals[normalcount][0], 
-		   &normals[normalcount][1], &normals[normalcount][2]);
+	    sscanf( line, "vn %lf %lf %lf\n", 
+		    &normals[normalcount][0], 
+		    &normals[normalcount][1], 
+		    &normals[normalcount][2] );
 	    /*
 	    printf("read_normals(%d) %.2f %.2f %.2f %s", normalcount, 
 		   normals[normalcount][0], normals[normalcount][1], 
@@ -638,9 +640,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.9  1998/01/27 18:37:04  curt
-/* Lots of updates to get back in sync with changes made over in .../Src/
+/* Revision 1.10  1998/01/31 00:41:27  curt
+/* Made a few changes converting floats to doubles.
 /*
+ * Revision 1.9  1998/01/27 18:37:04  curt
+ * Lots of updates to get back in sync with changes made over in .../Src/
+ *
  * Revision 1.8  1998/01/17 01:25:39  curt
  * Added support for shared normals.
  *

From bd693b85829ffffc63e97238d53a2976dcaa0c08 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 1 Feb 1998 03:42:26 +0000
Subject: [PATCH 035/283] Modifications to handle compressed dem files.

---
 Tools/process-dem.pl | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 209df364b..6a692b22f 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -81,7 +81,11 @@ if ( $error < 0.5 ) {
 #     irregularly fitted vertices
 
 if ( $do_demfit ) {
-    $command = "./Dem2node/demfit $ENV{FG_ROOT} $dem_file $error";
+    if ( $dem_file =~ m/.gz$/ ) {
+	$command = "gzip -dc $dem_file | ./Dem2node/demfit $ENV{FG_ROOT} - $error";
+    } else {
+	$command = "./Dem2node/demfit $ENV{FG_ROOT} $dem_file $error";
+    }
 
     print "Running '$command'\n";
 
@@ -132,7 +136,11 @@ if ( $do_triangle_1 ) {
 #     fixed file.1.node
 
 if ( $do_fixnode ) {
-    $command = "./FixNode/fixnode $dem_file $subdir";
+    if ( $dem_file =~ m/.gz$/ ) {
+	$command = "gzip -dc $dem_file | ./FixNode/fixnode - $subdir";
+    } else {
+	$command = "./FixNode/fixnode $dem_file $subdir";
+    }
     print "Running '$command'\n";
     open(OUT, "$command |");
     while ( <OUT> ) {
@@ -329,6 +337,9 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.10  1998/02/01 03:42:26  curt
+# Modifications to handle compressed dem files.
+#
 # Revision 1.9  1998/01/27 18:36:54  curt
 # Lots of updates to get back in sync with changes made over in .../Src/
 #

From b61908b6caad9323c238f22d26dda5fdbb2e9789 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 2 Mar 1998 23:31:00 +0000
Subject: [PATCH 036/283] Initial revision.

---
 DemRaw2ascii/Makefile |  51 ++++++++
 DemRaw2ascii/main.c   |  80 ++++++++++++
 DemRaw2ascii/rawdem.c | 297 ++++++++++++++++++++++++++++++++++++++++++
 DemRaw2ascii/rawdem.h |  80 ++++++++++++
 4 files changed, 508 insertions(+)
 create mode 100644 DemRaw2ascii/Makefile
 create mode 100644 DemRaw2ascii/main.c
 create mode 100644 DemRaw2ascii/rawdem.c
 create mode 100644 DemRaw2ascii/rawdem.h

diff --git a/DemRaw2ascii/Makefile b/DemRaw2ascii/Makefile
new file mode 100644
index 000000000..1a11a998f
--- /dev/null
+++ b/DemRaw2ascii/Makefile
@@ -0,0 +1,51 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started February 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+TARGET = raw2ascii
+
+CFILES = main.c rawdem.c
+LDLIBS = -lm
+
+
+include $(FG_ROOT_SRC)/commondefs
+
+
+#---------------------------------------------------------------------------
+# Rule for TARGET
+#---------------------------------------------------------------------------
+
+$(TARGET): $(OBJECTS)
+	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
+
+
+include $(COMMONRULES)
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/03/02 23:31:00  curt
+# Initial revision.
+#
diff --git a/DemRaw2ascii/main.c b/DemRaw2ascii/main.c
new file mode 100644
index 000000000..08ccd42ec
--- /dev/null
+++ b/DemRaw2ascii/main.c
@@ -0,0 +1,80 @@
+/* main.c -- main loop
+ *
+ * Written by Curtis Olson, started February 1998.
+ *
+ * Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "rawdem.h"
+
+
+int main(int argc, char **argv) {
+    fgRAWDEM raw;
+    char basename[256], output_dir[256], hdr_file[256], dem_file[256];
+    int i;
+
+    if ( argc != 3 ) {
+	printf("Usage: %s <input_file_basename> <output_dir>\n", argv[0]);
+	exit(-1);
+    }
+
+    /* get basename */
+    strcpy(basename, argv[1]);
+
+    /* get output dir */
+    strcpy(output_dir, argv[2]);
+
+    /* generate header file name */
+    strcpy(hdr_file, basename);
+    strcat(hdr_file, ".HDR");
+
+    /* generate input file name (raw dem) */
+    strcpy(dem_file, basename);
+    strcat(dem_file, ".DEM");
+    
+    printf("Header file = %s  Input file = %s\n", hdr_file, dem_file);
+    printf("Output Directory = %s\n", output_dir);
+
+    /* scan the header file and extract important values */
+    rawReadDemHdr(&raw, hdr_file);
+
+    /* open up the raw data file */
+    rawOpenDemFile(&raw, dem_file);
+
+    for ( i = 41; i <= 90; i++ ) {
+	rawReadStrip(&raw, i);
+    }
+
+    /* close the raw data file */
+    rawCloseDemFile(&raw);
+
+    return(0);
+}
+
+
+/* $Log$
+/* Revision 1.1  1998/03/02 23:31:01  curt
+/* Initial revision.
+/*
+ */
diff --git a/DemRaw2ascii/rawdem.c b/DemRaw2ascii/rawdem.c
new file mode 100644
index 000000000..1d24888b1
--- /dev/null
+++ b/DemRaw2ascii/rawdem.c
@@ -0,0 +1,297 @@
+/* rawdem.c -- library of routines for processing raw dem files (30 arcsec)
+ *
+ * Written by Curtis Olson, started February 1998.
+ *
+ * Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <math.h>      /* rint() */
+#include <stdio.h>
+#include <stdlib.h>    /* atoi() atof() */
+#include <string.h>    /* swab() */
+
+#include <sys/types.h> /* open() */
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>    /* close() */
+
+#include "rawdem.h"
+
+
+/* Read the DEM header to determine various key parameters for this
+ * DEM file */
+void rawReadDemHdr( fgRAWDEM *raw, char *hdr_file ) {
+    FILE *hdr;
+    char line[256], key[256], value[256];
+    int i, len, offset;
+    double tmp;
+
+    if ( (hdr = fopen(hdr_file, "r")) == NULL ) {
+	printf("Error opening DEM header file: %s\n", hdr_file);
+	exit(-1);
+    }
+
+    /* process each line */
+    while ( (fgets(line, 256, hdr) != NULL) ) {
+	/* printf("%s", line); */
+	len = strlen(line);
+
+	/* extract key */
+	i = 0;
+	while ( (line[i] != ' ') && (i < len) ) {
+	    key[i] = line[i];
+	    i++;
+	}
+	key[i] = '\0';
+
+	/* skip middle space */
+	while ( (line[i] == ' ') && (i < len) ) {
+	    i++;
+	}
+	offset = i;
+
+	/* extract value */
+	while ( (line[i] != '\n') && (i < len) ) {
+	    value[i-offset] = line[i];
+	    i++;
+	}
+	value[i-offset] = '\0';
+	/* printf("key='%s'  value='%s'\n", key, value); */
+
+	if ( strcmp(key, "NROWS") == 0 ) {
+	    raw->nrows = atoi(value);
+	} else if ( strcmp(key, "NCOLS") == 0 ) {
+	    raw->ncols = atoi(value);
+	} else if ( strcmp(key, "ULXMAP") == 0 ) {
+	    tmp = atof(value);
+	    raw->ulxmap = (int)rint(tmp * 3600.0); /* convert to arcsec */
+	} else if ( strcmp(key, "ULYMAP") == 0 ) {
+	    tmp = atof(value);
+	    raw->ulymap = (int)rint(tmp * 3600.0); /* convert to arcsec */
+	} else if ( strcmp(key, "XDIM") == 0 ) {
+	    tmp = atof(value);
+	    raw->xdim = (int)rint(tmp * 3600.0);   /* convert to arcsec */
+	} else if ( strcmp(key, "YDIM") == 0 ) {
+	    tmp = atof(value);
+	    raw->ydim = (int)rint(tmp * 3600.0);   /* convert to arcsec */
+	} else {
+	    /* ignore for now */
+	}
+    }
+
+    raw->rootx = raw->ulxmap - (raw->xdim / 2);
+    raw->rooty = raw->ulymap + (raw->ydim / 2);
+
+    printf("%d %d %d %d %d %d %d %d\n", raw->nrows, raw->ncols,
+           raw->ulxmap, raw->ulymap, raw->rootx, raw->rooty, raw->xdim,
+	   raw->ydim);
+}
+
+
+/* Open a raw DEM file. */
+void rawOpenDemFile( fgRAWDEM *raw, char *raw_dem_file ) {
+    printf("Opening Raw DEM file: %s\n", raw_dem_file);
+    if ( (raw->fd = open(raw_dem_file ,O_RDONLY)) == -1 ) {
+	printf("Error opening Raw DEM file: %s\n", raw_dem_file);
+	exit(-1);
+    }
+}
+
+
+/* Close a raw DEM file. */
+void rawCloseDemFile( fgRAWDEM *raw ) {
+    close(raw->fd);
+}
+
+
+/* Advance file pointer position to correct latitude (row) */
+void rawAdvancePosition( fgRAWDEM *raw, int arcsec ) {
+    long offset, result;
+
+    offset = 2 * raw->ncols * ( arcsec  / raw->ydim );
+
+    if ( (result = lseek(raw->fd, offset, SEEK_SET)) == -1 ) {
+	printf("Error lseek filed trying to offset by %ld\n", offset);
+	exit(-1);
+    }
+
+    printf("Successful seek ahead of %ld bytes\n", result);
+}
+
+
+/* Read the next row of data */
+void rawReadNextRow( fgRAWDEM *raw, int index ) {
+    char buf[MAX_COLS_X_2];
+    int i, result;
+
+    if ( raw->ncols > MAX_ROWS ) {
+	printf("Error, buf needs to be bigger in rawReadNextRow()\n");
+	exit(-1);
+    }
+
+    /* printf("Attempting to read %d bytes\n", 2 * raw->ncols); */
+    result = read(raw->fd, buf, 2 * raw->ncols);
+    /* printf("Read %d bytes\n", result); */
+
+    /* reverse byte order */
+    /* it would be nice to test in advance some how if we need to do
+     * this */
+    /* swab(frombuf, tobuf, 2 * raw->ncols); */
+
+    for ( i = 0; i < raw->ncols; i++ ) {
+	/* printf("hi = %d  lo = %d\n", buf[2*i], buf[2*i + 1]); */
+	raw->strip[index][i] = ( (buf[2*i] + 1) << 8 ) + buf[2*i + 1];
+    }
+}
+
+
+/* Convert from pixel centered values to pixel corner values.  This is
+   accomplished by taking the average of the closes center nodes.  In
+   the following diagram "x" marks the data point location:
+
+   +-----+        x-----x
+   |     |        |     |
+   |  x  |  ===>  |     |
+   |     |        |     |
+   +-----+        x-----x
+   
+   */
+void rawConvertCenter2Edge( fgRAWDEM *raw ) {
+    int i, j;
+
+    /* derive corner nodes */
+    raw->edge[0][0]     = raw->center[0][0];
+    raw->edge[120][0]   = raw->center[119][0];
+    raw->edge[120][120] = raw->center[119][119];
+    raw->edge[0][120]   = raw->center[0][119];
+
+    /* derive edge nodes */
+    for ( i = 1; i < 120; i++ ) {
+	raw->edge[i][0] = (raw->center[i-1][0] + raw->center[i][0]) / 2.0;
+	raw->edge[i][120] = (raw->center[i-1][119] + raw->center[i][119]) / 2.0;
+	raw->edge[0][i] = (raw->center[0][i-1] + raw->center[0][i]) / 2.0;
+	raw->edge[120][i] = (raw->center[119][i-1] + raw->center[119][i]) / 2.0;
+    }
+
+    /* derive internal nodes */
+    for ( j = 1; j < 120; j++ ) {
+	for ( i = 1; i < 120; i++ ) {
+	    raw->edge[i][j] = ( raw->center[i-1][j-1] + 
+				raw->center[i]  [j-1] +
+				raw->center[i]  [j]   +
+				raw->center[i-1][j] ) / 4;
+	}
+    }
+}
+
+
+/* Dump out the ascii format DEM file */
+void rawDumpAsciiDEM( fgRAWDEM *raw ) {
+}
+
+
+/* Read a horizontal strip of (1 vertical degree) from the raw DEM
+ * file specified by the upper latitude of the stripe specified in
+ * degrees */
+void rawReadStrip( fgRAWDEM *raw, int lat_degrees ) {
+    int lat, yrange;
+    int i, j, index, row, col;
+    int min = 0, max = 0;
+    int span, num_degrees, tile_width;
+    int xstart, xend;
+
+    /* convert to arcsec */
+    lat = lat_degrees * 3600;
+
+    printf("Max Latitude = %d arcsec\n", lat);
+
+    /* validity check ... */
+    if ( (lat > raw->rooty) || 
+	 (lat < (raw->rooty - raw->nrows * raw->ydim + 1)) ) {
+	printf("Latitude out of range for this DEM file\n");
+	return;
+    }
+
+    printf ("Reading strip starting at %d (top and working down)\n", lat);
+
+    /* advance to the correct latitude */
+    rawAdvancePosition(raw, (raw->rooty - lat));
+
+    /* printf("short = %d\n", sizeof(short)); */
+
+    yrange = 3600 / raw->ydim;
+
+    for ( i = 0; i < yrange; i++ ) {
+	index = yrange - i - 1;
+	/* printf("About to read into row %d\n", index); */
+	rawReadNextRow(raw, index);
+
+	for ( j = 0; j < raw->ncols; j++ ) {
+	    if ( raw->strip[index][j] == -9999 ) {
+		/* map ocean to 0 for now */
+		raw->strip[index][j] = 0;
+	    } 
+
+	    if ( raw->strip[index][j] < min) {
+		min = raw->strip[index][j];
+	    }
+
+	    if ( raw->strip[index][j] > max) {
+		max = raw->strip[index][j];
+	    }
+	}
+    }
+    printf("min = %d  max = %d\n", min, max);
+
+    /* extract individual tiles from the strip */
+    span = raw->ncols * raw->xdim;
+    num_degrees = span / 3600;
+    tile_width = raw->ncols / num_degrees;
+    printf("span = %d  num_degrees = %d  width = %d\n", 
+	   span, num_degrees, tile_width);
+
+    for ( i = 0; i < num_degrees; i++ ) {
+	xstart = i * tile_width;
+	xend = xstart + 120;
+
+	for ( row = 0; row < yrange; row++ ) {
+	    for ( col = xstart; col < xend; col++ ) {
+		/* Copy from strip to pixel centered tile.  Yep,
+                 * row/col are reversed here.  raw->strip is backwards
+                 * for convenience.  I am converting to [x,y] now. */
+		raw->center[col-xstart][row] = raw->strip[row][col];
+	    }
+	}
+
+	/* Convert from pixel centered to pixel edge values */
+	rawConvertCenter2Edge(raw);
+
+	/* Dump out the ascii format DEM file */
+	rawDumpAsciiDEM(raw);
+    }
+}
+
+
+/* $Log$
+/* Revision 1.1  1998/03/02 23:31:01  curt
+/* Initial revision.
+/*
+ */
diff --git a/DemRaw2ascii/rawdem.h b/DemRaw2ascii/rawdem.h
new file mode 100644
index 000000000..1bdb8e16c
--- /dev/null
+++ b/DemRaw2ascii/rawdem.h
@@ -0,0 +1,80 @@
+/* rawdem.h -- library of routines for processing raw dem files (30 arcsec)
+ *
+ * Written by Curtis Olson, started February 1998.
+ *
+ * Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#ifndef _RAWDEM_H
+#define _RAWDEM_H
+
+
+#define MAX_ROWS 6000
+#define MAX_COLS 7200
+#define MAX_COLS_X_2 14400
+
+typedef struct {
+    /* header info */
+    int nrows;       /* number of rows */
+    int ncols;       /* number of cols */
+    int ulxmap;      /* X coord of center of upper left pixel in arcsec */
+    int ulymap;      /* Y coord of center of upper left pixel in arcsec */
+    int rootx;       /* X coord of upper left *edge* of DEM region in degrees */
+    int rooty;       /* Y coord of upper left *edge* of DEM region in degrees */
+    int xdim;        /* X dimension of a pixel */
+    int ydim;        /* Y dimension of a pixel */
+
+    /* file ptr */
+    int fd;          /* Raw DEM file descriptor */
+
+    /* storage area for a 1 degree high strip of data.  Note, for
+     * convenience this is in y,x order */
+    short strip[120][MAX_ROWS];
+
+    short center[120][120];  /* tile with data taken at center of pixel */
+    float edge[121][121];    /* tile with data converted to corners */
+} fgRAWDEM;
+
+
+/* Read the DEM header to determine various key parameters for this
+ * DEM file */
+void rawReadDemHdr( fgRAWDEM *raw, char *hdr_file );
+
+/* Open a raw DEM file. */
+void rawOpenDemFile( fgRAWDEM *raw, char *raw_dem_file );
+
+/* Close a raw DEM file. */
+void rawCloseDemFile( fgRAWDEM *raw );
+
+/* Read a horizontal strip of (1 vertical degree) from the raw DEM
+ * file specified by the upper latitude of the stripe specified in
+ * degrees */
+void rawReadStrip( fgRAWDEM *raw, int lat );
+
+
+#endif /* _RAWDEM_H */
+
+
+/* $Log$
+/* Revision 1.1  1998/03/02 23:31:02  curt
+/* Initial revision.
+/*
+ */

From f0ff68edba208b15321984e02c679a635bab4da7 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 01:21:17 +0000
Subject: [PATCH 037/283] Added DemRaw2Ascii

---
 Tools/Makefile | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Tools/Makefile b/Tools/Makefile
index 893088b5b..15a75ef91 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,7 +27,8 @@
 include $(FG_ROOT_SRC)/commondefs
 
 
-SUBDIRS = AssemTris Dem2node FixNode FixObj SplitTris Stripe_u Tri2obj Triangle
+SUBDIRS = AssemTris Dem2node DemRaw2Ascii FixNode FixObj SplitTris Stripe_u \
+	Tri2obj Triangle
 ORDEREDDIRS = $(SUBDIRS)
 
 
@@ -39,7 +40,7 @@ all:
 depend:
 	for dir in $(ORDEREDDIRS); do \
 	    ( echo "Making depend in $$dir"; \
-	      cd $$dir; $(CC) -MM *.c > depend ) ; \
+	      cd $$dir; $(CC) $(CFLAGS) -M *.c > depend ) ; \
 	done
 
 Makefile-os2:
@@ -89,6 +90,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.9  1998/03/03 01:21:17  curt
+# Added DemRaw2Ascii
+#
 # Revision 1.8  1998/01/31 00:41:19  curt
 # Made a few changes converting floats to doubles.
 #

From 524ec03927060741cab9c4b5307204a86bdcb21a Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 02:04:01 +0000
Subject: [PATCH 038/283] Starting DEM Ascii format output routine.

---
 DemRaw2ascii/rawdem.c | 142 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 140 insertions(+), 2 deletions(-)

diff --git a/DemRaw2ascii/rawdem.c b/DemRaw2ascii/rawdem.c
index 1d24888b1..4004a9eed 100644
--- a/DemRaw2ascii/rawdem.c
+++ b/DemRaw2ascii/rawdem.c
@@ -205,6 +205,141 @@ void rawConvertCenter2Edge( fgRAWDEM *raw ) {
 
 /* Dump out the ascii format DEM file */
 void rawDumpAsciiDEM( fgRAWDEM *raw ) {
+    char outfile[256];
+    /* Generate output file name */
+    
+    
+    /* Dump the "A" record */
+
+    /* get the name field (144 characters) */
+    for ( i = 0; i < 144; i++ ) {
+        name[i] = fgetc(fd);
+    }
+    name[i+1] = '\0';
+
+    /* clean off the whitespace at the end */
+    for ( i = strlen(name)-2; i > 0; i-- ) {
+        if ( !isspace(name[i]) ) {
+            i=0;
+        } else {
+            name[i] = '\0'; 
+        }
+    }
+    printf("    Quad name field: %s\n", name);
+
+    /* get quadrangle id (now part of previous section  */
+    /* next_token(fd, dem_quadrangle); */
+    /* printf("    Quadrangle = %s\n", dem_quadrangle); */
+
+    /* DEM level code, 3 reflects processing by DMA */
+    inum = next_int(fd);
+    printf("    DEM level code = %d\n", inum);
+
+    /* Pattern code, 1 indicates a regular elevation pattern */
+    inum = next_int(fd);
+    printf("    Pattern code = %d\n", inum);
+
+    /* Planimetric reference system code, 0 indicates geographic 
+     * coordinate system. */
+    inum = next_int(fd);
+    printf("    Planimetric reference code = %d\n", inum);
+
+    /* Zone code */
+    inum = next_int(fd);
+    printf("    Zone code = %d\n", inum);
+
+    /* Map projection parameters (ignored) */
+    for ( i = 0; i < 15; i++ ) {
+        dnum = next_double(fd);
+        /* printf("%d: %f\n",i,dnum); */
+    }
+
+    /* Units code, 3 represents arc-seconds as the unit of measure for
+     * ground planimetric coordinates throughout the file. */
+    inum = next_int(fd);
+    if ( inum != 3 ) {
+        printf("    Unknown (X,Y) units code = %d!\n", inum);
+        exit(-1);
+    }
+
+    /* Units code; 2 represents meters as the unit of measure for
+     * elevation coordinates throughout the file. */
+    inum = next_int(fd);
+    if ( inum != 2 ) {
+        printf("    Unknown (Z) units code = %d!\n", inum);
+        exit(-1);
+    }
+
+    /* Number (n) of sides in the polygon which defines the coverage of
+     * the DEM file (usually equal to 4). */
+    inum = next_int(fd);
+    if ( inum != 4 ) {
+        printf("    Unknown polygon dimension = %d!\n", inum);
+        exit(-1);
+    }
+
+    /* Ground coordinates of bounding box in arc-seconds */
+    dem_x1 = m->originx = next_exp(fd);
+    dem_y1 = m->originy = next_exp(fd);
+    printf("    Origin = (%.2f,%.2f)\n", m->originx, m->originy);
+
+    dem_x2 = next_exp(fd);
+    dem_y2 = next_exp(fd);
+
+    dem_x3 = next_exp(fd);
+    dem_y3 = next_exp(fd);
+
+    dem_x4 = next_exp(fd);
+    dem_y4 = next_exp(fd);
+
+    /* Minimum/maximum elevations in meters */
+    dem_z1 = next_exp(fd);
+    dem_z2 = next_exp(fd);
+    printf("    Elevation range %.4f %.4f\n", dem_z1, dem_z2);
+
+    /* Counterclockwise angle from the primary axis of ground
+     * planimetric referenced to the primary axis of the DEM local
+     * reference system. */
+    next_token(fd, token);
+
+    /* Accuracy code; 0 indicates that a record of accuracy does not
+     * exist and that no record type C will follow. */
+    /* DEM spacial resolution.  Usually (3,3,1) (3,6,1) or (3,9,1)
+     * depending on latitude */
+    /* I will eventually have to do something with this for data at
+     * higher latitudes */
+    next_token(fd, token);
+    printf("    accuracy & spacial resolution string = %s\n", token);
+    i = strlen(token);
+    printf("    length = %d\n", i);
+
+    ptr = token + i - 12;
+    printf("    last field = %s = %.2f\n", ptr, atof(ptr));
+    ptr[0] = '\0';
+
+    ptr = ptr - 12;
+    m->col_step = atof(ptr);
+    printf("    last field = %s = %.2f\n", ptr, m->row_step);
+    ptr[0] = '\0';
+
+    ptr = ptr - 12;
+    m->row_step = atof(ptr);
+    printf("    last field = %s = %.2f\n", ptr, m->col_step);
+    ptr[0] = '\0';
+
+    /* accuracy code = atod(token) */
+    inum = atoi(token);
+    printf("    Accuracy code = %d\n", inum);
+
+    printf("    column step = %.2f  row step = %.2f\n", 
+           m->col_step, m->row_step);
+    /* dimension of arrays to follow (1)*/
+    next_token(fd, token);
+
+    /* number of profiles */
+    dem_num_profiles = m->cols = m->rows = next_int(fd);
+    printf("    Expecting %d profiles\n", dem_num_profiles);
+
 }
 
 
@@ -291,7 +426,10 @@ void rawReadStrip( fgRAWDEM *raw, int lat_degrees ) {
 
 
 /* $Log$
-/* Revision 1.1  1998/03/02 23:31:01  curt
-/* Initial revision.
+/* Revision 1.2  1998/03/03 02:04:01  curt
+/* Starting DEM Ascii format output routine.
 /*
+ * Revision 1.1  1998/03/02 23:31:01  curt
+ * Initial revision.
+ *
  */

From 904d046c7acc03791db4ec9910b885623d805d7b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 03:36:57 +0000
Subject: [PATCH 039/283] Cumulative tweaks.

---
 AssemTris/depend      | 27 +++++++++++--
 FixObj/obj.c          |  9 +++--
 SplitTris/depend      | 27 +++++++++++--
 SplitTris/splittris.c | 32 +++++++++------
 Tools/process-dem.pl  | 92 ++++++++++++++++++++++++++++---------------
 Tri2obj/depend        | 27 +++++++++++--
 Triangle/depend       | 30 ++++++++++++--
 7 files changed, 182 insertions(+), 62 deletions(-)

diff --git a/AssemTris/depend b/AssemTris/depend
index 50c56a1f3..d41a5f3cf 100644
--- a/AssemTris/depend
+++ b/AssemTris/depend
@@ -1,4 +1,23 @@
-assemtris.o: assemtris.c assemtris.h ../../Src/Include/constants.h \
- ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
- ../../Src/Math/mat3.h ../../Src/Math/polar.h \
- ../../Src/Math/../Include/types.h ../../Src/Scenery/tileutils.h
+assemtris.o: assemtris.c /usr/include/math.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/huge_val.h \
+ /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
+ /usr/include/values.h /usr/include/ieee754.h \
+ /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
+ /usr/include/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/string.h \
+ /usr/include/sys/stat.h /usr/include/sys/types.h \
+ /usr/include/linux/types.h /usr/include/linux/posix_types.h \
+ /usr/include/asm/posix_types.h /usr/include/asm/types.h \
+ /usr/include/sys/bitypes.h /usr/include/linux/stat.h \
+ /usr/include/unistd.h /usr/include/posix_opt.h \
+ /usr/include/gnu/types.h /usr/include/confname.h assemtris.h \
+ /home/home17/curt/projects/FlightGear/Src/Include/fg_constants.h \
+ /home/home17/curt/projects/FlightGear/Src/Include/fg_types.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/fg_geodesy.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/mat3.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/polar.h \
+ /home/home17/curt/projects/FlightGear/Src/Scenery/bucketutils.h
diff --git a/FixObj/obj.c b/FixObj/obj.c
index fde62bbbc..8f704957f 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -214,7 +214,7 @@ void obj_fix(char *infile, char *outfile) {
 	    }
 
 	    dot_prod = check_cur_face(n1, n2, n3);
-	    if ( dot_prod < -0.5 ) {
+	    if ( dot_prod < 0.0 ) {
 		/* this stripe is backwards (CW) */
 		is_ccw = 0;
 		printf(" -> Starting a backwards stripe\n");
@@ -288,9 +288,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.4  1998/01/31 00:41:25  curt
-/* Made a few changes converting floats to doubles.
+/* Revision 1.5  1998/03/03 03:37:03  curt
+/* Cumulative tweaks.
 /*
+ * Revision 1.4  1998/01/31 00:41:25  curt
+ * Made a few changes converting floats to doubles.
+ *
  * Revision 1.3  1998/01/19 19:51:07  curt
  * A couple final pre-release tweaks.
  *
diff --git a/SplitTris/depend b/SplitTris/depend
index 5b95dd978..f45316766 100644
--- a/SplitTris/depend
+++ b/SplitTris/depend
@@ -1,4 +1,23 @@
-splittris.o: splittris.c splittris.h ../../Src/Include/constants.h \
- ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
- ../../Src/Math/mat3.h ../../Src/Math/polar.h \
- ../../Src/Math/../Include/types.h ../../Src/Scenery/tileutils.h
+splittris.o: splittris.c /usr/include/math.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/huge_val.h \
+ /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
+ /usr/include/values.h /usr/include/ieee754.h \
+ /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
+ /usr/include/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/string.h \
+ /usr/include/sys/stat.h /usr/include/sys/types.h \
+ /usr/include/linux/types.h /usr/include/linux/posix_types.h \
+ /usr/include/asm/posix_types.h /usr/include/asm/types.h \
+ /usr/include/sys/bitypes.h /usr/include/linux/stat.h \
+ /usr/include/unistd.h /usr/include/posix_opt.h \
+ /usr/include/gnu/types.h /usr/include/confname.h splittris.h \
+ /home/home17/curt/projects/FlightGear/Src/Include/fg_constants.h \
+ /home/home17/curt/projects/FlightGear/Src/Include/fg_types.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/fg_geodesy.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/mat3.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/polar.h \
+ /home/home17/curt/projects/FlightGear/Src/Scenery/bucketutils.h
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index 3646e22cc..9c8f7bfb1 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -456,8 +456,11 @@ void dump_obj(char *basename, char *basepath) {
 	} else {
 	    fp = body;
 	}
-	fprintf(fp, "gdn %.2f %.2f %.2f\n", 
-		nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+
+	if ( fp != NULL ) {
+	    fprintf(fp, "gdn %.2f %.2f %.2f\n", 
+		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	}
     }
 
     printf("  calculating and writing normals\n");
@@ -541,17 +544,17 @@ void dump_obj(char *basename, char *basepath) {
 	}
     }
 
-    fclose(sw);
-    fclose(se);
-    fclose(ne);
-    fclose(nw);
+    if ( sw ) { fclose(sw); }
+    if ( se ) { fclose(se); }
+    if ( ne ) { fclose(ne); }
+    if ( nw ) { fclose(nw); }
 
-    fclose(north);
-    fclose(south);
-    fclose(east);
-    fclose(west);
+    if ( north ) { fclose(north); }
+    if ( south ) { fclose(south); }
+    if ( east ) { fclose(east); }
+    if ( west ) { fclose(west); }
 
-    fclose(body);
+    if ( body ) { fclose(body); }
 }
 
 
@@ -609,9 +612,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.4  1998/01/31 00:41:26  curt
-/* Made a few changes converting floats to doubles.
+/* Revision 1.5  1998/03/03 03:37:04  curt
+/* Cumulative tweaks.
 /*
+ * Revision 1.4  1998/01/31 00:41:26  curt
+ * Made a few changes converting floats to doubles.
+ *
  * Revision 1.3  1998/01/27 18:37:04  curt
  * Lots of updates to get back in sync with changes made over in .../Src/
  *
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 6a692b22f..22d8ee9a7 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -40,16 +40,6 @@ $do_strips =     1;
 $do_fixobj =     1;
 
 
-# return the file name root (ending at last ".")
-sub file_root {
-    my($file) = @_;
-    my($pos);
-
-    $pos = rindex($file, ".");
-    return substr($file, 0, $pos);
-}
-
-
 # set the FG_ROOT environment variable if it hasn't already been set.
 if ( $ENV{FG_ROOT} eq "" ) {
     # look for a file called fgtop as a place marker
@@ -61,26 +51,64 @@ if ( $ENV{FG_ROOT} eq "" ) {
 }
 
 
-# 1.  Start with file.dem
+if ( $#ARGV < 1 ) {
+    die "Usage: $0 <error^2> dem-file1 [ dem-file2 dem-file3 ... ]\n";
+}
+
+# Start with file.dem
 
-$dem_file = shift(@ARGV);
 $error = shift(@ARGV);
 $error += 0.0;
 
-print "Source file = $dem_file  Error tolerance = $error\n";
+while ( $dem_file = shift(@ARGV) ) {
+    print "Source file = $dem_file  Error tolerance = $error\n";
 
-if ( $error < 0.5 ) {
-    die "I doubt you'll be happy with an error tolerance as low as $error.\n";
+    if ( $error < 0.5 ) {
+	die "I doubt you'll be happy with an error tolerance as " . 
+	    "low as $error.\n";
+    }
+
+
+    if ( $do_demfit ) {
+	demfit() ;
+    } else {
+	$subdir = "../Scenery/w100n040/w093n045";
+	print "WARNING:  Hardcoding subdir = $subdir\n";
+    }
+    
+    triangle_1() if ( $do_triangle_1 );
+    fixnode() if ( $do_fixnode );
+    splittris() if ( $do_splittris );
+    assemtris() if ( $do_assemtris );
+    triangle_2() if ( $do_triangle_2);
+    tri2obj() if ( $do_tri2obj );
+    strips() if ( $do_strips );
+    fixobj() if ( $do_fixobj );
 }
 
-# 2.  dem2node $FG_ROOT dem_file tolerance^2 (meters)
+
+# exit normally
+exit(0);
+
+
+# return the file name root (ending at last ".")
+sub file_root {
+    my($file) = @_;
+    my($pos);
+
+    $pos = rindex($file, ".");
+    return substr($file, 0, $pos);
+}
+
+
+# 1.  dem2node $FG_ROOT dem_file tolerance^2 (meters)
 # 
 #     - dem2node .. dem_file 160000
 #
 #     splits dem file into 64 file.node's which contain the
 #     irregularly fitted vertices
 
-if ( $do_demfit ) {
+sub demfit {
     if ( $dem_file =~ m/.gz$/ ) {
 	$command = "gzip -dc $dem_file | ./Dem2node/demfit $ENV{FG_ROOT} - $error";
     } else {
@@ -99,17 +127,15 @@ if ( $do_demfit ) {
 	}
     }
     close(OUT);
-} else {
-    $subdir = "../Scenery/w100n040/w093n045";
-    print "WARNING:  Hardcoding subdir = $subdir\n";
-}
+} 
 
-# 3.  triangle -q file (Takes file.node and produces file.1.node and
+
+# 2.  triangle -q file (Takes file.node and produces file.1.node and
 #                      file.1.ele)
 
 print "Subdirectory for this dem file is $subdir\n";
 
-if ( $do_triangle_1 ) {
+sub triangle_1 {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	print $file;
@@ -129,13 +155,14 @@ if ( $do_triangle_1 ) {
     }
 }
 
-# 4.  fixnode file.dem subdir
+
+# 3.  fixnode file.dem subdir
 #
 #     Take the original .dem file (for interpolating Z values) and the
 #     subdirecotry containing all the file.1.node's and replace with
 #     fixed file.1.node
 
-if ( $do_fixnode ) {
+sub fixnode {
     if ( $dem_file =~ m/.gz$/ ) {
 	$command = "gzip -dc $dem_file | ./FixNode/fixnode - $subdir";
     } else {
@@ -165,7 +192,7 @@ if ( $do_fixnode ) {
 #     gets to define the edge verticies and normals.  All the other
 #     adjacent tiles must use these.
 
-if ( $do_splittris ) {
+sub splittris {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	chop($file);
@@ -192,7 +219,7 @@ if ( $do_splittris ) {
 #     using the proper shared corners and edges.  Save as a node file
 #     so we can retriangulate.
 
-if ( $do_assemtris ) {
+sub assemtris {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	chop($file);
@@ -215,7 +242,7 @@ if ( $do_assemtris ) {
 # 4.3 Retriangulate reassembled files (without -q option) so no new
 #     nodes are generated.
 
-if ( $do_triangle_2 ) {
+sub triangle_2 {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	print $file;
@@ -246,7 +273,7 @@ if ( $do_triangle_2 ) {
 #     the gaps between tiles eliminated, but the colors and lighting
 #     transition smoothly across tile boundaries.
 
-if ( $do_tri2obj ) {
+sub tri2obj {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	chop($file);
@@ -278,7 +305,7 @@ if ( $do_tri2obj ) {
 #
 #     strips produces a file called "bands.d" ... copy this to file.2.obj
 
-if ( $do_strips ) {
+sub strips {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	chop($file);
@@ -313,7 +340,7 @@ if ( $do_strips ) {
 #
 #     Sort file.2.obj by strip winding
 
-if ( $do_fixobj ) {
+sub fixobj {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	chop($file);
@@ -337,6 +364,9 @@ if ( $do_fixobj ) {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.11  1998/03/03 03:36:57  curt
+# Cumulative tweaks.
+#
 # Revision 1.10  1998/02/01 03:42:26  curt
 # Modifications to handle compressed dem files.
 #
diff --git a/Tri2obj/depend b/Tri2obj/depend
index 06689736e..1ae0d9c5f 100644
--- a/Tri2obj/depend
+++ b/Tri2obj/depend
@@ -1,4 +1,23 @@
-tri2obj.o: tri2obj.c tri2obj.h ../../Src/Include/constants.h \
- ../../Src/Include/types.h ../../Src/Math/fg_geodesy.h \
- ../../Src/Math/mat3.h ../../Src/Math/polar.h \
- ../../Src/Math/../Include/types.h ../../Src/Scenery/tileutils.h
+tri2obj.o: tri2obj.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/stdlib.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
+ /usr/include/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/string.h \
+ /usr/include/sys/stat.h /usr/include/sys/types.h \
+ /usr/include/linux/types.h /usr/include/linux/posix_types.h \
+ /usr/include/asm/posix_types.h /usr/include/asm/types.h \
+ /usr/include/sys/bitypes.h /usr/include/linux/stat.h \
+ /usr/include/unistd.h /usr/include/posix_opt.h \
+ /usr/include/gnu/types.h /usr/include/confname.h tri2obj.h \
+ /home/home17/curt/projects/FlightGear/Src/Include/fg_constants.h \
+ /usr/include/math.h /usr/include/huge_val.h /usr/include/endian.h \
+ /usr/include/bytesex.h /usr/include/nan.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
+ /usr/include/values.h /usr/include/ieee754.h \
+ /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
+ /home/home17/curt/projects/FlightGear/Src/Include/fg_types.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/fg_geodesy.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/mat3.h \
+ /home/home17/curt/projects/FlightGear/Src/Math/polar.h \
+ /home/home17/curt/projects/FlightGear/Src/Scenery/bucketutils.h
diff --git a/Triangle/depend b/Triangle/depend
index 8265ad69e..3293c1b40 100644
--- a/Triangle/depend
+++ b/Triangle/depend
@@ -1,3 +1,27 @@
-showme.o: showme.c
-triangle.o: triangle.c
-tricall.o: tricall.c triangle.h
+showme.o: showme.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/string.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
+ /usr/include/X11/Xlib.h /usr/include/sys/types.h \
+ /usr/include/linux/types.h /usr/include/linux/posix_types.h \
+ /usr/include/asm/posix_types.h /usr/include/asm/types.h \
+ /usr/include/sys/bitypes.h /usr/include/X11/X.h \
+ /usr/include/X11/Xfuncproto.h /usr/include/X11/Xosdefs.h \
+ /usr/include/X11/Xutil.h /usr/include/X11/Xatom.h
+triangle.o: triangle.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/string.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
+ /usr/include/math.h /usr/include/huge_val.h /usr/include/endian.h \
+ /usr/include/bytesex.h /usr/include/nan.h \
+ /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
+ /usr/include/values.h /usr/include/ieee754.h \
+ /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
+ /usr/include/sys/time.h /usr/include/linux/types.h \
+ /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h \
+ /usr/include/asm/types.h /usr/include/linux/time.h \
+ /usr/include/time.h /usr/include/sys/types.h \
+ /usr/include/sys/bitypes.h
+tricall.o: tricall.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/libio.h \
+ /usr/include/_G_config.h triangle.h

From 64114fd6e7bd19c5084e0919065781604a4d9076 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 03:38:39 +0000
Subject: [PATCH 040/283] Removed ...

---
 AssemTris/depend | 23 -----------------------
 SplitTris/depend | 23 -----------------------
 Tri2obj/depend   | 23 -----------------------
 3 files changed, 69 deletions(-)
 delete mode 100644 AssemTris/depend
 delete mode 100644 SplitTris/depend
 delete mode 100644 Tri2obj/depend

diff --git a/AssemTris/depend b/AssemTris/depend
deleted file mode 100644
index d41a5f3cf..000000000
--- a/AssemTris/depend
+++ /dev/null
@@ -1,23 +0,0 @@
-assemtris.o: assemtris.c /usr/include/math.h /usr/include/features.h \
- /usr/include/sys/cdefs.h /usr/include/huge_val.h \
- /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
- /usr/include/values.h /usr/include/ieee754.h \
- /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/stdlib.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
- /usr/include/errno.h /usr/include/linux/errno.h \
- /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/string.h \
- /usr/include/sys/stat.h /usr/include/sys/types.h \
- /usr/include/linux/types.h /usr/include/linux/posix_types.h \
- /usr/include/asm/posix_types.h /usr/include/asm/types.h \
- /usr/include/sys/bitypes.h /usr/include/linux/stat.h \
- /usr/include/unistd.h /usr/include/posix_opt.h \
- /usr/include/gnu/types.h /usr/include/confname.h assemtris.h \
- /home/home17/curt/projects/FlightGear/Src/Include/fg_constants.h \
- /home/home17/curt/projects/FlightGear/Src/Include/fg_types.h \
- /home/home17/curt/projects/FlightGear/Src/Math/fg_geodesy.h \
- /home/home17/curt/projects/FlightGear/Src/Math/mat3.h \
- /home/home17/curt/projects/FlightGear/Src/Math/polar.h \
- /home/home17/curt/projects/FlightGear/Src/Scenery/bucketutils.h
diff --git a/SplitTris/depend b/SplitTris/depend
deleted file mode 100644
index f45316766..000000000
--- a/SplitTris/depend
+++ /dev/null
@@ -1,23 +0,0 @@
-splittris.o: splittris.c /usr/include/math.h /usr/include/features.h \
- /usr/include/sys/cdefs.h /usr/include/huge_val.h \
- /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
- /usr/include/values.h /usr/include/ieee754.h \
- /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/stdlib.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
- /usr/include/errno.h /usr/include/linux/errno.h \
- /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/string.h \
- /usr/include/sys/stat.h /usr/include/sys/types.h \
- /usr/include/linux/types.h /usr/include/linux/posix_types.h \
- /usr/include/asm/posix_types.h /usr/include/asm/types.h \
- /usr/include/sys/bitypes.h /usr/include/linux/stat.h \
- /usr/include/unistd.h /usr/include/posix_opt.h \
- /usr/include/gnu/types.h /usr/include/confname.h splittris.h \
- /home/home17/curt/projects/FlightGear/Src/Include/fg_constants.h \
- /home/home17/curt/projects/FlightGear/Src/Include/fg_types.h \
- /home/home17/curt/projects/FlightGear/Src/Math/fg_geodesy.h \
- /home/home17/curt/projects/FlightGear/Src/Math/mat3.h \
- /home/home17/curt/projects/FlightGear/Src/Math/polar.h \
- /home/home17/curt/projects/FlightGear/Src/Scenery/bucketutils.h
diff --git a/Tri2obj/depend b/Tri2obj/depend
deleted file mode 100644
index 1ae0d9c5f..000000000
--- a/Tri2obj/depend
+++ /dev/null
@@ -1,23 +0,0 @@
-tri2obj.o: tri2obj.c /usr/include/stdio.h /usr/include/features.h \
- /usr/include/sys/cdefs.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/stdlib.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
- /usr/include/errno.h /usr/include/linux/errno.h \
- /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/string.h \
- /usr/include/sys/stat.h /usr/include/sys/types.h \
- /usr/include/linux/types.h /usr/include/linux/posix_types.h \
- /usr/include/asm/posix_types.h /usr/include/asm/types.h \
- /usr/include/sys/bitypes.h /usr/include/linux/stat.h \
- /usr/include/unistd.h /usr/include/posix_opt.h \
- /usr/include/gnu/types.h /usr/include/confname.h tri2obj.h \
- /home/home17/curt/projects/FlightGear/Src/Include/fg_constants.h \
- /usr/include/math.h /usr/include/huge_val.h /usr/include/endian.h \
- /usr/include/bytesex.h /usr/include/nan.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
- /usr/include/values.h /usr/include/ieee754.h \
- /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
- /home/home17/curt/projects/FlightGear/Src/Include/fg_types.h \
- /home/home17/curt/projects/FlightGear/Src/Math/fg_geodesy.h \
- /home/home17/curt/projects/FlightGear/Src/Math/mat3.h \
- /home/home17/curt/projects/FlightGear/Src/Math/polar.h \
- /home/home17/curt/projects/FlightGear/Src/Scenery/bucketutils.h

From 4b577c8bab4306e16b8764ab24648a5564052140 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 13:10:28 +0000
Subject: [PATCH 041/283] Close to a working version.

---
 DemRaw2ascii/main.c   |   9 +-
 DemRaw2ascii/rawdem.c | 229 +++++++++++++++++++++++-------------------
 DemRaw2ascii/rawdem.h |  13 ++-
 3 files changed, 138 insertions(+), 113 deletions(-)

diff --git a/DemRaw2ascii/main.c b/DemRaw2ascii/main.c
index 08ccd42ec..94aedb635 100644
--- a/DemRaw2ascii/main.c
+++ b/DemRaw2ascii/main.c
@@ -63,7 +63,7 @@ int main(int argc, char **argv) {
     rawOpenDemFile(&raw, dem_file);
 
     for ( i = 41; i <= 90; i++ ) {
-	rawReadStrip(&raw, i);
+	rawProcessStrip(&raw, i, output_dir);
     }
 
     /* close the raw data file */
@@ -74,7 +74,10 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.1  1998/03/02 23:31:01  curt
-/* Initial revision.
+/* Revision 1.2  1998/03/03 13:10:28  curt
+/* Close to a working version.
 /*
+ * Revision 1.1  1998/03/02 23:31:01  curt
+ * Initial revision.
+ *
  */
diff --git a/DemRaw2ascii/rawdem.c b/DemRaw2ascii/rawdem.c
index 4004a9eed..88727d73d 100644
--- a/DemRaw2ascii/rawdem.c
+++ b/DemRaw2ascii/rawdem.c
@@ -204,152 +204,163 @@ void rawConvertCenter2Edge( fgRAWDEM *raw ) {
 
 
 /* Dump out the ascii format DEM file */
-void rawDumpAsciiDEM( fgRAWDEM *raw ) {
+void rawDumpAsciiDEM( fgRAWDEM *raw, char *path, int ilon, int ilat ) {
     char outfile[256];
+    char tmp[256];
+    int lon, lat;
+    char lon_sign, lat_sign;
+    int i, j;
+    FILE *fd;
+
     /* Generate output file name */
-    
-    
+
+    if ( ilon >= 0 ) {
+	lon = ilon;
+	lon_sign = 'e';
+    } else {
+	lon = -ilon;
+	lon_sign = 'w';
+    }
+
+    if ( ilat >= 0 ) {
+	lat = ilat;
+	lat_sign = 'n';
+    } else {
+	lat = -ilat;
+	lat_sign = 's';
+    }
+
+    sprintf(outfile, "%s/%c%03d%c%03d.dem", path, lon_sign, lon, lat_sign, lat);
+
+    printf("outfile = %s\n", outfile);
+
+    if ( (fd = fopen(outfile, "w")) == NULL ) {
+	printf("Error opening output file = %s\n", outfile);
+	exit(-1);
+    }
+
     /* Dump the "A" record */
 
-    /* get the name field (144 characters) */
-    for ( i = 0; i < 144; i++ ) {
-        name[i] = fgetc(fd);
-    }
-    name[i+1] = '\0';
-
-    /* clean off the whitespace at the end */
-    for ( i = strlen(name)-2; i > 0; i-- ) {
-        if ( !isspace(name[i]) ) {
-            i=0;
-        } else {
-            name[i] = '\0'; 
-        }
-    }
-    printf("    Quad name field: %s\n", name);
-
-    /* get quadrangle id (now part of previous section  */
-    /* next_token(fd, dem_quadrangle); */
-    /* printf("    Quadrangle = %s\n", dem_quadrangle); */
+    /* print descriptive header (144 characters) */
+    sprintf(tmp, "%s - Generated from a 30 arcsec binary DEM", outfile);
+    fprintf(fd, "%-144s", tmp);
 
     /* DEM level code, 3 reflects processing by DMA */
-    inum = next_int(fd);
-    printf("    DEM level code = %d\n", inum);
+    fprintf(fd, "%6d", 1);
 
     /* Pattern code, 1 indicates a regular elevation pattern */
-    inum = next_int(fd);
-    printf("    Pattern code = %d\n", inum);
+    fprintf(fd, "%6d", 1);
 
     /* Planimetric reference system code, 0 indicates geographic 
      * coordinate system. */
-    inum = next_int(fd);
-    printf("    Planimetric reference code = %d\n", inum);
+    fprintf(fd, "%6d", 0);
 
     /* Zone code */
-    inum = next_int(fd);
-    printf("    Zone code = %d\n", inum);
+    fprintf(fd, "%6d", 0);
 
     /* Map projection parameters (ignored) */
     for ( i = 0; i < 15; i++ ) {
-        dnum = next_double(fd);
-        /* printf("%d: %f\n",i,dnum); */
+        fprintf(fd, "%6.1f%18s", 0.0, "");
     }
 
-    /* Units code, 3 represents arc-seconds as the unit of measure for
+   /* Units code, 3 represents arc-seconds as the unit of measure for
      * ground planimetric coordinates throughout the file. */
-    inum = next_int(fd);
-    if ( inum != 3 ) {
-        printf("    Unknown (X,Y) units code = %d!\n", inum);
-        exit(-1);
-    }
+    fprintf(fd, "%6d", 3);
 
     /* Units code; 2 represents meters as the unit of measure for
      * elevation coordinates throughout the file. */
-    inum = next_int(fd);
-    if ( inum != 2 ) {
-        printf("    Unknown (Z) units code = %d!\n", inum);
-        exit(-1);
-    }
+    fprintf(fd, "%6d", 2);
 
     /* Number (n) of sides in the polygon which defines the coverage of
      * the DEM file (usually equal to 4). */
-    inum = next_int(fd);
-    if ( inum != 4 ) {
-        printf("    Unknown polygon dimension = %d!\n", inum);
-        exit(-1);
-    }
+    fprintf(fd, "%6d", 4);
 
     /* Ground coordinates of bounding box in arc-seconds */
-    dem_x1 = m->originx = next_exp(fd);
-    dem_y1 = m->originy = next_exp(fd);
-    printf("    Origin = (%.2f,%.2f)\n", m->originx, m->originy);
+    fprintf(fd, "%20.15fD+06", ilon * 3600.0 / 1000000.0);
+    fprintf(fd, "%20.15fD+06", ilat * 3600.0 / 1000000.0);
 
-    dem_x2 = next_exp(fd);
-    dem_y2 = next_exp(fd);
+    fprintf(fd, "%20.15fD+06", ilon * 3600.0 / 1000000.0);
+    fprintf(fd, "%20.15fD+06", (ilat+1) * 3600.0 / 1000000.0);
 
-    dem_x3 = next_exp(fd);
-    dem_y3 = next_exp(fd);
+    fprintf(fd, "%20.15fD+06", (ilon+1) * 3600.0 / 1000000.0);
+    fprintf(fd, "%20.15fD+06", (ilat+1) * 3600.0 / 1000000.0);
 
-    dem_x4 = next_exp(fd);
-    dem_y4 = next_exp(fd);
+    fprintf(fd, "%20.15fD+06", (ilon+1) * 3600.0 / 1000000.0);
+    fprintf(fd, "%20.15fD+06", (ilat) * 3600.0 / 1000000.0);
 
     /* Minimum/maximum elevations in meters */
-    dem_z1 = next_exp(fd);
-    dem_z2 = next_exp(fd);
-    printf("    Elevation range %.4f %.4f\n", dem_z1, dem_z2);
+    fprintf(fd, "   %20.15E", (double)raw->tmp_min);
+    fprintf(fd, "   %20.15E", (double)raw->tmp_max);
 
     /* Counterclockwise angle from the primary axis of ground
      * planimetric referenced to the primary axis of the DEM local
      * reference system. */
-    next_token(fd, token);
+    fprintf(fd, "%6.1f", 0.0);
 
     /* Accuracy code; 0 indicates that a record of accuracy does not
      * exist and that no record type C will follow. */
-    /* DEM spacial resolution.  Usually (3,3,1) (3,6,1) or (3,9,1)
+    fprintf(fd, "%24d", 0);
+
+    /* DEM spacial resolution.  Usually (3,3) (3,6) or (3,9)
      * depending on latitude */
-    /* I will eventually have to do something with this for data at
-     * higher latitudes */
-    next_token(fd, token);
-    printf("    accuracy & spacial resolution string = %s\n", token);
-    i = strlen(token);
-    printf("    length = %d\n", i);
+    fprintf(fd, "%12.6E", 30.0);
+    fprintf(fd, "%12.6E", 30.0);
 
-    ptr = token + i - 12;
-    printf("    last field = %s = %.2f\n", ptr, atof(ptr));
-    ptr[0] = '\0';
-
-    ptr = ptr - 12;
-    m->col_step = atof(ptr);
-    printf("    last field = %s = %.2f\n", ptr, m->row_step);
-    ptr[0] = '\0';
-
-    ptr = ptr - 12;
-    m->row_step = atof(ptr);
-    printf("    last field = %s = %.2f\n", ptr, m->col_step);
-    ptr[0] = '\0';
-
-    /* accuracy code = atod(token) */
-    inum = atoi(token);
-    printf("    Accuracy code = %d\n", inum);
-
-    printf("    column step = %.2f  row step = %.2f\n", 
-           m->col_step, m->row_step);
+    /* accuracy code */
+    fprintf(fd, "%12.6E", 1.0);
+    
     /* dimension of arrays to follow (1)*/
-    next_token(fd, token);
+    fprintf(fd, "%6d", 1);
 
     /* number of profiles */
-    dem_num_profiles = m->cols = m->rows = next_int(fd);
-    printf("    Expecting %d profiles\n", dem_num_profiles);
+    fprintf(fd, "%6d", 3600 / raw->ydim + 1);
 
+    /* pad the end */
+    fprintf(fd, "%160s", "");
+
+
+    /* Dump "B" records */
+
+    for ( j = 0; j <= 120; j++ ) {
+	/* row / column id of this profile */
+	fprintf(fd, "%6d%6d", 1, j + 1);
+
+	/* Number of columns and rows (elevations) in this profile */
+	fprintf(fd, "%6d%6d", 3600 / raw->xdim + 1, 1);
+
+	/* Ground planimetric coordinates (arc-seconds) of the first
+	 * elevation in the profile */
+	fprintf(fd, "%20.15fD+06", ilon * 3600.0 / 1000000.0);
+	fprintf(fd, "%20.15fD+06", (ilat * 3600.0 + j * raw->ydim) / 1000000.0);
+
+	/* Elevation of local datum for the profile.  Always zero for
+	 * 1-degree DEM, the reference is mean sea level. */
+	fprintf(fd, "%6.1f", 0.0);
+	fprintf(fd, "%18s", "");
+
+	/* Minimum and maximum elevations for the profile. */
+	fprintf(fd, "   %20.15E", 0.0);
+	fprintf(fd, "   %20.15E", 0.0);
+
+	/* One (usually) dimensional array (prof_num_cols,1) of elevations */
+	for ( i = 0; i <= 120; i++ ) {
+	    fprintf(fd, "%6.0f", raw->edge[j][i]);
+	}
+    }
+
+    fprintf(fd, "\n");
+
+    fclose(fd);
 }
 
 
 /* Read a horizontal strip of (1 vertical degree) from the raw DEM
  * file specified by the upper latitude of the stripe specified in
- * degrees */
-void rawReadStrip( fgRAWDEM *raw, int lat_degrees ) {
+ * degrees.  The output the individual ASCII format DEM tiles.  */
+void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path ) {
     int lat, yrange;
     int i, j, index, row, col;
-    int min = 0, max = 0;
+    int min, max;
     int span, num_degrees, tile_width;
     int xstart, xend;
 
@@ -384,17 +395,8 @@ void rawReadStrip( fgRAWDEM *raw, int lat_degrees ) {
 		/* map ocean to 0 for now */
 		raw->strip[index][j] = 0;
 	    } 
-
-	    if ( raw->strip[index][j] < min) {
-		min = raw->strip[index][j];
-	    }
-
-	    if ( raw->strip[index][j] > max) {
-		max = raw->strip[index][j];
-	    }
 	}
     }
-    printf("min = %d  max = %d\n", min, max);
 
     /* extract individual tiles from the strip */
     span = raw->ncols * raw->xdim;
@@ -407,28 +409,43 @@ void rawReadStrip( fgRAWDEM *raw, int lat_degrees ) {
 	xstart = i * tile_width;
 	xend = xstart + 120;
 
+	min = 10000; max = -10000;
 	for ( row = 0; row < yrange; row++ ) {
 	    for ( col = xstart; col < xend; col++ ) {
 		/* Copy from strip to pixel centered tile.  Yep,
                  * row/col are reversed here.  raw->strip is backwards
                  * for convenience.  I am converting to [x,y] now. */
 		raw->center[col-xstart][row] = raw->strip[row][col];
+	
+		if ( raw->strip[row][col] < min) {
+		    min = raw->strip[row][col];
+		}
+		
+		if ( raw->strip[row][col] > max) {
+		    max = raw->strip[row][col];
+		}
 	    }
 	}
 
+	raw->tmp_min = min;
+	raw->tmp_max = max;
+
 	/* Convert from pixel centered to pixel edge values */
 	rawConvertCenter2Edge(raw);
 
 	/* Dump out the ascii format DEM file */
-	rawDumpAsciiDEM(raw);
+	rawDumpAsciiDEM(raw, path, (raw->rootx / 3600) + i, lat_degrees - 1);
     }
 }
 
 
 /* $Log$
-/* Revision 1.2  1998/03/03 02:04:01  curt
-/* Starting DEM Ascii format output routine.
+/* Revision 1.3  1998/03/03 13:10:29  curt
+/* Close to a working version.
 /*
+ * Revision 1.2  1998/03/03 02:04:01  curt
+ * Starting DEM Ascii format output routine.
+ *
  * Revision 1.1  1998/03/02 23:31:01  curt
  * Initial revision.
  *
diff --git a/DemRaw2ascii/rawdem.h b/DemRaw2ascii/rawdem.h
index 1bdb8e16c..8877b2eaa 100644
--- a/DemRaw2ascii/rawdem.h
+++ b/DemRaw2ascii/rawdem.h
@@ -41,6 +41,8 @@ typedef struct {
     int rooty;       /* Y coord of upper left *edge* of DEM region in degrees */
     int xdim;        /* X dimension of a pixel */
     int ydim;        /* Y dimension of a pixel */
+    int tmp_min;     /* current 1x1 degree tile minimum */
+    int tmp_max;     /* current 1x1 degree tile maximum */
 
     /* file ptr */
     int fd;          /* Raw DEM file descriptor */
@@ -66,15 +68,18 @@ void rawCloseDemFile( fgRAWDEM *raw );
 
 /* Read a horizontal strip of (1 vertical degree) from the raw DEM
  * file specified by the upper latitude of the stripe specified in
- * degrees */
-void rawReadStrip( fgRAWDEM *raw, int lat );
+ * degrees.  The output the individual ASCII format DEM tiles.  */
+void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path );
 
 
 #endif /* _RAWDEM_H */
 
 
 /* $Log$
-/* Revision 1.1  1998/03/02 23:31:02  curt
-/* Initial revision.
+/* Revision 1.2  1998/03/03 13:10:30  curt
+/* Close to a working version.
 /*
+ * Revision 1.1  1998/03/02 23:31:02  curt
+ * Initial revision.
+ *
  */

From 9125f724499c137f1eff5d7d8834ed218d82966f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 15:36:11 +0000
Subject: [PATCH 042/283] Tweaks for compiling with g++

---
 FixObj/obj.c          | 15 +++++++++------
 FixObj/obj.h          | 11 +++++------
 SplitTris/splittris.c | 15 +++++++++------
 SplitTris/splittris.h | 10 +++++-----
 Tools/Makefile        |  7 +++++--
 5 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index 8f704957f..3971aac83 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -33,13 +33,13 @@
 
 
 /* what do ya' know, here's some global variables */
-double nodes[MAXNODES][3];
-double normals[MAXNODES][3];
+static double nodes[MAXNODES][3];
+static double normals[MAXNODES][3];
 
-int ccw_list[MAXNODES];
+static int ccw_list[MAXNODES];
 int ccw_list_ptr;
 
-int cw_list[MAXNODES];
+static int cw_list[MAXNODES];
 int cw_list_ptr;
 
 FILE *in, *out;
@@ -288,9 +288,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.5  1998/03/03 03:37:03  curt
-/* Cumulative tweaks.
+/* Revision 1.6  1998/03/03 15:36:12  curt
+/* Tweaks for compiling with g++
 /*
+ * Revision 1.5  1998/03/03 03:37:03  curt
+ * Cumulative tweaks.
+ *
  * Revision 1.4  1998/01/31 00:41:25  curt
  * Made a few changes converting floats to doubles.
  *
diff --git a/FixObj/obj.h b/FixObj/obj.h
index 954a088a7..4fd07f42f 100644
--- a/FixObj/obj.h
+++ b/FixObj/obj.h
@@ -30,10 +30,6 @@
 
 #define MAXNODES 100000
 
-extern double nodes[MAXNODES][3];
-extern double normals[MAXNODES][3];
-extern int stack[MAXNODES];
-
 
 /* Load a .obj file */
 void obj_fix(char *infile, char *outfile);
@@ -43,9 +39,12 @@ void obj_fix(char *infile, char *outfile);
 
 
 /* $Log$
-/* Revision 1.3  1998/01/31 00:41:25  curt
-/* Made a few changes converting floats to doubles.
+/* Revision 1.4  1998/03/03 15:36:13  curt
+/* Tweaks for compiling with g++
 /*
+ * Revision 1.3  1998/01/31 00:41:25  curt
+ * Made a few changes converting floats to doubles.
+ *
  * Revision 1.2  1998/01/09 23:03:13  curt
  * Restructured to split 1deg x 1deg dem's into 64 subsections.
  *
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index 9c8f7bfb1..36b8db356 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -45,11 +45,11 @@
 int nodecount, tricount;
 double xmin, xmax, ymin, ymax;
 
-double nodes_orig[MAX_NODES][3];
-int tris[MAX_TRIS][3];
-int new_tris[MAX_TRIS][3];
+static double nodes_orig[MAX_NODES][3];
+static int tris[MAX_TRIS][3];
+/* static int new_tris[MAX_TRIS][3]; */
 
-struct fgCartesianPoint nodes_cart[MAX_NODES];
+static struct fgCartesianPoint nodes_cart[MAX_NODES];
 
 struct fgBUCKET ne_index, nw_index, sw_index, se_index;
 struct fgBUCKET north_index, south_index, east_index, west_index;
@@ -612,9 +612,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.5  1998/03/03 03:37:04  curt
-/* Cumulative tweaks.
+/* Revision 1.6  1998/03/03 15:36:13  curt
+/* Tweaks for compiling with g++
 /*
+ * Revision 1.5  1998/03/03 03:37:04  curt
+ * Cumulative tweaks.
+ *
  * Revision 1.4  1998/01/31 00:41:26  curt
  * Made a few changes converting floats to doubles.
  *
diff --git a/SplitTris/splittris.h b/SplitTris/splittris.h
index abd7621b4..6ed50d672 100644
--- a/SplitTris/splittris.h
+++ b/SplitTris/splittris.h
@@ -37,9 +37,6 @@
 
 
 extern int nodecount, tricount;
-extern struct fgCartesianPoint nodes[MAX_NODES];
-extern int tris[MAX_TRIS][3];
-extern int new_tris[MAX_TRIS][3];
 
 
 /* Initialize a new mesh structure */
@@ -50,9 +47,12 @@ void triload(char *basename);
 
 
 /* $Log$
-/* Revision 1.2  1998/01/15 02:49:25  curt
-/* Misc. housekeeping.
+/* Revision 1.3  1998/03/03 15:36:13  curt
+/* Tweaks for compiling with g++
 /*
+ * Revision 1.2  1998/01/15 02:49:25  curt
+ * Misc. housekeeping.
+ *
  * Revision 1.1  1998/01/14 02:11:32  curt
  * Initial revision.
  *
diff --git a/Tools/Makefile b/Tools/Makefile
index 15a75ef91..25970e183 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,8 +27,8 @@
 include $(FG_ROOT_SRC)/commondefs
 
 
-SUBDIRS = AssemTris Dem2node DemRaw2Ascii FixNode FixObj SplitTris Stripe_u \
-	Tri2obj Triangle
+SUBDIRS = AssemTris Dem2node DemRaw2Ascii FixNode FixObj SplitTris \
+	Stripe_u Tri2obj Triangle
 ORDEREDDIRS = $(SUBDIRS)
 
 
@@ -90,6 +90,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.10  1998/03/03 15:36:11  curt
+# Tweaks for compiling with g++
+#
 # Revision 1.9  1998/03/03 01:21:17  curt
 # Added DemRaw2Ascii
 #

From d6ba1a71880b46a2edfa99038b24b54db8bebede Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 16:00:52 +0000
Subject: [PATCH 043/283] More c++ compile tweaks.

---
 AssemTris/assemtris.c |  9 ++++++---
 FixNode/fixnode.c     |  9 ++++++---
 FixNode/fixnode.h     | 11 +++++++----
 FixNode/main.c        | 15 ++++++++++-----
 FixNode/triload.c     | 10 ++++++----
 FixNode/triload.h     | 10 ++++++----
 Tri2obj/tri2obj.c     | 14 ++++++++------
 Tri2obj/tri2obj.h     | 13 +++++--------
 8 files changed, 54 insertions(+), 37 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index e1e1413a1..ab53c1a1c 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -41,7 +41,7 @@
 
 int nodecount = 0;
 
-double nodes[MAX_NODES][3];
+static double nodes[MAX_NODES][3];
 
 
 struct fgBUCKET my_index;
@@ -454,9 +454,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.4  1998/01/31 00:41:23  curt
-/* Made a few changes converting floats to doubles.
+/* Revision 1.5  1998/03/03 16:00:52  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.4  1998/01/31 00:41:23  curt
+ * Made a few changes converting floats to doubles.
+ *
  * Revision 1.3  1998/01/27 18:37:00  curt
  * Lots of updates to get back in sync with changes made over in .../Src/
  *
diff --git a/FixNode/fixnode.c b/FixNode/fixnode.c
index 8c3aee33a..afd707082 100644
--- a/FixNode/fixnode.c
+++ b/FixNode/fixnode.c
@@ -34,7 +34,7 @@
 
 
 /* load the node information */
-void fixnodes(char *filename, struct MESH *m) {
+void fixnodes(char *filename, struct MESH *m, double nodes[MAX_NODES][3]) {
     char toname[256];
     FILE *fd;
     int i;
@@ -77,9 +77,12 @@ void fixnodes(char *filename, struct MESH *m) {
 
 
 /* $Log$
-/* Revision 1.3  1998/01/09 23:03:08  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
+/* Revision 1.4  1998/03/03 16:00:57  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.3  1998/01/09 23:03:08  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
  * Revision 1.2  1997/12/02 13:12:07  curt
  * Updated to fix every node.
  *
diff --git a/FixNode/fixnode.h b/FixNode/fixnode.h
index 303eb6286..ee6501ac3 100644
--- a/FixNode/fixnode.h
+++ b/FixNode/fixnode.h
@@ -31,21 +31,24 @@
 #include <stdio.h>
 #include <string.h>
 
-/* #include "fixnode.h" */
+#include "triload.h"
 #include "../Dem2node/mesh.h"
 
 
 /* load the node information */
-void fixnodes(char *basename, struct MESH *m);
+void fixnodes(char *basename, struct MESH *m, double nodes[MAX_NODES][3]);
 
 
 #endif /* FIXNODE_H */
 
 
 /* $Log$
-/* Revision 1.2  1997/12/02 13:12:07  curt
-/* Updated to fix every node.
+/* Revision 1.3  1998/03/03 16:00:58  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.2  1997/12/02 13:12:07  curt
+ * Updated to fix every node.
+ *
  * Revision 1.1  1997/11/27 00:17:33  curt
  * Initial revision.
  *
diff --git a/FixNode/main.c b/FixNode/main.c
index 002c495cf..c2caca7e1 100644
--- a/FixNode/main.c
+++ b/FixNode/main.c
@@ -35,8 +35,10 @@
 
 
 /* Original DEM which is used to interpolate z values */
-struct MESH dem_mesh;
+static struct MESH dem_mesh;
 
+/* Node list */
+static double nodes[MAX_NODES][3];
 
 /* find all the matching files in the specified directory and fix them */
 void process_files(char *root_path) {
@@ -65,9 +67,9 @@ void process_files(char *root_path) {
 		printf("File = %s\n", file_path);
 
 		/* load the input data files */
-		triload(file_path);
+		triload(file_path, nodes);
 
-		fixnodes(file_path, &dem_mesh);
+		fixnodes(file_path, &dem_mesh, nodes);
 	    }
 	}
     }
@@ -97,9 +99,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.3  1998/01/09 23:03:08  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
+/* Revision 1.4  1998/03/03 16:00:58  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.3  1998/01/09 23:03:08  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
  * Revision 1.2  1997/12/02 13:12:07  curt
  * Updated to fix every node.
  *
diff --git a/FixNode/triload.c b/FixNode/triload.c
index f0510bd27..72d9427f9 100644
--- a/FixNode/triload.c
+++ b/FixNode/triload.c
@@ -31,11 +31,10 @@
 
 
 int nodecount;
-double nodes[MAX_NODES][3];
 
 
 /* load the node information */
-void triload(char *filename) {
+void triload(char *filename, double nodes[MAX_NODES][3]) {
     FILE *node;
     int dim, junk1, junk2;
     int i;
@@ -67,9 +66,12 @@ void triload(char *filename) {
 
 
 /* $Log$
-/* Revision 1.2  1998/01/09 23:03:09  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
+/* Revision 1.3  1998/03/03 16:00:59  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.2  1998/01/09 23:03:09  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
  * Revision 1.1  1997/11/27 00:17:35  curt
  * Initial revision.
  *
diff --git a/FixNode/triload.h b/FixNode/triload.h
index 2d84f8e74..8b5e32451 100644
--- a/FixNode/triload.h
+++ b/FixNode/triload.h
@@ -37,20 +37,22 @@
 
 
 extern int nodecount, tricount;
-double nodes[MAX_NODES][3];
 
 
 /* Initialize a new mesh structure */
-void triload(char *basename);
+void triload(char *basename, double nodes[MAX_NODES][3]);
 
 
 #endif /* TRILOAD_H */
 
 
 /* $Log$
-/* Revision 1.2  1998/01/09 23:03:09  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
+/* Revision 1.3  1998/03/03 16:00:59  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.2  1998/01/09 23:03:09  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
  * Revision 1.1  1997/11/27 00:17:35  curt
  * Initial revision.
  *
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 93fb4f9b6..e44f5559d 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -42,11 +42,10 @@
 
 int nodecount, tricount;
 int normalcount = 0;
-struct fgCartesianPoint nodes[MAX_NODES];
-int tris[MAX_TRIS][3];
-int new_tris[MAX_TRIS][3];
+static struct fgCartesianPoint nodes[MAX_NODES];
+static int tris[MAX_TRIS][3];
 
-double normals[MAX_NODES][3];
+static double normals[MAX_NODES][3];
 
 struct fgBUCKET my_index;
 struct fgBUCKET ne_index, nw_index, sw_index, se_index;
@@ -640,9 +639,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.10  1998/01/31 00:41:27  curt
-/* Made a few changes converting floats to doubles.
+/* Revision 1.11  1998/03/03 16:01:00  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.10  1998/01/31 00:41:27  curt
+ * Made a few changes converting floats to doubles.
+ *
  * Revision 1.9  1998/01/27 18:37:04  curt
  * Lots of updates to get back in sync with changes made over in .../Src/
  *
diff --git a/Tri2obj/tri2obj.h b/Tri2obj/tri2obj.h
index 0b867edaf..e53ae1d0d 100644
--- a/Tri2obj/tri2obj.h
+++ b/Tri2obj/tri2obj.h
@@ -36,12 +36,6 @@
 #define MAX_TRIS  400000
 
 
-extern int nodecount, tricount;
-extern struct fgCartesianPoint nodes[MAX_NODES];
-extern int tris[MAX_TRIS][3];
-extern int new_tris[MAX_TRIS][3];
-
-
 /* Initialize a new mesh structure */
 void triload(char *basename, char *basepath);
 
@@ -50,9 +44,12 @@ void triload(char *basename, char *basepath);
 
 
 /* $Log$
-/* Revision 1.4  1998/01/17 01:25:40  curt
-/* Added support for shared normals.
+/* Revision 1.5  1998/03/03 16:01:00  curt
+/* More c++ compile tweaks.
 /*
+ * Revision 1.4  1998/01/17 01:25:40  curt
+ * Added support for shared normals.
+ *
  * Revision 1.3  1997/11/15 18:05:06  curt
  * minor tweaks ...
  *

From 73a1b3e6d2aa9a9556905bce2b358a86af1ac9b5 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 3 Mar 1998 21:54:43 +0000
Subject: [PATCH 044/283] Changes to process 30 arcsec binary DEM files.

---
 DemRaw2ascii/main.c | 15 ++++++---
 Tools/Makefile      | 11 ++++---
 Tools/README        | 76 +++++++++++++++++++++++++++++++++++++++------
 3 files changed, 84 insertions(+), 18 deletions(-)

diff --git a/DemRaw2ascii/main.c b/DemRaw2ascii/main.c
index 94aedb635..8cc0f2ffa 100644
--- a/DemRaw2ascii/main.c
+++ b/DemRaw2ascii/main.c
@@ -32,7 +32,7 @@
 int main(int argc, char **argv) {
     fgRAWDEM raw;
     char basename[256], output_dir[256], hdr_file[256], dem_file[256];
-    int i;
+    int i, start_lat, end_lat;
 
     if ( argc != 3 ) {
 	printf("Usage: %s <input_file_basename> <output_dir>\n", argv[0]);
@@ -62,7 +62,11 @@ int main(int argc, char **argv) {
     /* open up the raw data file */
     rawOpenDemFile(&raw, dem_file);
 
-    for ( i = 41; i <= 90; i++ ) {
+    end_lat = raw.rooty / 3600;
+    start_lat = end_lat - ((raw.nrows * raw.ydim) / 3600);
+    printf("Latitude ranges from %d to %d\n", start_lat, end_lat);
+
+    for ( i = start_lat + 1; i <= end_lat; i++ ) {
 	rawProcessStrip(&raw, i, output_dir);
     }
 
@@ -74,9 +78,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.2  1998/03/03 13:10:28  curt
-/* Close to a working version.
+/* Revision 1.3  1998/03/03 21:54:50  curt
+/* Changes to process 30 arcsec binary DEM files.
 /*
+ * Revision 1.2  1998/03/03 13:10:28  curt
+ * Close to a working version.
+ *
  * Revision 1.1  1998/03/02 23:31:01  curt
  * Initial revision.
  *
diff --git a/Tools/Makefile b/Tools/Makefile
index 25970e183..e894ece41 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -62,15 +62,15 @@ source-tar: clean
 	(cd ..; \
 	tar cvzf demtools-$(FG_VERSION).tar.gz Tools/Makefile Tools/README \
 	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
-        Tools/Dem2node Tools/FixNode Tools/FixObj Tools/SplitTris \
-	Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
+        Tools/Dem2node Tools/DemRaw2Ascii Tools/FixNode Tools/FixObj \
+	Tools/SplitTris Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
 
 source-zip: clean
 	(cd ..; \
 	zip -r demtools-$(FG_VERSION).zip Tools/Makefile Tools/README \
 	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
-        Tools/Dem2node Tools/FixNode Tools/FixObj Tools/SplitTris \
-	Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
+        Tools/Dem2node Tools/DemRaw2Ascii Tools/FixNode Tools/FixObj \
+	Tools/SplitTris Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
 
 bin-tar: all
 	echo "need to fix this"
@@ -90,6 +90,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.11  1998/03/03 21:54:43  curt
+# Changes to process 30 arcsec binary DEM files.
+#
 # Revision 1.10  1998/03/03 15:36:11  curt
 # Tweaks for compiling with g++
 #
diff --git a/Tools/README b/Tools/README
index fa4bf7290..253e47e04 100644
--- a/Tools/README
+++ b/Tools/README
@@ -1,19 +1,75 @@
-1.  Start with file.dem
+FG Scenery Tools README
+=======================
 
-2.  dem2node file.dem tolerance^2 (meters)
+Contained here-in are the FG scenery creation tools.  These can be
+used to convert 3 arcsec ASCII format DEM files and 30 arcsec binary
+format DEM files into Flight Gear scenery.
 
-    - dem2node file.dem 160000
+Eventually these tools will expand to support insertion of airports,
+roads, rivers, lakes, etc.
 
-3.  triangle -q file
 
-4.  fixnode file
+Building the Tools
+==================
 
-5.  tri2obj file.1
+These tools are compiled and tested under Linux.  I'm all for
+portability, but I just haven't been as motivated to port these tools,
+since scenery creation is less of a general need ... especially at
+this stage.  However, if anyone wants to work on porting to other
+platforms, I will be happy to incorporate patches.
 
-6.  strip file.1.obj
+The process for building these tools is very similar to building the
+main FG source code.
 
-7.  cp bands.d file-new.obj
+1.  Set the FG_ROOT, FG_ROOT_SRC, and FG_ROOT_LIB environment
+    variables.
 
-8.  fixobj file-new
+2.  Run ``make depend''
 
-9.  cp file-new.1.obj .../Scenery/...
+3.  Run ``make clean''
+
+4.  Run ``make''
+
+
+3 Arcsec ASCII DEM files
+========================
+
+Data files for the USA are available in this format from:
+
+    http://edcwww.cr.usgs.gov/doc/edchome/ndcdb/ndcdb.html
+
+To generate FG scenery from one of these dem files, run:
+
+    ./process-dem.pl <error-tolerance-squared> dem-file-1 [ dem-file-2 ...]
+
+You can vary the error tolerance to control the level of detail (and
+size) of the resulting scenery.  Note, you must specify the error
+tolerance squared.  So, if you wish to allow up to a 10 meter error
+margin (very high level of detail) you would specify a value of 100.
+If you desire an error tolerance of 200 meters (medium detail level)
+you would specify a value of 40000.
+
+The process-dem.pl script will automatically dump the resulting .obj
+files in the proper directory tree.
+
+
+30 Arcsec Binary DEM files
+==========================
+
+These data files have world wide coverage and are available from:
+
+    http://edcwww.cr.usgs.gov/landdaac/gtopo30/gtopo30.html
+
+To process these data files, you must first run:
+
+    DemRaw2Ascii/raw2ascii <input_file_basename> <output_dir>
+
+For example:
+
+    DemRaw2Ascii/raw2ascii /tmp/W020N90 asciidems/ 
+
+This will create ASCII DEM files for each 1 degree x 1 degree area in
+the specified output dir.
+
+Then, you can take these ascii dem files and feed them through the
+same procedure you use with the 3 arcsec dem files.
\ No newline at end of file

From c98579b6dec9813e34383afa5ec8a1ef1dbd58c0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 19 Mar 1998 01:48:34 +0000
Subject: [PATCH 045/283] Added gpc-2.01 (generic polygon clipping library)

---
 Tools/Makefile       | 5 ++++-
 Tools/process-dem.pl | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/Tools/Makefile b/Tools/Makefile
index e894ece41..6a4ed347f 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,7 +27,7 @@
 include $(FG_ROOT_SRC)/commondefs
 
 
-SUBDIRS = AssemTris Dem2node DemRaw2Ascii FixNode FixObj SplitTris \
+SUBDIRS = gpc2.01 AssemTris Dem2node DemRaw2Ascii FixNode FixObj SplitTris \
 	Stripe_u Tri2obj Triangle
 ORDEREDDIRS = $(SUBDIRS)
 
@@ -90,6 +90,9 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.12  1998/03/19 01:48:34  curt
+# Added gpc-2.01 (generic polygon clipping library)
+#
 # Revision 1.11  1998/03/03 21:54:43  curt
 # Changes to process 30 arcsec binary DEM files.
 #
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 22d8ee9a7..8737d2744 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -75,7 +75,7 @@ while ( $dem_file = shift(@ARGV) ) {
 	$subdir = "../Scenery/w100n040/w093n045";
 	print "WARNING:  Hardcoding subdir = $subdir\n";
     }
-    
+
     triangle_1() if ( $do_triangle_1 );
     fixnode() if ( $do_fixnode );
     splittris() if ( $do_splittris );
@@ -364,6 +364,9 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.12  1998/03/19 01:48:35  curt
+# Added gpc-2.01 (generic polygon clipping library)
+#
 # Revision 1.11  1998/03/03 03:36:57  curt
 # Cumulative tweaks.
 #

From 31c774d723b41a42f1f29fb2c19537c19779099f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 19 Mar 1998 02:50:19 +0000
Subject: [PATCH 046/283] Updated to support -lDEM class.

---
 FixNode/Makefile  |   5 ++-
 FixNode/fixnode.c |  16 ++++---
 FixNode/fixnode.h |  86 +++++++++++++++++++------------------
 FixNode/main.c    | 107 ++++++++++++++++++++++++----------------------
 FixNode/triload.h |  13 +++---
 5 files changed, 125 insertions(+), 102 deletions(-)

diff --git a/FixNode/Makefile b/FixNode/Makefile
index 80e346cd3..b259c623d 100644
--- a/FixNode/Makefile
+++ b/FixNode/Makefile
@@ -27,7 +27,7 @@
 TARGET = fixnode
 
 CFILES = fixnode.c main.c triload.c
-LDLIBS = ../Dem2node/demparse.o ../Dem2node/mesh.o -lm
+LDLIBS = -lDEM -lScenery -lm
 
 
 include $(FG_ROOT_SRC)/commondefs
@@ -46,6 +46,9 @@ include $(COMMONRULES)
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/03/19 02:50:19  curt
+# Updated to support -lDEM class.
+#
 # Revision 1.2  1998/01/21 02:55:50  curt
 # Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
 #
diff --git a/FixNode/fixnode.c b/FixNode/fixnode.c
index afd707082..5276348d0 100644
--- a/FixNode/fixnode.c
+++ b/FixNode/fixnode.c
@@ -29,12 +29,14 @@
 #include <unistd.h>
 
 #include "fixnode.h"
-#include "../Dem2node/mesh.h"
 #include "triload.h"
 
 
 /* load the node information */
-void fixnodes(char *filename, struct MESH *m, double nodes[MAX_NODES][3]) {
+void fixnodes( char *filename, fgDEM dem, 
+	       float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
+	       double nodes[MAX_NODES][3] )
+{
     char toname[256];
     FILE *fd;
     int i;
@@ -50,7 +52,8 @@ void fixnodes(char *filename, struct MESH *m, double nodes[MAX_NODES][3]) {
 	/* printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0],
 	       nodes[i][1], nodes[i][2]); */
 
-	nodes[i][2] = mesh_altitude(m, nodes[i][0], nodes[i][1]);
+	nodes[i][2] = 
+	    dem.interpolate_altitude(dem_data, nodes[i][0], nodes[i][1]);
 
 	/* printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
 	       nodes[i][1], nodes[i][2]); */
@@ -77,9 +80,12 @@ void fixnodes(char *filename, struct MESH *m, double nodes[MAX_NODES][3]) {
 
 
 /* $Log$
-/* Revision 1.4  1998/03/03 16:00:57  curt
-/* More c++ compile tweaks.
+/* Revision 1.5  1998/03/19 02:50:19  curt
+/* Updated to support -lDEM class.
 /*
+ * Revision 1.4  1998/03/03 16:00:57  curt
+ * More c++ compile tweaks.
+ *
  * Revision 1.3  1998/01/09 23:03:08  curt
  * Restructured to split 1deg x 1deg dem's into 64 subsections.
  *
diff --git a/FixNode/fixnode.h b/FixNode/fixnode.h
index ee6501ac3..ec83d7b7d 100644
--- a/FixNode/fixnode.h
+++ b/FixNode/fixnode.h
@@ -1,55 +1,59 @@
-/* fixnode.h -- traverse the node file and fix the elevation of all the new
- *              interpolated points.
- *
- * Written by Curtis Olson, started November 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
+// fixnode.h -- traverse the node file and fix the elevation of all the new
+//              interpolated points.
+//
+// Written by Curtis Olson, started November 1997.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
 
 
-#ifndef FIXNODE_H
-#define FIXNODE_H
+#ifndef _FIXNODE_H
+#define _FIXNODE_H
 
 
 #include <stdio.h>
 #include <string.h>
 
 #include "triload.h"
-#include "../Dem2node/mesh.h"
+#include "../DEM/dem.h"
 
 
-/* load the node information */
-void fixnodes(char *basename, struct MESH *m, double nodes[MAX_NODES][3]);
+// load the node information
+void fixnodes( char *basename, fgDEM dem, 
+	       float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
+	       double nodes[MAX_NODES][3] );
 
 
-#endif /* FIXNODE_H */
+#endif // _FIXNODE_H
 
 
-/* $Log$
-/* Revision 1.3  1998/03/03 16:00:58  curt
-/* More c++ compile tweaks.
-/*
- * Revision 1.2  1997/12/02 13:12:07  curt
- * Updated to fix every node.
- *
- * Revision 1.1  1997/11/27 00:17:33  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.4  1998/03/19 02:50:19  curt
+// Updated to support -lDEM class.
+//
+// Revision 1.3  1998/03/03 16:00:58  curt
+// More c++ compile tweaks.
+//
+// Revision 1.2  1997/12/02 13:12:07  curt
+// Updated to fix every node.
+//
+// Revision 1.1  1997/11/27 00:17:33  curt
+// Initial revision.
+//
diff --git a/FixNode/main.c b/FixNode/main.c
index c2caca7e1..e903df613 100644
--- a/FixNode/main.c
+++ b/FixNode/main.c
@@ -1,27 +1,27 @@
-/* triload.c -- read in a .node file and fix the z values of the interpolated 
- *              points
- *
- * Written by Curtis Olson, started November 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
+// triload.c -- read in a .node file and fix the z values of the interpolated 
+//              points
+//
+// Written by Curtis Olson, started November 1997.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
 
 
 #include <dirent.h>
@@ -29,18 +29,20 @@
 #include <string.h>
 #include <sys/types.h>
 
-#include "../Dem2node/demparse.h"
+#include "../DEM/dem.h"
 #include "fixnode.h"
 #include "triload.h"
 
 
-/* Original DEM which is used to interpolate z values */
-static struct MESH dem_mesh;
+// Storage for the original DEM data which is used to interpolate z values
+static fgDEM dem;
+static float dem_data[DEM_SIZE_1][DEM_SIZE_1];
 
-/* Node list */
+// Node list
 static double nodes[MAX_NODES][3];
 
-/* find all the matching files in the specified directory and fix them */
+
+// find all the matching files in the specified directory and fix them
 void process_files(char *root_path) {
     DIR *d;
     struct dirent *de;
@@ -58,7 +60,7 @@ void process_files(char *root_path) {
 	if ( len > 7 ) {
 	    ptr = de->d_name;
 	    ptr += (len - 7);
-	    /* printf("--> %s \n", ptr); */
+	    // printf("--> %s \n", ptr);
 
 	    if ( strcmp(ptr, ".1.node") == 0 ) {
 		strcpy(file_path, root_path);
@@ -66,17 +68,17 @@ void process_files(char *root_path) {
 		strcat(file_path, de->d_name);
 		printf("File = %s\n", file_path);
 
-		/* load the input data files */
+		// load the input data files
 		triload(file_path, nodes);
 
-		fixnodes(file_path, &dem_mesh, nodes);
+		fixnodes(file_path, dem, dem_data, nodes);
 	    }
 	}
     }
 }
 
 
-/* main */
+// main
 int main(int argc, char **argv) {
     char demfile[256], root_path[256];
 
@@ -88,27 +90,32 @@ int main(int argc, char **argv) {
     strcpy(demfile, argv[1]);
     strcpy(root_path, argv[2]);
 
-    /* load the corresponding dem file so we can interpolate elev values */
-    dem_parse(demfile, &dem_mesh);
+    // load the corresponding dem file so we can interpolate elev values
+    dem.open(demfile);
+    dem.parse(dem_data);
+    dem.close();
 
-    /* process all the *.1.node files in the specified directory */
+    // process all the *.1.node files in the specified directory
     process_files(root_path);
 
     return(0);
 }
 
 
-/* $Log$
-/* Revision 1.4  1998/03/03 16:00:58  curt
-/* More c++ compile tweaks.
-/*
- * Revision 1.3  1998/01/09 23:03:08  curt
- * Restructured to split 1deg x 1deg dem's into 64 subsections.
- *
- * Revision 1.2  1997/12/02 13:12:07  curt
- * Updated to fix every node.
- *
- * Revision 1.1  1997/11/27 00:17:34  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.5  1998/03/19 02:50:20  curt
+// Updated to support -lDEM class.
+//
+// Revision 1.4  1998/03/03 16:00:58  curt
+// More c++ compile tweaks.
+//
+// Revision 1.3  1998/01/09 23:03:08  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.2  1997/12/02 13:12:07  curt
+// Updated to fix every node.
+//
+// Revision 1.1  1997/11/27 00:17:34  curt
+// Initial revision.
+//
+//
diff --git a/FixNode/triload.h b/FixNode/triload.h
index 8b5e32451..c145e11cf 100644
--- a/FixNode/triload.h
+++ b/FixNode/triload.h
@@ -24,8 +24,8 @@
  */
 
 
-#ifndef TRILOAD_H
-#define TRILOAD_H
+#ifndef _TRILOAD_H
+#define _TRILOAD_H
 
 
 #include <stdio.h>
@@ -43,13 +43,16 @@ extern int nodecount, tricount;
 void triload(char *basename, double nodes[MAX_NODES][3]);
 
 
-#endif /* TRILOAD_H */
+#endif // _TRILOAD_H
 
 
 /* $Log$
-/* Revision 1.3  1998/03/03 16:00:59  curt
-/* More c++ compile tweaks.
+/* Revision 1.4  1998/03/19 02:50:20  curt
+/* Updated to support -lDEM class.
 /*
+ * Revision 1.3  1998/03/03 16:00:59  curt
+ * More c++ compile tweaks.
+ *
  * Revision 1.2  1998/01/09 23:03:09  curt
  * Restructured to split 1deg x 1deg dem's into 64 subsections.
  *

From 138c3ebe05f6d953eb353220ed1aecefb3d17797 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 19 Mar 1998 02:51:41 +0000
Subject: [PATCH 047/283] Added special case handling to compensate for bugs in
 our beloved tri striper

---
 FixObj/obj.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index 3971aac83..8d2deceb8 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -208,10 +208,13 @@ void obj_fix(char *infile, char *outfile) {
 	    printf("new tri strip = %s", line);
 	    sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
 
-	    /* special case to handle a bug in our beloved tri striper */
+	    /* special cases to handle bugs in our beloved tri striper */
 	    if ( (n1 == 4) && (n2 == 2) && (n3 == 2) && (n4 == 1) ) {
 		n2 = 3;
 	    }
+	    if ( (n1 == 3) && (n2 == 1) && (n3 == 1) && (n4 == 0) ) {
+		n3 = 4;
+	    }
 
 	    dot_prod = check_cur_face(n1, n2, n3);
 	    if ( dot_prod < 0.0 ) {
@@ -288,9 +291,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.6  1998/03/03 15:36:12  curt
-/* Tweaks for compiling with g++
+/* Revision 1.7  1998/03/19 02:51:41  curt
+/* Added special case handling to compensate for bugs in our beloved tri striper
 /*
+ * Revision 1.6  1998/03/03 15:36:12  curt
+ * Tweaks for compiling with g++
+ *
  * Revision 1.5  1998/03/03 03:37:03  curt
  * Cumulative tweaks.
  *

From 21a2616ab42219e28297b8103726e1d2981eea2b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 19 Mar 1998 02:52:51 +0000
Subject: [PATCH 048/283] Updated to reflect some minor tool reorganization and
 the creation of class to handle DEM processing needs.

---
 Tools/Makefile       | 11 ++++++++---
 Tools/process-dem.pl |  8 ++++++--
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/Tools/Makefile b/Tools/Makefile
index 6a4ed347f..370d4ef55 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -27,9 +27,10 @@
 include $(FG_ROOT_SRC)/commondefs
 
 
-SUBDIRS = gpc2.01 AssemTris Dem2node DemRaw2Ascii FixNode FixObj SplitTris \
-	Stripe_u Tri2obj Triangle
-ORDEREDDIRS = $(SUBDIRS)
+LIBDIRS = DEM gpc2.01
+SUBDIRS = Areas AssemTris Dem2node DemRaw2Ascii FixNode FixObj \
+	SplitTris Stripe_u Tri2obj Triangle
+ORDEREDDIRS = $(LIBDIRS) $(SUBDIRS)
 
 
 all: 
@@ -90,6 +91,10 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.13  1998/03/19 02:52:51  curt
+# Updated to reflect some minor tool reorganization and the creation of class
+# to handle DEM processing needs.
+#
 # Revision 1.12  1998/03/19 01:48:34  curt
 # Added gpc-2.01 (generic polygon clipping library)
 #
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 8737d2744..a9c0ba05e 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -110,9 +110,9 @@ sub file_root {
 
 sub demfit {
     if ( $dem_file =~ m/.gz$/ ) {
-	$command = "gzip -dc $dem_file | ./Dem2node/demfit $ENV{FG_ROOT} - $error";
+	$command = "gzip -dc $dem_file | ./Dem2node/dem2node $ENV{FG_ROOT} - $error";
     } else {
-	$command = "./Dem2node/demfit $ENV{FG_ROOT} $dem_file $error";
+	$command = "./Dem2node/dem2node $ENV{FG_ROOT} $dem_file $error";
     }
 
     print "Running '$command'\n";
@@ -364,6 +364,10 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.13  1998/03/19 02:52:52  curt
+# Updated to reflect some minor tool reorganization and the creation of class
+# to handle DEM processing needs.
+#
 # Revision 1.12  1998/03/19 01:48:35  curt
 # Added gpc-2.01 (generic polygon clipping library)
 #

From bc4e92b8873a5f00bbe954e0a23f742a497b1369 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 19 Mar 1998 02:54:46 +0000
Subject: [PATCH 049/283] Reorganized into a class lib called fgDEM.

---
 DEM/Makefile   |  45 ++++
 DEM/dem.c      | 693 +++++++++++++++++++++++++++++++++++++++++++++++++
 DEM/dem.h      | 139 ++++++++++
 DEM/leastsqs.c | 121 +++++++++
 DEM/leastsqs.h |  67 +++++
 5 files changed, 1065 insertions(+)
 create mode 100644 DEM/Makefile
 create mode 100644 DEM/dem.c
 create mode 100644 DEM/dem.h
 create mode 100644 DEM/leastsqs.c
 create mode 100644 DEM/leastsqs.h

diff --git a/DEM/Makefile b/DEM/Makefile
new file mode 100644
index 000000000..fe04f0e9b
--- /dev/null
+++ b/DEM/Makefile
@@ -0,0 +1,45 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started March 1998.
+#
+# Copyright (C) 1997  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+ARLIBRARY = libDEM.a
+TARGETS = $(ARLIBRARY)
+
+CFILES =  dem.c leastsqs.c
+CXXFILES = 
+
+LDIRT = $(FG_ROOT_LIB)/$(ARLIBRARY)
+
+include $(FG_ROOT_SRC)/commondefs
+
+include $(COMMONRULES)
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/03/19 02:54:46  curt
+# Reorganized into a class lib called fgDEM.
+#
+
diff --git a/DEM/dem.c b/DEM/dem.c
new file mode 100644
index 000000000..1d783564d
--- /dev/null
+++ b/DEM/dem.c
@@ -0,0 +1,693 @@
+// -*- Mode: C++ -*-
+//
+// dem.c -- DEM management class
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include <ctype.h>    // isspace()
+#include <math.h>     // rint()
+#include <stdio.h>
+#include <stdlib.h>   // atoi()
+#include <sys/stat.h> // stat()
+#include <unistd.h>   // stat()
+
+#include "dem.h"
+#include "leastsqs.h"
+
+
+fgDEM::fgDEM( void ) {
+    // printf("class fgDEM CONstructor called.\n");
+}
+
+
+// open a DEM file
+int fgDEM::open ( char *file ) {
+    // open input file (or read from stdin)
+    if ( strcmp(file, "-") == 0 ) {
+	printf("Loading DEM data file: stdin\n");
+	fd = stdin;
+    } else {
+	if ( (fd = fopen(file, "r")) == NULL ) {
+	    printf("Cannot open %s\n", file);
+	    return(0);
+	}
+	printf("Loading DEM data file: %s\n", file);
+    }
+
+    return(1);
+}
+
+
+// close a DEM file
+int fgDEM::close ( void ) {
+    fclose(fd);
+
+    return(1);
+}
+
+
+// return next token from input stream
+static void next_token(FILE *fd, char *token) {
+    int result;
+
+    result = fscanf(fd, "%s", token);
+
+    if ( result == EOF ) {
+	strcpy(token, "__END_OF_FILE__");
+	printf("    Warning:  Reached end of file!\n");
+    }
+
+    // printf("    returning %s\n", token);
+}
+
+
+// return next integer from input stream
+static int next_int(FILE *fd) {
+    char token[80];
+
+    next_token(fd, token);
+    return ( atoi(token) );
+}
+
+
+// return next double from input stream
+double next_double(FILE *fd) {
+    char token[80];
+
+    next_token(fd, token);
+    return ( atof(token) );
+}
+
+
+// return next exponential num from input stream
+int next_exp(FILE *fd) {
+    double mantissa;
+    int exp, acc;
+    int i;
+
+    fscanf(fd, "%lfD%d", &mantissa, &exp);
+
+    // printf("    Mantissa = %.4f  Exp = %d\n", mantissa, exp);
+
+    acc = 1;
+    if ( exp > 0 ) {
+	for ( i = 1; i <= exp; i++ ) {
+	    acc *= 10;
+	}
+    } else if ( exp < 0 ) {
+	for ( i = -1; i >= exp; i-- ) {
+	    acc /= 10;
+	}
+    }
+
+    return( (int)rint(mantissa * (double)acc) );
+}
+
+
+// read and parse DEM "A" record
+void fgDEM::read_a_record( void ) {
+    int i, inum;
+    double dnum;
+    char name[144];
+    char token[80];
+    char *ptr;
+
+    // get the name field (144 characters)
+    for ( i = 0; i < 144; i++ ) {
+	name[i] = fgetc(fd);
+    }
+    name[i+1] = '\0';
+
+    // clean off the whitespace at the end
+    for ( i = strlen(name)-2; i > 0; i-- ) {
+	if ( !isspace(name[i]) ) {
+	    i=0;
+	} else {
+	    name[i] = '\0'; 
+	}
+    }
+    printf("    Quad name field: %s\n", name);
+
+    // DEM level code, 3 reflects processing by DMA
+    inum = next_int(fd);
+    printf("    DEM level code = %d\n", inum);
+
+    // Pattern code, 1 indicates a regular elevation pattern
+    inum = next_int(fd);
+    printf("    Pattern code = %d\n", inum);
+
+    // Planimetric reference system code, 0 indicates geographic
+    // coordinate system.
+    inum = next_int(fd);
+    printf("    Planimetric reference code = %d\n", inum);
+
+    // Zone code
+    inum = next_int(fd);
+    printf("    Zone code = %d\n", inum);
+
+    // Map projection parameters (ignored)
+    for ( i = 0; i < 15; i++ ) {
+	dnum = next_double(fd);
+	// printf("%d: %f\n",i,dnum);
+    }
+
+    // Units code, 3 represents arc-seconds as the unit of measure for
+    // ground planimetric coordinates throughout the file.
+    inum = next_int(fd);
+    if ( inum != 3 ) {
+	printf("    Unknown (X,Y) units code = %d!\n", inum);
+	exit(-1);
+    }
+
+    // Units code; 2 represents meters as the unit of measure for
+    // elevation coordinates throughout the file.
+    inum = next_int(fd);
+    if ( inum != 2 ) {
+	printf("    Unknown (Z) units code = %d!\n", inum);
+	exit(-1);
+    }
+
+    // Number (n) of sides in the polygon which defines the coverage of
+    // the DEM file (usually equal to 4).
+    inum = next_int(fd);
+    if ( inum != 4 ) {
+	printf("    Unknown polygon dimension = %d!\n", inum);
+	exit(-1);
+    }
+
+    // Ground coordinates of bounding box in arc-seconds
+    dem_x1 = originx = next_exp(fd);
+    dem_y1 = originy = next_exp(fd);
+    printf("    Origin = (%.2f,%.2f)\n", originx, originy);
+
+    dem_x2 = next_exp(fd);
+    dem_y2 = next_exp(fd);
+
+    dem_x3 = next_exp(fd);
+    dem_y3 = next_exp(fd);
+
+    dem_x4 = next_exp(fd);
+    dem_y4 = next_exp(fd);
+
+    // Minimum/maximum elevations in meters
+    dem_z1 = next_exp(fd);
+    dem_z2 = next_exp(fd);
+    printf("    Elevation range %.4f %.4f\n", dem_z1, dem_z2);
+
+    // Counterclockwise angle from the primary axis of ground
+    // planimetric referenced to the primary axis of the DEM local
+    // reference system.
+    next_token(fd, token);
+
+    // Accuracy code; 0 indicates that a record of accuracy does not
+    // exist and that no record type C will follow.
+
+    // DEM spacial resolution.  Usually (3,3,1) (3,6,1) or (3,9,1)
+    // depending on latitude
+
+    // I will eventually have to do something with this for data at
+    // higher latitudes */
+    next_token(fd, token);
+    printf("    accuracy & spacial resolution string = %s\n", token);
+    i = strlen(token);
+    printf("    length = %d\n", i);
+
+    ptr = token + i - 12;
+    printf("    last field = %s = %.2f\n", ptr, atof(ptr));
+    ptr[0] = '\0';
+
+    ptr = ptr - 12;
+    col_step = atof(ptr);
+    printf("    last field = %s = %.2f\n", ptr, col_step);
+    ptr[0] = '\0';
+
+    ptr = ptr - 12;
+    row_step = atof(ptr);
+    printf("    last field = %s = %.2f\n", ptr, row_step);
+    ptr[0] = '\0';
+
+    // accuracy code = atod(token)
+    inum = atoi(token);
+    printf("    Accuracy code = %d\n", inum);
+
+    printf("    column step = %.2f  row step = %.2f\n", 
+	   col_step, row_step);
+    // dimension of arrays to follow (1)
+    next_token(fd, token);
+
+    // number of profiles
+    dem_num_profiles = rows = next_int(fd);
+    printf("    Expecting %d profiles\n", dem_num_profiles);
+}
+
+
+// read and parse DEM "B" record
+void fgDEM::read_b_record(float dem_data[DEM_SIZE_1][DEM_SIZE_1])
+{
+    char token[80];
+    int i;
+
+    // row / column id of this profile
+    prof_col = next_int(fd);
+    prof_row = next_int(fd);
+    // printf("col id = %d  row id = %d\n", prof_col, prof_row);
+
+    // Number of columns and rows (elevations) in this profile
+    prof_num_cols = cols = next_int(fd);
+    prof_num_rows = next_int(fd);
+    // printf("    profile num rows = %d\n", prof_num_cols);
+
+    // Ground planimetric coordinates (arc-seconds) of the first
+    // elevation in the profile
+    prof_x1 = next_exp(fd);
+    prof_y1 = next_exp(fd);
+    // printf("    Starting at %.2f %.2f\n", prof_x1, prof_y1);
+
+    // Elevation of local datum for the profile.  Always zero for
+    // 1-degree DEM, the reference is mean sea level.
+    next_token(fd, token);
+
+    // Minimum and maximum elevations for the profile.
+    next_token(fd, token);
+    next_token(fd, token);
+
+    // One (usually) dimensional array (prof_num_cols,1) of elevations
+    for ( i = 0; i < prof_num_cols; i++ ) {
+	prof_data = next_int(fd);
+	dem_data[i][cur_row] = (float)prof_data;
+    }
+}
+
+
+// parse dem file
+int fgDEM::parse( float dem_data[DEM_SIZE_1][DEM_SIZE_1] ) {
+    int i;
+
+    cur_row = 0;
+
+    read_a_record();
+
+    for ( i = 0; i < dem_num_profiles; i++ ) {
+	read_b_record( dem_data );
+	cur_row++;
+
+	if ( cur_row % 100 == 0 ) {
+	    printf("    loaded %d profiles of data\n", cur_row);
+	}
+    }
+
+    printf("    Done parsing\n");
+
+    return(0);
+}
+
+
+// return the current altitude based on mesh data.  We should rewrite
+// this to interpolate exact values, but for now this is good enough
+double fgDEM::interpolate_altitude( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
+				    double lon, double lat)
+{
+    // we expect incoming (lon,lat) to be in arcsec for now
+
+    double xlocal, ylocal, dx, dy, zA, zB, elev;
+    int x1, x2, x3, y1, y2, y3;
+    float z1, z2, z3;
+    int xindex, yindex;
+
+    /* determine if we are in the lower triangle or the upper triangle 
+       ______
+       |   /|
+       |  / |
+       | /  |
+       |/   |
+       ------
+
+       then calculate our end points
+     */
+
+    xlocal = (lon - originx) / col_step;
+    ylocal = (lat - originy) / row_step;
+
+    xindex = (int)(xlocal);
+    yindex = (int)(ylocal);
+
+    // printf("xindex = %d  yindex = %d\n", xindex, yindex);
+
+    if ( xindex + 1 == cols ) {
+	xindex--;
+    }
+
+    if ( yindex + 1 == rows ) {
+	yindex--;
+    }
+
+    if ( (xindex < 0) || (xindex + 1 >= cols) ||
+	 (yindex < 0) || (yindex + 1 >= rows) ) {
+	return(-9999);
+    }
+
+    dx = xlocal - xindex;
+    dy = ylocal - yindex;
+
+    if ( dx > dy ) {
+	// lower triangle
+	// printf("  Lower triangle\n");
+
+	x1 = xindex; 
+	y1 = yindex; 
+	z1 = dem_data[x1][y1];
+
+	x2 = xindex + 1; 
+	y2 = yindex; 
+	z2 = dem_data[x2][y2];
+				  
+	x3 = xindex + 1; 
+	y3 = yindex + 1; 
+	z3 = dem_data[x3][y3];
+
+	// printf("  dx = %.2f  dy = %.2f\n", dx, dy);
+	// printf("  (x1,y1,z1) = (%d,%d,%d)\n", x1, y1, z1);
+	// printf("  (x2,y2,z2) = (%d,%d,%d)\n", x2, y2, z2);
+	// printf("  (x3,y3,z3) = (%d,%d,%d)\n", x3, y3, z3);
+
+	zA = dx * (z2 - z1) + z1;
+	zB = dx * (z3 - z1) + z1;
+	
+	// printf("  zA = %.2f  zB = %.2f\n", zA, zB);
+
+	if ( dx > EPSILON ) {
+	    elev = dy * (zB - zA) / dx + zA;
+	} else {
+	    elev = zA;
+	}
+    } else {
+	// upper triangle
+	// printf("  Upper triangle\n");
+
+	x1 = xindex; 
+	y1 = yindex; 
+	z1 = dem_data[x1][y1];
+
+	x2 = xindex; 
+	y2 = yindex + 1; 
+	z2 = dem_data[x2][y2];
+				  
+	x3 = xindex + 1; 
+	y3 = yindex + 1; 
+	z3 = dem_data[x3][y3];
+
+	// printf("  dx = %.2f  dy = %.2f\n", dx, dy);
+	// printf("  (x1,y1,z1) = (%d,%d,%d)\n", x1, y1, z1);
+	// printf("  (x2,y2,z2) = (%d,%d,%d)\n", x2, y2, z2);
+	// printf("  (x3,y3,z3) = (%d,%d,%d)\n", x3, y3, z3);
+ 
+	zA = dy * (z2 - z1) + z1;
+	zB = dy * (z3 - z1) + z1;
+	
+	// printf("  zA = %.2f  zB = %.2f\n", zA, zB );
+	// printf("  xB - xA = %.2f\n", col_step * dy / row_step);
+
+	if ( dy > EPSILON ) {
+	    elev = dx * (zB - zA) / dy    + zA;
+	} else {
+	    elev = zA;
+	}
+    }
+
+    return(elev);
+}
+
+
+// Use least squares to fit a simpler data set to dem data
+void fgDEM::fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
+		 float output_data[DEM_SIZE_1][DEM_SIZE_1], 
+		 char *fg_root, double error, struct fgBUCKET *p )
+{
+    double x[DEM_SIZE_1], y[DEM_SIZE_1];
+    double m, b, ave_error, max_error;
+    double cury, lasty;
+    int n, row, start, end, good_fit;
+    int colmin, colmax, rowmin, rowmax;
+    // FILE *dem, *fit, *fit1;
+
+    printf("Initializing output mesh structure\n");
+    outputmesh_init( output_data );
+
+    // determine dimensions
+    colmin = p->x * ( (cols - 1) / 8);
+    colmax = colmin + ( (cols - 1) / 8);
+    rowmin = p->y * ( (rows - 1) / 8);
+    rowmax = rowmin + ( (rows - 1) / 8);
+    printf("Fitting region = %d,%d to %d,%d\n", colmin, rowmin, colmax, rowmax);
+    
+    // include the corners explicitly
+    outputmesh_set_pt(output_data, colmin, rowmin, dem_data[colmin][rowmin]);
+    outputmesh_set_pt(output_data, colmin, rowmax, dem_data[colmin][rowmax]);
+    outputmesh_set_pt(output_data, colmax, rowmax, dem_data[colmax][rowmax]);
+    outputmesh_set_pt(output_data, colmax, rowmin, dem_data[colmax][rowmin]);
+
+    printf("Beginning best fit procedure\n");
+
+    for ( row = rowmin; row <= rowmax; row++ ) {
+	// fit  = fopen("fit.dat",  "w");
+	// fit1 = fopen("fit1.dat", "w");
+
+	start = colmin;
+
+	// printf("    fitting row = %d\n", row);
+
+	while ( start < colmax ) {
+	    end = start + 1;
+	    good_fit = 1;
+
+	    x[(end - start) - 1] = 0.0 + ( start * col_step );
+	    y[(end - start) - 1] = dem_data[start][row];
+
+	    while ( (end <= colmax) && good_fit ) {
+		n = (end - start) + 1;
+		// printf("Least square of first %d points\n", n);
+		x[end - start] = 0.0 + ( end * col_step );
+		y[end - start] = dem_data[end][row];
+		least_squares(x, y, n, &m, &b);
+		ave_error = least_squares_error(x, y, n, m, b);
+		max_error = least_squares_max_error(x, y, n, m, b);
+
+		/*
+		printf("%d - %d  ave error = %.2f  max error = %.2f  y = %.2f*x + %.2f\n", 
+		start, end, ave_error, max_error, m, b);
+		
+		f = fopen("gnuplot.dat", "w");
+		for ( j = 0; j <= end; j++) {
+		    fprintf(f, "%.2f %.2f\n", 0.0 + ( j * col_step ), 
+			    dem_data[row][j]);
+		}
+		for ( j = start; j <= end; j++) {
+		    fprintf(f, "%.2f %.2f\n", 0.0 + ( j * col_step ), 
+			    dem_data[row][j]);
+		}
+		fclose(f);
+
+		printf("Please hit return: "); gets(junk);
+		*/
+
+		if ( max_error > error ) {
+		    good_fit = 0;
+		}
+		
+		end++;
+	    }
+
+	    if ( !good_fit ) {
+		// error exceeded the threshold, back up
+		end -= 2;  // back "end" up to the last good enough fit
+		n--;       // back "n" up appropriately too
+	    } else {
+		// we popped out of the above loop while still within
+		// the error threshold, so we must be at the end of
+		// the data set
+		end--;
+	    }
+	    
+	    least_squares(x, y, n, &m, &b);
+	    ave_error = least_squares_error(x, y, n, m, b);
+	    max_error = least_squares_max_error(x, y, n, m, b);
+
+	    /*
+	    printf("\n");
+	    printf("%d - %d  ave error = %.2f  max error = %.2f  y = %.2f*x + %.2f\n", 
+		   start, end, ave_error, max_error, m, b);
+	    printf("\n");
+
+	    fprintf(fit1, "%.2f %.2f\n", x[0], m * x[0] + b);
+	    fprintf(fit1, "%.2f %.2f\n", x[end-start], m * x[end-start] + b);
+	    */
+
+	    if ( start > colmin ) {
+		// skip this for the first line segment
+		cury = m * x[0] + b;
+		outputmesh_set_pt(output_data, start, row, (lasty + cury) / 2);
+		// fprintf(fit, "%.2f %.2f\n", x[0], (lasty + cury) / 2);
+	    }
+
+	    lasty = m * x[end-start] + b;
+	    start = end;
+	}
+
+	/*
+	fclose(fit);
+	fclose(fit1);
+
+	dem = fopen("gnuplot.dat", "w");
+	for ( j = 0; j < DEM_SIZE_1; j++) {
+	    fprintf(dem, "%.2f %.2f\n", 0.0 + ( j * col_step ), 
+		    dem_data[j][row]);
+	} 
+	fclose(dem);
+	*/
+
+	// NOTICE, this is for testing only.  This instance of
+        // output_nodes should be removed.  It should be called only
+        // once at the end once all the nodes have been generated.
+	// newmesh_output_nodes(&nm, "mesh.node");
+	// printf("Please hit return: "); gets(junk);
+    }
+
+    outputmesh_output_nodes(output_data, fg_root, p);
+}
+
+
+// Initialize output mesh structure
+void fgDEM::outputmesh_init( float output_data[DEM_SIZE_1][DEM_SIZE_1] ) {
+    int i, j;
+
+    for ( i = 0; i < DEM_SIZE_1; i++ ) {
+	for ( j = 0; j < DEM_SIZE_1; j++ ) {
+	    output_data[i][j] = -9999.0;
+	}
+    }
+}
+
+
+// Get the value of a mesh node
+double fgDEM::outputmesh_get_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
+				 int i, int j )
+{
+    return ( output_data[i][j] );
+}
+
+
+// Set the value of a mesh node
+void fgDEM::outputmesh_set_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
+			       int i, int j, double value )
+{
+    // printf("Setting data[%d][%d] = %.2f\n", i, j, value);
+   output_data[i][j] = value;
+}
+
+
+// Write out a node file that can be used by the "triangle" program
+void fgDEM::outputmesh_output_nodes( float output_data[DEM_SIZE_1][DEM_SIZE_1],
+				     char *fg_root, struct fgBUCKET *p )
+{
+    struct stat stat_buf;
+    char base_path[256], dir[256], file[256];
+    char command[256];
+    FILE *fd;
+    long int index;
+    int colmin, colmax, rowmin, rowmax;
+    int i, j, count, result;
+
+    // determine dimensions
+    colmin = p->x * ( (cols - 1) / 8);
+    colmax = colmin + ( (cols - 1) / 8);
+    rowmin = p->y * ( (rows - 1) / 8);
+    rowmax = rowmin + ( (rows - 1) / 8);
+    printf("  dumping region = %d,%d to %d,%d\n", 
+	   colmin, rowmin, colmax, rowmax);
+
+    // generate the base directory
+    fgBucketGenBasePath(p, base_path);
+    printf("fg_root = %s  Base Path = %s\n", fg_root, base_path);
+    sprintf(dir, "%s/Scenery/%s", fg_root, base_path);
+    printf("Dir = %s\n", dir);
+    
+    // stat() directory and create if needed
+    result = stat(dir, &stat_buf);
+    if ( result != 0 ) {
+	printf("Stat error need to create directory\n");
+	sprintf(command, "mkdir -p %s\n", dir);
+	system(command);
+    } else {
+	// assume directory exists
+    }
+
+    // get index and generate output file name
+    index = fgBucketGenIndex(p);
+    sprintf(file, "%s/%ld.node", dir, index);
+
+    printf("Creating node file:  %s\n", file);
+    fd = fopen(file, "w");
+
+    // first count nodes to generate header
+    count = 0;
+    for ( j = rowmin; j <= rowmax; j++ ) {
+	for ( i = colmin; i <= colmax; i++ ) {
+	    if ( output_data[i][j] > -9000.0 ) {
+		count++;
+	    }
+	}
+	// printf("    count = %d\n", count);
+    }
+    fprintf(fd, "%d 2 1 0\n", count);
+
+    // now write out actual node data
+    count = 1;
+    for ( j = rowmin; j <= rowmax; j++ ) {
+	for ( i = colmin; i <= colmax; i++ ) {
+	    if ( output_data[i][j] > -9000.0 ) {
+		fprintf(fd, "%d %.2f %.2f %.2f\n", 
+			count++, 
+			originx + (double)i * col_step, 
+			originy + (double)j * row_step,
+			output_data[i][j]);
+	    }
+	}
+	// printf("    count = %d\n", count);
+    }
+
+    fclose(fd);
+}
+
+
+fgDEM::~fgDEM( void ) {
+    // printf("class fgDEM DEstructor called.\n");
+}
+
+
+// $Log$
+// Revision 1.1  1998/03/19 02:54:47  curt
+// Reorganized into a class lib called fgDEM.
+//
+// Revision 1.1  1998/03/19 01:46:28  curt
+// Initial revision.
+//
diff --git a/DEM/dem.h b/DEM/dem.h
new file mode 100644
index 000000000..b8ffc0d14
--- /dev/null
+++ b/DEM/dem.h
@@ -0,0 +1,139 @@
+// -*- Mode: C++ -*-
+//
+// dem.h -- DEM management class
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _DEM_H
+#define _DEM_H
+
+
+#include <stdio.h>
+
+#include <Scenery/bucketutils.h>
+
+
+#define EPSILON 0.000001
+#define DEM_SIZE 1200
+#define DEM_SIZE_1 1201
+
+
+class fgDEM {
+    // file pointer for input
+    FILE *fd;
+
+    // coordinates (in arc seconds) of south west corner
+    double originx, originy;
+    
+    // number of columns and rows
+    int cols, rows;
+    
+    // Distance between column and row data points (in arc seconds)
+    double col_step, row_step;
+    
+    // the actual mesh data allocated here
+    // float dem_data[DEM_SIZE_1][DEM_SIZE_1];
+    // float output_data[DEM_SIZE_1][DEM_SIZE_1];
+
+    // Current "A" Record Information
+    char dem_description[80], dem_quadrangle[80];
+    double dem_x1, dem_y1, dem_x2, dem_y2, dem_x3, dem_y3, dem_x4, dem_y4;
+    double dem_z1, dem_z2;
+    int dem_resolution, dem_num_profiles;
+  
+    // Current "B" Record Information
+    int prof_col, prof_row;
+    int prof_num_cols, prof_num_rows;
+    double prof_x1, prof_y1;
+    int prof_data;
+
+    // temporary values for the class to use
+    char option_name[32];
+    int do_data;
+    int cur_col, cur_row;
+
+public:
+
+    // Constructor (opens a DEM file)
+    fgDEM( void );
+
+    // open a DEM file (use "-" if input is coming from stdin)
+    int open ( char *file );
+
+    // close a DEM file
+    int close ( void );
+
+    // parse a DEM file
+    int parse( float dem_data[DEM_SIZE_1][DEM_SIZE_1] );
+
+    // read and parse DEM "A" record
+    void read_a_record( );
+
+    // read and parse DEM "B" record
+    void read_b_record( float dem_data[DEM_SIZE_1][DEM_SIZE_1] );
+
+    // Informational methods
+    double info_originx( void ) { return(originx); }
+    double info_originy( void ) { return(originy); }
+
+    // return the current altitude based on mesh data.  We should
+    // rewrite this to interpolate exact values, but for now this is
+    // good enough
+    double interpolate_altitude( float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
+				 double lon, double lat);
+
+    // Use least squares to fit a simpler data set to dem data
+    void fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
+	      float output_data[DEM_SIZE_1][DEM_SIZE_1], 
+	      char *fg_root, double error, struct fgBUCKET *p );
+
+    // Initialize output mesh structure
+    void outputmesh_init( float output_data[DEM_SIZE_1][DEM_SIZE_1] );
+
+    // Get the value of a mesh node
+    double outputmesh_get_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
+			      int i, int j );
+
+    // Set the value of a mesh node
+    void outputmesh_set_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
+			    int i, int j, double value );
+
+    // Write out a node file that can be used by the "triangle" program
+    void outputmesh_output_nodes( float output_data[DEM_SIZE_1][DEM_SIZE_1],
+				  char *fg_root, struct fgBUCKET *p );
+
+    // Destructor
+    ~fgDEM( void );
+};
+
+
+#endif // _DEM_H
+
+
+// $Log$
+// Revision 1.1  1998/03/19 02:54:47  curt
+// Reorganized into a class lib called fgDEM.
+//
+// Revision 1.1  1998/03/19 01:46:29  curt
+// Initial revision.
+//
diff --git a/DEM/leastsqs.c b/DEM/leastsqs.c
new file mode 100644
index 000000000..1eebb0330
--- /dev/null
+++ b/DEM/leastsqs.c
@@ -0,0 +1,121 @@
+/* leastsqs.c -- Implements a simple linear least squares best fit routine
+ *
+ * Written by Curtis Olson, started September 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+#include <stdio.h>
+
+#include "leastsqs.h"
+
+
+/* 
+Least squares fit:
+
+y = b0 + b1x
+
+     n*sum(xi*yi) - (sum(xi)*sum(yi))
+b1 = --------------------------------
+     n*sum(xi^2) - (sum(xi))^2
+
+
+b0 = sum(yi)/n - b1*(sum(xi)/n)
+*/
+
+void least_squares(double *x, double *y, int n, double *m, double *b) {
+    double sum_xi, sum_yi, sum_xi_2, sum_xi_yi;
+    int i;
+
+    sum_xi = sum_yi = sum_xi_2 = sum_xi_yi = 0.0;
+
+    for ( i = 0; i < n; i++ ) {
+	sum_xi += x[i];
+	sum_yi += y[i];
+	sum_xi_2 += x[i] * x[i];
+	sum_xi_yi += x[i] * y[i];
+    }
+
+    /* printf("sum(xi)=%.2f  sum(yi)=%.2f  sum(xi^2)=%.2f  sum(xi*yi)=%.2f\n",
+	   sum_xi, sum_yi, sum_xi_2, sum_xi_yi); */
+
+    *m = ( (double)n * sum_xi_yi - sum_xi * sum_yi ) / 
+	( (double)n * sum_xi_2 - sum_xi * sum_xi );
+    *b = (sum_yi / (double)n) - (*m) * (sum_xi / (double)n);
+
+    /* printf("slope = %.2f  intercept = %.2f\n", *m, *b); */
+}
+
+
+/* 
+  return the least squares error:
+
+              (y[i] - y_hat[i])^2
+              -------------------
+                      n
+ */
+double least_squares_error(double *x, double *y, int n, double m, double b) {
+    int i;
+    double error, sum;
+
+    sum = 0.0;
+
+    for ( i = 0; i < n; i++ ) {
+	error = y[i] - (m * x[i] + b);
+	sum += error * error;
+	/* printf("%.2f %.2f\n", error, sum); */
+    }
+
+    return ( sum / (double)n );
+}
+
+
+/* 
+  return the maximum least squares error:
+
+              (y[i] - y_hat[i])^2
+ */
+double least_squares_max_error(double *x, double *y, int n, double m, double b){
+    int i;
+    double error, max_error;
+
+    max_error = 0.0;
+
+    for ( i = 0; i < n; i++ ) {
+	error = y[i] - (m * x[i] + b);
+	error = error * error;
+	if ( error > max_error ) {
+	    max_error = error;
+	}
+    }
+
+    return ( max_error );
+}
+
+
+/* $Log$
+/* Revision 1.1  1998/03/19 02:54:47  curt
+/* Reorganized into a class lib called fgDEM.
+/*
+ * Revision 1.1  1997/10/13 17:02:35  curt
+ * Initial revision.
+ *
+ */
diff --git a/DEM/leastsqs.h b/DEM/leastsqs.h
new file mode 100644
index 000000000..c2b8866ef
--- /dev/null
+++ b/DEM/leastsqs.h
@@ -0,0 +1,67 @@
+/* leastsqs.h -- Implements a simple linear least squares best fit routine
+ *
+ * Written by Curtis Olson, started September 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ */
+
+
+/* 
+Least squares fit:
+
+y = b0 + b1x
+
+     n*sum(xi*yi) - (sum(xi)*sum(yi))
+b1 = --------------------------------
+     n*sum(xi^2) - (sum(xi))^2
+
+
+b0 = sum(yi)/n - b1*(sum(xi)/n)
+*/
+
+void least_squares(double *x, double *y, int n, double *m, double *b);
+
+
+/* 
+  return the least squares error:
+
+              (y[i] - y_hat[i])^2
+              -------------------
+                      n
+ */
+double least_squares_error(double *x, double *y, int n, double m, double b);
+
+
+/* 
+  return the maximum least squares error:
+
+              (y[i] - y_hat[i])^2
+ */
+double least_squares_max_error(double *x, double *y, int n, double m, double b);
+
+
+/* $Log$
+/* Revision 1.1  1998/03/19 02:54:48  curt
+/* Reorganized into a class lib called fgDEM.
+/*
+ * Revision 1.1  1997/10/13 17:02:35  curt
+ * Initial revision.
+ *
+ */

From f3fed05fc962b8ed6a425b090f5f76ff359b2e45 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 23 Mar 1998 20:35:41 +0000
Subject: [PATCH 050/283] Updated to use FG_EPSILON

---
 DEM/dem.c | 9 +++++++--
 DEM/dem.h | 4 +++-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/DEM/dem.c b/DEM/dem.c
index 1d783564d..ae46f8689 100644
--- a/DEM/dem.c
+++ b/DEM/dem.c
@@ -34,6 +34,8 @@
 #include "dem.h"
 #include "leastsqs.h"
 
+#include <Include/fg_constants.h>
+
 
 fgDEM::fgDEM( void ) {
     // printf("class fgDEM CONstructor called.\n");
@@ -395,7 +397,7 @@ double fgDEM::interpolate_altitude( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
 	
 	// printf("  zA = %.2f  zB = %.2f\n", zA, zB);
 
-	if ( dx > EPSILON ) {
+	if ( dx > FG_EPSILON ) {
 	    elev = dy * (zB - zA) / dx + zA;
 	} else {
 	    elev = zA;
@@ -427,7 +429,7 @@ double fgDEM::interpolate_altitude( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
 	// printf("  zA = %.2f  zB = %.2f\n", zA, zB );
 	// printf("  xB - xA = %.2f\n", col_step * dy / row_step);
 
-	if ( dy > EPSILON ) {
+	if ( dy > FG_EPSILON ) {
 	    elev = dx * (zB - zA) / dy    + zA;
 	} else {
 	    elev = zA;
@@ -685,6 +687,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.2  1998/03/23 20:35:41  curt
+// Updated to use FG_EPSILON
+//
 // Revision 1.1  1998/03/19 02:54:47  curt
 // Reorganized into a class lib called fgDEM.
 //
diff --git a/DEM/dem.h b/DEM/dem.h
index b8ffc0d14..64f04e4b4 100644
--- a/DEM/dem.h
+++ b/DEM/dem.h
@@ -33,7 +33,6 @@
 #include <Scenery/bucketutils.h>
 
 
-#define EPSILON 0.000001
 #define DEM_SIZE 1200
 #define DEM_SIZE_1 1201
 
@@ -131,6 +130,9 @@ public:
 
 
 // $Log$
+// Revision 1.2  1998/03/23 20:35:42  curt
+// Updated to use FG_EPSILON
+//
 // Revision 1.1  1998/03/19 02:54:47  curt
 // Reorganized into a class lib called fgDEM.
 //

From e9ffabdc8eb9888b2de2545facbc719a516648fd Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 6 Apr 1998 21:09:37 +0000
Subject: [PATCH 051/283] Additional win32 support. Fixed a bad bug in dem file
 parsing that was causing the output to be flipped about x = y.

---
 DEM/dem.c             | 111 ++++++++++++++++++++++++++++++++++++------
 DemRaw2ascii/rawdem.c |  11 +++--
 FixNode/Makefile      |   7 ++-
 FixNode/main.c        |   9 +++-
 Tools/Makefile        |  15 ++++--
 Tools/Todo            |   4 ++
 Tools/process-dem.pl  |  52 +++++++++++++++-----
 7 files changed, 172 insertions(+), 37 deletions(-)

diff --git a/DEM/dem.c b/DEM/dem.c
index ae46f8689..0dc3aa5e8 100644
--- a/DEM/dem.c
+++ b/DEM/dem.c
@@ -28,6 +28,7 @@
 #include <math.h>     // rint()
 #include <stdio.h>
 #include <stdlib.h>   // atoi()
+#include <string.h>
 #include <sys/stat.h> // stat()
 #include <unistd.h>   // stat()
 
@@ -37,11 +38,61 @@
 #include <Include/fg_constants.h>
 
 
+#ifdef WIN32
+#  define MKDIR(a) mkdir(a,S_IRWXU)     // I am just guessing at this flag (NHV)
+#endif // WIN32
+
+
 fgDEM::fgDEM( void ) {
     // printf("class fgDEM CONstructor called.\n");
 }
 
 
+#ifdef WIN32
+
+// return the file path name ( foo/bar/file.ext = foo/bar )
+void extract_path (char *in, char *base) {
+    int len, i;
+    
+    len = strlen (in);
+    strcpy (base, in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    base[i] = '\0';
+}
+
+
+// Make a subdirectory
+int my_mkdir (char *dir) {
+    struct stat stat_buf;
+    int result;
+
+    printf ("mk_dir() ");
+
+    result = stat (dir, &stat_buf);
+
+    if (result != 0) {
+	MKDIR (dir);
+	result = stat (dir, &stat_buf);
+	if (result != 0) {
+	    printf ("problem creating %s\n", dir);
+	} else {
+	    printf ("%s created\n", dir);
+	}
+    } else {
+	printf ("%s already exists\n", dir);
+    }
+
+    return (result);
+}
+
+#endif // WIN32
+
+
 // open a DEM file
 int fgDEM::open ( char *file ) {
     // open input file (or read from stdin)
@@ -93,7 +144,7 @@ static int next_int(FILE *fd) {
 
 
 // return next double from input stream
-double next_double(FILE *fd) {
+static double next_double(FILE *fd) {
     char token[80];
 
     next_token(fd, token);
@@ -102,7 +153,7 @@ double next_double(FILE *fd) {
 
 
 // return next exponential num from input stream
-int next_exp(FILE *fd) {
+static int next_exp(FILE *fd) {
     double mantissa;
     int exp, acc;
     int i;
@@ -258,7 +309,7 @@ void fgDEM::read_a_record( void ) {
     next_token(fd, token);
 
     // number of profiles
-    dem_num_profiles = rows = next_int(fd);
+    dem_num_profiles = cols = next_int(fd);
     printf("    Expecting %d profiles\n", dem_num_profiles);
 }
 
@@ -270,14 +321,14 @@ void fgDEM::read_b_record(float dem_data[DEM_SIZE_1][DEM_SIZE_1])
     int i;
 
     // row / column id of this profile
-    prof_col = next_int(fd);
     prof_row = next_int(fd);
+    prof_col = next_int(fd);
     // printf("col id = %d  row id = %d\n", prof_col, prof_row);
 
     // Number of columns and rows (elevations) in this profile
-    prof_num_cols = cols = next_int(fd);
-    prof_num_rows = next_int(fd);
-    // printf("    profile num rows = %d\n", prof_num_cols);
+    prof_num_rows = rows = next_int(fd);
+    prof_num_cols = next_int(fd);
+    // printf("    profile num rows = %d\n", prof_num_rows);
 
     // Ground planimetric coordinates (arc-seconds) of the first
     // elevation in the profile
@@ -294,9 +345,9 @@ void fgDEM::read_b_record(float dem_data[DEM_SIZE_1][DEM_SIZE_1])
     next_token(fd, token);
 
     // One (usually) dimensional array (prof_num_cols,1) of elevations
-    for ( i = 0; i < prof_num_cols; i++ ) {
+    for ( i = 0; i < prof_num_rows; i++ ) {
 	prof_data = next_int(fd);
-	dem_data[i][cur_row] = (float)prof_data;
+	dem_data[cur_col][i] = (float)prof_data;
     }
 }
 
@@ -311,10 +362,10 @@ int fgDEM::parse( float dem_data[DEM_SIZE_1][DEM_SIZE_1] ) {
 
     for ( i = 0; i < dem_num_profiles; i++ ) {
 	read_b_record( dem_data );
-	cur_row++;
+	cur_col++;
 
-	if ( cur_row % 100 == 0 ) {
-	    printf("    loaded %d profiles of data\n", cur_row);
+	if ( cur_col % 100 == 0 ) {
+	    printf("    loaded %d profiles of data\n", cur_col);
 	}
     }
 
@@ -581,9 +632,9 @@ void fgDEM::fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
 // Initialize output mesh structure
 void fgDEM::outputmesh_init( float output_data[DEM_SIZE_1][DEM_SIZE_1] ) {
     int i, j;
-
-    for ( i = 0; i < DEM_SIZE_1; i++ ) {
-	for ( j = 0; j < DEM_SIZE_1; j++ ) {
+    
+    for ( j = 0; j < DEM_SIZE_1; j++ ) {
+	for ( i = 0; i < DEM_SIZE_1; i++ ) {
 	    output_data[i][j] = -9999.0;
 	}
     }
@@ -613,6 +664,9 @@ void fgDEM::outputmesh_output_nodes( float output_data[DEM_SIZE_1][DEM_SIZE_1],
 {
     struct stat stat_buf;
     char base_path[256], dir[256], file[256];
+#ifdef WIN32
+    char tmp_path[256];
+#endif
     char command[256];
     FILE *fd;
     long int index;
@@ -637,8 +691,30 @@ void fgDEM::outputmesh_output_nodes( float output_data[DEM_SIZE_1][DEM_SIZE_1],
     result = stat(dir, &stat_buf);
     if ( result != 0 ) {
 	printf("Stat error need to create directory\n");
+
+#ifndef WIN32
+
 	sprintf(command, "mkdir -p %s\n", dir);
 	system(command);
+
+#else // WIN32
+
+	// Cygwin crashes when trying to output to node file
+	// explicitly making directory structure seems OK on Win95
+
+	extract_path (base_path, tmp_path);
+
+	sprintf (dir, "%s/Scenery", fg_root);
+	if (my_mkdir (dir)) { exit (-1); }
+
+	sprintf (dir, "%s/Scenery/%s", fg_root, tmp_path);
+	if (my_mkdir (dir)) { exit (-1); }
+
+	sprintf (dir, "%s/Scenery/%s", fg_root, base_path);
+	if (my_mkdir (dir)) { exit (-1); }
+
+#endif // WIN32
+
     } else {
 	// assume directory exists
     }
@@ -687,6 +763,11 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.3  1998/04/06 21:09:41  curt
+// Additional win32 support.
+// Fixed a bad bug in dem file parsing that was causing the output to be
+// flipped about x = y.
+//
 // Revision 1.2  1998/03/23 20:35:41  curt
 // Updated to use FG_EPSILON
 //
diff --git a/DemRaw2ascii/rawdem.c b/DemRaw2ascii/rawdem.c
index 88727d73d..ae6679f09 100644
--- a/DemRaw2ascii/rawdem.c
+++ b/DemRaw2ascii/rawdem.c
@@ -416,7 +416,7 @@ void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path ) {
                  * row/col are reversed here.  raw->strip is backwards
                  * for convenience.  I am converting to [x,y] now. */
 		raw->center[col-xstart][row] = raw->strip[row][col];
-	
+
 		if ( raw->strip[row][col] < min) {
 		    min = raw->strip[row][col];
 		}
@@ -440,9 +440,14 @@ void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path ) {
 
 
 /* $Log$
-/* Revision 1.3  1998/03/03 13:10:29  curt
-/* Close to a working version.
+/* Revision 1.4  1998/04/06 21:09:43  curt
+/* Additional win32 support.
+/* Fixed a bad bug in dem file parsing that was causing the output to be
+/* flipped about x = y.
 /*
+ * Revision 1.3  1998/03/03 13:10:29  curt
+ * Close to a working version.
+ *
  * Revision 1.2  1998/03/03 02:04:01  curt
  * Starting DEM Ascii format output routine.
  *
diff --git a/FixNode/Makefile b/FixNode/Makefile
index b259c623d..d5a138928 100644
--- a/FixNode/Makefile
+++ b/FixNode/Makefile
@@ -37,7 +37,7 @@ include $(FG_ROOT_SRC)/commondefs
 # Rule for TARGET
 #---------------------------------------------------------------------------
 
-$(TARGET): $(OBJECTS)
+$(TARGET): $(OBJECTS) $(FG_ROOT_LIB)/stamp_libs
 	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
 
 
@@ -46,6 +46,11 @@ include $(COMMONRULES)
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/06 21:09:44  curt
+# Additional win32 support.
+# Fixed a bad bug in dem file parsing that was causing the output to be
+# flipped about x = y.
+#
 # Revision 1.3  1998/03/19 02:50:19  curt
 # Updated to support -lDEM class.
 #
diff --git a/FixNode/main.c b/FixNode/main.c
index e903df613..b43c1d174 100644
--- a/FixNode/main.c
+++ b/FixNode/main.c
@@ -1,5 +1,5 @@
-// triload.c -- read in a .node file and fix the z values of the interpolated 
-//              points
+// main.c -- read in a .node file and fix the z values of the interpolated 
+//           points
 //
 // Written by Curtis Olson, started November 1997.
 //
@@ -103,6 +103,11 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.6  1998/04/06 21:09:44  curt
+// Additional win32 support.
+// Fixed a bad bug in dem file parsing that was causing the output to be
+// flipped about x = y.
+//
 // Revision 1.5  1998/03/19 02:50:20  curt
 // Updated to support -lDEM class.
 //
diff --git a/Tools/Makefile b/Tools/Makefile
index 370d4ef55..8c1a7750b 100644
--- a/Tools/Makefile
+++ b/Tools/Makefile
@@ -63,15 +63,17 @@ source-tar: clean
 	(cd ..; \
 	tar cvzf demtools-$(FG_VERSION).tar.gz Tools/Makefile Tools/README \
 	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
-        Tools/Dem2node Tools/DemRaw2Ascii Tools/FixNode Tools/FixObj \
-	Tools/SplitTris Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
+        Tools/DEM Tools/gpc2.01 Tools/Dem2node Tools/DemRaw2Ascii \
+	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
+	Tools/Tri2obj Tools/Triangle)
 
 source-zip: clean
 	(cd ..; \
 	zip -r demtools-$(FG_VERSION).zip Tools/Makefile Tools/README \
 	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
-        Tools/Dem2node Tools/DemRaw2Ascii Tools/FixNode Tools/FixObj \
-	Tools/SplitTris Tools/Stripe_u Tools/Tri2obj Tools/Triangle)
+        Tools/DEM Tools/gpc2.01 Tools/Dem2node Tools/DemRaw2Ascii \
+	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
+	Tools/Tri2obj Tools/Triangle)
 
 bin-tar: all
 	echo "need to fix this"
@@ -91,6 +93,11 @@ bin-zip:
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.14  1998/04/06 21:09:37  curt
+# Additional win32 support.
+# Fixed a bad bug in dem file parsing that was causing the output to be
+# flipped about x = y.
+#
 # Revision 1.13  1998/03/19 02:52:51  curt
 # Updated to reflect some minor tool reorganization and the creation of class
 # to handle DEM processing needs.
diff --git a/Tools/Todo b/Tools/Todo
index 96d0bd539..d056dfc03 100644
--- a/Tools/Todo
+++ b/Tools/Todo
@@ -2,6 +2,10 @@
 | Done
 --------------------------------------------------------------------------
 
+4/6/98 -   fix 30 arcsec dem file processing
+
+4/6/98 -   incorporate autoconf/automake build system
+
 1/10/98 -  Split areas into smaller tiles
 
 1/14/98 -  Don't create shared corners or edges if one already exists.
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index a9c0ba05e..d82b9b5ce 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -91,6 +91,21 @@ while ( $dem_file = shift(@ARGV) ) {
 exit(0);
 
 
+# fix command to work with windoze, replaces first "/" with "\\"
+sub fix_command {
+    my($in) = @_;
+
+    $system = `uname -s`;
+    chop($system);
+
+    if ( $system =~ m/CYGWIN32/ ) { 
+	$in =~ s/\//\\\\/;
+    }
+
+    return($in);
+}
+
+
 # return the file name root (ending at last ".")
 sub file_root {
     my($file) = @_;
@@ -110,11 +125,11 @@ sub file_root {
 
 sub demfit {
     if ( $dem_file =~ m/.gz$/ ) {
-	$command = "gzip -dc $dem_file | ./Dem2node/dem2node $ENV{FG_ROOT} - $error";
+	$command = "gzip -dc $dem_file | Dem2node/dem2node $ENV{FG_ROOT} - $error";
     } else {
-	$command = "./Dem2node/dem2node $ENV{FG_ROOT} $dem_file $error";
+	$command = "Dem2node/dem2node $ENV{FG_ROOT} $dem_file $error";
     }
-
+    $command = fix_command($command);
     print "Running '$command'\n";
 
     open(OUT, "$command |");
@@ -141,7 +156,8 @@ sub triangle_1 {
 	print $file;
 	chop($file);
 	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
-	    $command = "./Triangle/triangle -q $subdir/$file";
+	    $command = "Triangle/triangle -q $subdir/$file";
+	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -164,10 +180,11 @@ sub triangle_1 {
 
 sub fixnode {
     if ( $dem_file =~ m/.gz$/ ) {
-	$command = "gzip -dc $dem_file | ./FixNode/fixnode - $subdir";
+	$command = "gzip -dc $dem_file | FixNode/fixnode - $subdir";
     } else {
-	$command = "./FixNode/fixnode $dem_file $subdir";
+	$command = "FixNode/fixnode $dem_file $subdir";
     }
+    $command = fix_command($command);
     print "Running '$command'\n";
     open(OUT, "$command |");
     while ( <OUT> ) {
@@ -199,7 +216,8 @@ sub splittris {
 	if ( $file =~ m/\.1\.node$/ ) {
 	    $file =~ s/\.node$//;  # strip off the ".node"
 	
-	    $command = "./SplitTris/splittris $subdir/$file";
+	    $command = "SplitTris/splittris $subdir/$file";
+	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -226,7 +244,8 @@ sub assemtris {
 	if ( $file =~ m/\.1\.body$/ ) {
 	    $file =~ s/\.body$//;  # strip off the ".body"
 	
-	    $command = "./AssemTris/assemtris $subdir/$file";
+	    $command = "AssemTris/assemtris $subdir/$file";
+	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -248,7 +267,8 @@ sub triangle_2 {
 	print $file;
 	chop($file);
 	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
-	    $command = "./Triangle/triangle $subdir/$file";
+	    $command = "Triangle/triangle $subdir/$file";
+	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -280,7 +300,8 @@ sub tri2obj {
 	if ( $file =~ m/\.1\.node$/ ) {
 	    $file =~ s/\.node$//;  # strip off the ".node"
 	    
-	    $command = "./Tri2obj/tri2obj $subdir/$file";
+	    $command = "Tri2obj/tri2obj $subdir/$file";
+	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -310,7 +331,8 @@ sub strips {
     foreach $file ( @FILES ) {
 	chop($file);
 	if ( $file =~ m/\.1\.obj$/ ) {
-	    $command = "./Stripe_u/strips $subdir/$file";
+	    $command = "Stripe_u/strips $subdir/$file";
+	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -348,7 +370,8 @@ sub fixobj {
 	    $newfile = $file;
 	    $newfile =~ s/\.2\.obj$/.obj/;
 	    
-	    $command = "./FixObj/fixobj $subdir/$file $subdir/$newfile";
+	    $command = "FixObj/fixobj $subdir/$file $subdir/$newfile";
+	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -364,6 +387,11 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.14  1998/04/06 21:09:38  curt
+# Additional win32 support.
+# Fixed a bad bug in dem file parsing that was causing the output to be
+# flipped about x = y.
+#
 # Revision 1.13  1998/03/19 02:52:52  curt
 # Updated to reflect some minor tool reorganization and the creation of class
 # to handle DEM processing needs.

From 079b3ad13d7387fd160c25e854c23072cd0d45ec Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 8 Apr 1998 22:54:56 +0000
Subject: [PATCH 052/283] Adopted Gnu automake/autoconf system.

---
 AssemTris/{Makefile => Makefile.am} |  25 +-
 AssemTris/Makefile.in               | 360 ++++++++++++++++++++++++++++
 AssemTris/assemtris.c               |  15 +-
 DEM/Makefile                        |  45 ----
 DEM/Makefile.am                     |   8 +
 DEM/Makefile.in                     | 335 ++++++++++++++++++++++++++
 DEM/{dem.c => dem.cxx}              |   7 +-
 DEM/{dem.h => dem.hxx}              |   5 +-
 DEM/{leastsqs.c => leastsqs.cxx}    |   9 +-
 DEM/{leastsqs.h => leastsqs.hxx}    |   7 +-
 10 files changed, 741 insertions(+), 75 deletions(-)
 rename AssemTris/{Makefile => Makefile.am} (73%)
 create mode 100644 AssemTris/Makefile.in
 delete mode 100644 DEM/Makefile
 create mode 100644 DEM/Makefile.am
 create mode 100644 DEM/Makefile.in
 rename DEM/{dem.c => dem.cxx} (99%)
 rename DEM/{dem.h => dem.hxx} (96%)
 rename DEM/{leastsqs.c => leastsqs.cxx} (93%)
 rename DEM/{leastsqs.h => leastsqs.hxx} (90%)

diff --git a/AssemTris/Makefile b/AssemTris/Makefile.am
similarity index 73%
rename from AssemTris/Makefile
rename to AssemTris/Makefile.am
index 842396e04..aed518219 100644
--- a/AssemTris/Makefile
+++ b/AssemTris/Makefile.am
@@ -3,7 +3,7 @@
 #
 # Written by Curtis Olson, started January 1998.
 #
-# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -24,28 +24,21 @@
 #---------------------------------------------------------------------------
 
 
-TARGET = assemtris
+bin_PROGRAMS = assemtris
 
-CFILES = assemtris.c
-LDLIBS = -lMath -lScenery -lm
+assemtris_SOURCES = assemtris.c assemtris.h
 
+assemtris_LDADD = \
+	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
 
-include $(FG_ROOT_SRC)/commondefs
-
-
-#---------------------------------------------------------------------------
-# Rule for TARGET
-#---------------------------------------------------------------------------
-
-$(TARGET): $(OBJECTS)
-	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
-
-
-include $(COMMONRULES)
+INCLUDES += -I../../Simulator
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.1  1998/04/08 22:54:57  curt
+# Adopted Gnu automake/autoconf system.
+#
 # Revision 1.2  1998/01/21 02:55:46  curt
 # Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
 #
diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
new file mode 100644
index 000000000..1bcc681b3
--- /dev/null
+++ b/AssemTris/Makefile.in
@@ -0,0 +1,360 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = assemtris
+
+assemtris_SOURCES = assemtris.c assemtris.h
+
+assemtris_LDADD = \
+	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+assemtris_OBJECTS =  assemtris.o
+assemtris_DEPENDENCIES =  \
+$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+assemtris_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/assemtris.P
+SOURCES = $(assemtris_SOURCES)
+OBJECTS = $(assemtris_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/AssemTris/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+assemtris: $(assemtris_OBJECTS) $(assemtris_DEPENDENCIES)
+	@rm -f assemtris
+	$(LINK) $(assemtris_LDFLAGS) $(assemtris_OBJECTS) $(assemtris_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/AssemTris
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/AssemTris/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+INCLUDES += -I../../Simulator
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/08 22:54:57  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.2  1998/01/21 02:55:46  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1998/01/15 02:45:25  curt
+# Initial revision.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index ab53c1a1c..835dc756e 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -33,10 +33,10 @@
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
-#include <Math/fg_geodesy.h>
-#include <Math/mat3.h>
-#include <Math/polar.h>
-#include <Scenery/bucketutils.h>
+// #include <Math/fg_geodesy.h>
+// #include <Math/mat3.h>
+// #include <Math/polar.h>
+#include <Scenery/Bucket/bucketutils.h>
 
 
 int nodecount = 0;
@@ -454,9 +454,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.5  1998/03/03 16:00:52  curt
-/* More c++ compile tweaks.
+/* Revision 1.6  1998/04/08 22:54:58  curt
+/* Adopted Gnu automake/autoconf system.
 /*
+ * Revision 1.5  1998/03/03 16:00:52  curt
+ * More c++ compile tweaks.
+ *
  * Revision 1.4  1998/01/31 00:41:23  curt
  * Made a few changes converting floats to doubles.
  *
diff --git a/DEM/Makefile b/DEM/Makefile
deleted file mode 100644
index fe04f0e9b..000000000
--- a/DEM/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started March 1998.
-#
-# Copyright (C) 1997  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-ARLIBRARY = libDEM.a
-TARGETS = $(ARLIBRARY)
-
-CFILES =  dem.c leastsqs.c
-CXXFILES = 
-
-LDIRT = $(FG_ROOT_LIB)/$(ARLIBRARY)
-
-include $(FG_ROOT_SRC)/commondefs
-
-include $(COMMONRULES)
-
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.1  1998/03/19 02:54:46  curt
-# Reorganized into a class lib called fgDEM.
-#
-
diff --git a/DEM/Makefile.am b/DEM/Makefile.am
new file mode 100644
index 000000000..d24cc6b35
--- /dev/null
+++ b/DEM/Makefile.am
@@ -0,0 +1,8 @@
+libdir  = ${exec_prefix}/lib
+
+lib_LTLIBRARIES = libDEM.la
+
+libDEM_la_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
+
+INCLUDES += -I../../Simulator
+
diff --git a/DEM/Makefile.in b/DEM/Makefile.in
new file mode 100644
index 000000000..81e385ab9
--- /dev/null
+++ b/DEM/Makefile.in
@@ -0,0 +1,335 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+libdir  = ${exec_prefix}/lib
+
+lib_LTLIBRARIES = libDEM.la
+
+libDEM_la_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(lib_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libDEM_la_LDFLAGS = 
+libDEM_la_LIBADD = 
+libDEM_la_OBJECTS =  dem.lo leastsqs.lo
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/dem.P .deps/leastsqs.P
+CXXMKDEP = $(CXX) -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+SOURCES = $(libDEM_la_SOURCES)
+OBJECTS = $(libDEM_la_OBJECTS)
+
+all: Makefile $(LTLIBRARIES)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .cxx .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/DEM/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-libLTLIBRARIES:
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+
+distclean-libLTLIBRARIES:
+
+maintainer-clean-libLTLIBRARIES:
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(libdir)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "$(LIBTOOL)  --mode=install $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  $(LIBTOOL)  --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libDEM.la: $(libDEM_la_OBJECTS) $(libDEM_la_DEPENDENCIES)
+	$(CXXLINK) -rpath $(libdir) $(libDEM_la_LDFLAGS) $(libDEM_la_OBJECTS) $(libDEM_la_LIBADD) $(LIBS)
+.cxx.o:
+	$(CXXCOMPILE) -c $<
+.cxx.lo:
+	$(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/DEM
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/DEM/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+
+%.o: %.cxx
+	@echo '$(CXXCOMPILE) -c $<'; \
+	$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.cxx
+	@echo '$(LTCXXCOMPILE) -c $<'; \
+	$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-libLTLIBRARIES
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-libLTLIBRARIES
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(libdir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-libLTLIBRARIES mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-libLTLIBRARIES distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-libLTLIBRARIES \
+		maintainer-clean-compile maintainer-clean-libtool \
+		maintainer-clean-tags maintainer-clean-depend \
+		maintainer-clean-generic distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \
+clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \
+uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \
+distclean-compile clean-compile maintainer-clean-compile \
+mostlyclean-libtool distclean-libtool clean-libtool \
+maintainer-clean-libtool tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info dvi \
+installcheck install-exec install-data install uninstall all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+INCLUDES += -I../../Simulator
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/DEM/dem.c b/DEM/dem.cxx
similarity index 99%
rename from DEM/dem.c
rename to DEM/dem.cxx
index 0dc3aa5e8..77a7c5c81 100644
--- a/DEM/dem.c
+++ b/DEM/dem.cxx
@@ -32,8 +32,8 @@
 #include <sys/stat.h> // stat()
 #include <unistd.h>   // stat()
 
-#include "dem.h"
-#include "leastsqs.h"
+#include "dem.hxx"
+#include "leastsqs.hxx"
 
 #include <Include/fg_constants.h>
 
@@ -763,6 +763,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.1  1998/04/08 22:57:22  curt
+// Adopted Gnu automake/autoconf system.
+//
 // Revision 1.3  1998/04/06 21:09:41  curt
 // Additional win32 support.
 // Fixed a bad bug in dem file parsing that was causing the output to be
diff --git a/DEM/dem.h b/DEM/dem.hxx
similarity index 96%
rename from DEM/dem.h
rename to DEM/dem.hxx
index 64f04e4b4..a3b5f215c 100644
--- a/DEM/dem.h
+++ b/DEM/dem.hxx
@@ -30,7 +30,7 @@
 
 #include <stdio.h>
 
-#include <Scenery/bucketutils.h>
+#include <Scenery/Bucket/bucketutils.h>
 
 
 #define DEM_SIZE 1200
@@ -130,6 +130,9 @@ public:
 
 
 // $Log$
+// Revision 1.1  1998/04/08 22:57:23  curt
+// Adopted Gnu automake/autoconf system.
+//
 // Revision 1.2  1998/03/23 20:35:42  curt
 // Updated to use FG_EPSILON
 //
diff --git a/DEM/leastsqs.c b/DEM/leastsqs.cxx
similarity index 93%
rename from DEM/leastsqs.c
rename to DEM/leastsqs.cxx
index 1eebb0330..7414fa628 100644
--- a/DEM/leastsqs.c
+++ b/DEM/leastsqs.cxx
@@ -25,7 +25,7 @@
 
 #include <stdio.h>
 
-#include "leastsqs.h"
+#include "leastsqs.hxx"
 
 
 /* 
@@ -112,9 +112,12 @@ double least_squares_max_error(double *x, double *y, int n, double m, double b){
 
 
 /* $Log$
-/* Revision 1.1  1998/03/19 02:54:47  curt
-/* Reorganized into a class lib called fgDEM.
+/* Revision 1.1  1998/04/08 22:57:24  curt
+/* Adopted Gnu automake/autoconf system.
 /*
+ * Revision 1.1  1998/03/19 02:54:47  curt
+ * Reorganized into a class lib called fgDEM.
+ *
  * Revision 1.1  1997/10/13 17:02:35  curt
  * Initial revision.
  *
diff --git a/DEM/leastsqs.h b/DEM/leastsqs.hxx
similarity index 90%
rename from DEM/leastsqs.h
rename to DEM/leastsqs.hxx
index c2b8866ef..8e0d3dec8 100644
--- a/DEM/leastsqs.h
+++ b/DEM/leastsqs.hxx
@@ -58,9 +58,12 @@ double least_squares_max_error(double *x, double *y, int n, double m, double b);
 
 
 /* $Log$
-/* Revision 1.1  1998/03/19 02:54:48  curt
-/* Reorganized into a class lib called fgDEM.
+/* Revision 1.1  1998/04/08 22:57:25  curt
+/* Adopted Gnu automake/autoconf system.
 /*
+ * Revision 1.1  1998/03/19 02:54:48  curt
+ * Reorganized into a class lib called fgDEM.
+ *
  * Revision 1.1  1997/10/13 17:02:35  curt
  * Initial revision.
  *

From 104ea85dfe7844e95c16db05a64cbc19427cdbaa Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 8 Apr 1998 23:05:54 +0000
Subject: [PATCH 053/283] Adopted Gnu automake/autoconf system.

---
 FixNode/{Makefile => Makefile.am}  |  29 +--
 FixNode/Makefile.in                | 388 +++++++++++++++++++++++++++++
 FixNode/{fixnode.c => fixnode.cxx} |  11 +-
 FixNode/{fixnode.h => fixnode.hxx} |   8 +-
 FixNode/{main.c => main.cxx}       |  10 +-
 FixNode/triload.c                  |  78 ------
 FixNode/triload.cxx                |  79 ++++++
 FixNode/triload.h                  |  62 -----
 FixNode/triload.hxx                |  63 +++++
 9 files changed, 563 insertions(+), 165 deletions(-)
 rename FixNode/{Makefile => Makefile.am} (75%)
 create mode 100644 FixNode/Makefile.in
 rename FixNode/{fixnode.c => fixnode.cxx} (92%)
 rename FixNode/{fixnode.h => fixnode.hxx} (92%)
 rename FixNode/{main.c => main.cxx} (95%)
 delete mode 100644 FixNode/triload.c
 create mode 100644 FixNode/triload.cxx
 delete mode 100644 FixNode/triload.h
 create mode 100644 FixNode/triload.hxx

diff --git a/FixNode/Makefile b/FixNode/Makefile.am
similarity index 75%
rename from FixNode/Makefile
rename to FixNode/Makefile.am
index d5a138928..4445f8400 100644
--- a/FixNode/Makefile
+++ b/FixNode/Makefile.am
@@ -3,7 +3,7 @@
 #
 # Written by Curtis Olson, started October 1997.
 #
-# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+# Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -24,28 +24,25 @@
 #---------------------------------------------------------------------------
 
 
-TARGET = fixnode
+bin_PROGRAMS = fixnode
 
-CFILES = fixnode.c main.c triload.c
-LDLIBS = -lDEM -lScenery -lm
+fixnode_SOURCES = \
+	fixnode.cxx fixnode.hxx \
+	main.cxx \
+	triload.cxx triload.hxx
 
+fixnode_LDADD = \
+	$(top_builddir)/Tools/DEM/libDEM.la \
+        $(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
 
-include $(FG_ROOT_SRC)/commondefs
-
-
-#---------------------------------------------------------------------------
-# Rule for TARGET
-#---------------------------------------------------------------------------
-
-$(TARGET): $(OBJECTS) $(FG_ROOT_LIB)/stamp_libs
-	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
-
-
-include $(COMMONRULES)
+INCLUDES += -I.. -I../../Simulator
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.1  1998/04/08 23:05:54  curt
+# Adopted Gnu automake/autoconf system.
+#
 # Revision 1.4  1998/04/06 21:09:44  curt
 # Additional win32 support.
 # Fixed a bad bug in dem file parsing that was causing the output to be
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
new file mode 100644
index 000000000..091d3835a
--- /dev/null
+++ b/FixNode/Makefile.in
@@ -0,0 +1,388 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started October 1997.
+#
+# Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = fixnode
+
+fixnode_SOURCES = \
+	fixnode.cxx fixnode.hxx \
+	main.cxx \
+	triload.cxx triload.hxx
+
+fixnode_LDADD = \
+	$(top_builddir)/Tools/DEM/libDEM.la \
+        $(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+fixnode_OBJECTS =  fixnode.o main.o triload.o
+fixnode_DEPENDENCIES =  $(top_builddir)/Tools/DEM/libDEM.la \
+$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+fixnode_LDFLAGS = 
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/fixnode.P .deps/main.P .deps/triload.P
+CXXMKDEP = $(CXX) -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+SOURCES = $(fixnode_SOURCES)
+OBJECTS = $(fixnode_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .cxx .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/FixNode/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+fixnode: $(fixnode_OBJECTS) $(fixnode_DEPENDENCIES)
+	@rm -f fixnode
+	$(CXXLINK) $(fixnode_LDFLAGS) $(fixnode_OBJECTS) $(fixnode_LDADD) $(LIBS)
+.cxx.o:
+	$(CXXCOMPILE) -c $<
+.cxx.lo:
+	$(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/FixNode
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/FixNode/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+
+%.o: %.cxx
+	@echo '$(CXXCOMPILE) -c $<'; \
+	$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.cxx
+	@echo '$(LTCXXCOMPILE) -c $<'; \
+	$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+INCLUDES += -I.. -I../../Simulator
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/08 23:05:55  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.4  1998/04/06 21:09:44  curt
+# Additional win32 support.
+# Fixed a bad bug in dem file parsing that was causing the output to be
+# flipped about x = y.
+#
+# Revision 1.3  1998/03/19 02:50:19  curt
+# Updated to support -lDEM class.
+#
+# Revision 1.2  1998/01/21 02:55:50  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1997/11/27 00:17:32  curt
+# Initial revision.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/FixNode/fixnode.c b/FixNode/fixnode.cxx
similarity index 92%
rename from FixNode/fixnode.c
rename to FixNode/fixnode.cxx
index 5276348d0..8acf685a7 100644
--- a/FixNode/fixnode.c
+++ b/FixNode/fixnode.cxx
@@ -28,8 +28,8 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "fixnode.h"
-#include "triload.h"
+#include "fixnode.hxx"
+#include "triload.hxx"
 
 
 /* load the node information */
@@ -80,9 +80,12 @@ void fixnodes( char *filename, fgDEM dem,
 
 
 /* $Log$
-/* Revision 1.5  1998/03/19 02:50:19  curt
-/* Updated to support -lDEM class.
+/* Revision 1.1  1998/04/08 23:05:56  curt
+/* Adopted Gnu automake/autoconf system.
 /*
+ * Revision 1.5  1998/03/19 02:50:19  curt
+ * Updated to support -lDEM class.
+ *
  * Revision 1.4  1998/03/03 16:00:57  curt
  * More c++ compile tweaks.
  *
diff --git a/FixNode/fixnode.h b/FixNode/fixnode.hxx
similarity index 92%
rename from FixNode/fixnode.h
rename to FixNode/fixnode.hxx
index ec83d7b7d..370e136a5 100644
--- a/FixNode/fixnode.h
+++ b/FixNode/fixnode.hxx
@@ -31,8 +31,9 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "triload.h"
-#include "../DEM/dem.h"
+#include <DEM/dem.hxx>
+
+#include "triload.hxx"
 
 
 // load the node information
@@ -45,6 +46,9 @@ void fixnodes( char *basename, fgDEM dem,
 
 
 // $Log$
+// Revision 1.1  1998/04/08 23:05:56  curt
+// Adopted Gnu automake/autoconf system.
+//
 // Revision 1.4  1998/03/19 02:50:19  curt
 // Updated to support -lDEM class.
 //
diff --git a/FixNode/main.c b/FixNode/main.cxx
similarity index 95%
rename from FixNode/main.c
rename to FixNode/main.cxx
index b43c1d174..840ee23ae 100644
--- a/FixNode/main.c
+++ b/FixNode/main.cxx
@@ -29,9 +29,10 @@
 #include <string.h>
 #include <sys/types.h>
 
-#include "../DEM/dem.h"
-#include "fixnode.h"
-#include "triload.h"
+#include <DEM/dem.hxx>
+
+#include "fixnode.hxx"
+#include "triload.hxx"
 
 
 // Storage for the original DEM data which is used to interpolate z values
@@ -103,6 +104,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.1  1998/04/08 23:05:57  curt
+// Adopted Gnu automake/autoconf system.
+//
 // Revision 1.6  1998/04/06 21:09:44  curt
 // Additional win32 support.
 // Fixed a bad bug in dem file parsing that was causing the output to be
diff --git a/FixNode/triload.c b/FixNode/triload.c
deleted file mode 100644
index 72d9427f9..000000000
--- a/FixNode/triload.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* triload.c -- read in a .node file and fix the z values of the interpolated 
- *              points
- *
- * Written by Curtis Olson, started November 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
-
-
-#include <stdio.h>
-#include <string.h>
-
-#include "triload.h"
-
-
-int nodecount;
-
-
-/* load the node information */
-void triload(char *filename, double nodes[MAX_NODES][3]) {
-    FILE *node;
-    int dim, junk1, junk2;
-    int i;
-
-    printf("Loading node file:  %s ...\n", filename);
-    if ( (node = fopen(filename, "r")) == NULL ) {
-	printf("Cannot open file '%s'\n", filename);
-	exit(-1);
-    }
-
-    fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
-
-    if ( nodecount > MAX_NODES - 1 ) {
-	printf("Error, too many nodes, need to increase array size\n");
-	exit(-1);
-    } else {
-	printf("    Expecting %d nodes\n", nodecount);
-    }
-
-    for ( i = 1; i <= nodecount; i++ ) {
-	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
-	       &nodes[i][0], &nodes[i][1], &nodes[i][2], &junk2);
-	/* printf("%d %.2f %.2f %.2f\n", junk1, nodes[i][0], nodes[i][1], 
-	   nodes[i][2]); */
-    }
-
-    fclose(node);
-}
-
-
-/* $Log$
-/* Revision 1.3  1998/03/03 16:00:59  curt
-/* More c++ compile tweaks.
-/*
- * Revision 1.2  1998/01/09 23:03:09  curt
- * Restructured to split 1deg x 1deg dem's into 64 subsections.
- *
- * Revision 1.1  1997/11/27 00:17:35  curt
- * Initial revision.
- *
- */
diff --git a/FixNode/triload.cxx b/FixNode/triload.cxx
new file mode 100644
index 000000000..3986780ac
--- /dev/null
+++ b/FixNode/triload.cxx
@@ -0,0 +1,79 @@
+// triload.cxx -- read in a .node file and fix the z values of the 
+//                interpolated points
+//
+// Written by Curtis Olson, started November 1997.
+//
+// Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "triload.hxx"
+
+
+int nodecount;
+
+
+// load the node information
+void triload(char *filename, double nodes[MAX_NODES][3]) {
+    FILE *node;
+    int dim, junk1, junk2;
+    int i;
+
+    printf("Loading node file:  %s ...\n", filename);
+    if ( (node = fopen(filename, "r")) == NULL ) {
+	printf("Cannot open file '%s'\n", filename);
+	exit(-1);
+    }
+
+    fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
+
+    if ( nodecount > MAX_NODES - 1 ) {
+	printf("Error, too many nodes, need to increase array size\n");
+	exit(-1);
+    } else {
+	printf("    Expecting %d nodes\n", nodecount);
+    }
+
+    for ( i = 1; i <= nodecount; i++ ) {
+	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
+	       &nodes[i][0], &nodes[i][1], &nodes[i][2], &junk2);
+	// printf("%d %.2f %.2f %.2f\n", junk1, nodes[i][0], nodes[i][1], 
+	// nodes[i][2]);
+    }
+
+    fclose(node);
+}
+
+
+// $Log$
+// Revision 1.1  1998/04/08 23:05:58  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.3  1998/03/03 16:00:59  curt
+// More c++ compile tweaks.
+//
+// Revision 1.2  1998/01/09 23:03:09  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.1  1997/11/27 00:17:35  curt
+// Initial revision.
+//
diff --git a/FixNode/triload.h b/FixNode/triload.h
deleted file mode 100644
index c145e11cf..000000000
--- a/FixNode/triload.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* triload.h -- read in a .node file and fix the z values of the interpolated 
- *              points
- *
- * Written by Curtis Olson, started November 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
-
-
-#ifndef _TRILOAD_H
-#define _TRILOAD_H
-
-
-#include <stdio.h>
-#include <string.h>
-
-
-#define MAX_NODES 200000
-#define MAX_TRIS  400000
-
-
-extern int nodecount, tricount;
-
-
-/* Initialize a new mesh structure */
-void triload(char *basename, double nodes[MAX_NODES][3]);
-
-
-#endif // _TRILOAD_H
-
-
-/* $Log$
-/* Revision 1.4  1998/03/19 02:50:20  curt
-/* Updated to support -lDEM class.
-/*
- * Revision 1.3  1998/03/03 16:00:59  curt
- * More c++ compile tweaks.
- *
- * Revision 1.2  1998/01/09 23:03:09  curt
- * Restructured to split 1deg x 1deg dem's into 64 subsections.
- *
- * Revision 1.1  1997/11/27 00:17:35  curt
- * Initial revision.
- *
- */
diff --git a/FixNode/triload.hxx b/FixNode/triload.hxx
new file mode 100644
index 000000000..de40c1b31
--- /dev/null
+++ b/FixNode/triload.hxx
@@ -0,0 +1,63 @@
+// triload.hxx -- read in a .node file and fix the z values of the 
+//                interpolated points
+//
+// Written by Curtis Olson, started November 1997.
+//
+// Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _TRILOAD_H
+#define _TRILOAD_H
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+#define MAX_NODES 200000
+#define MAX_TRIS  400000
+
+
+extern int nodecount, tricount;
+
+
+// Initialize a new mesh structure
+void triload(char *basename, double nodes[MAX_NODES][3]);
+
+
+#endif // _TRILOAD_H
+
+
+// $Log$
+// Revision 1.1  1998/04/08 23:06:00  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.4  1998/03/19 02:50:20  curt
+// Updated to support -lDEM class.
+//
+// Revision 1.3  1998/03/03 16:00:59  curt
+// More c++ compile tweaks.
+//
+// Revision 1.2  1998/01/09 23:03:09  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.1  1997/11/27 00:17:35  curt
+// Initial revision.
+//

From 784960bd8f123ffc78b49d950b0fd18cdfd7dcd5 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 8 Apr 1998 23:19:34 +0000
Subject: [PATCH 054/283] Adopted Gnu automake/autoconf system.

---
 FixObj/MAT3vec.c                    | 149 +++++
 FixObj/{Makefile => Makefile.am}    |  24 +-
 FixObj/Makefile.in                  | 358 ++++++++++++
 FixObj/mat3.h                       | 147 +++++
 FixObj/obj.c                        |   9 +-
 SplitTris/MAT3vec.c                 | 149 +++++
 SplitTris/{Makefile => Makefile.am} |  30 +-
 SplitTris/Makefile.in               | 369 +++++++++++++
 SplitTris/fg_geodesy.c              | 230 ++++++++
 SplitTris/fg_geodesy.h              | 163 ++++++
 SplitTris/mat3.h                    | 147 +++++
 SplitTris/polar.c                   | 124 +++++
 SplitTris/polar.h                   |  93 ++++
 SplitTris/splittris.c               |  15 +-
 Tools/Makefile                      | 141 -----
 Tools/Makefile.am                   |  14 +
 Tools/Makefile.in                   | 297 ++++++++++
 Tools/make.inc                      | 128 -----
 Tools/process-dem.pl                |  11 +-
 Tri2obj/MAT3vec.c                   | 149 +++++
 Tri2obj/Makefile                    |  69 ---
 Tri2obj/Makefile.am                 |  53 ++
 Tri2obj/Makefile.in                 | 366 +++++++++++++
 Tri2obj/fg_geodesy.c                | 230 ++++++++
 Tri2obj/fg_geodesy.h                | 163 ++++++
 Tri2obj/mat3.h                      | 147 +++++
 Tri2obj/polar.c                     | 124 +++++
 Tri2obj/polar.h                     |  93 ++++
 Tri2obj/tri2obj.c                   |  16 +-
 Triangle/Makefile                   | 111 ----
 Triangle/Makefile.am                |  18 +
 Triangle/Makefile.in                | 333 ++++++++++++
 Triangle/depend                     |  27 -
 Triangle/triangle.doc               | 817 ++++++++++++++++++++++++++++
 34 files changed, 4787 insertions(+), 527 deletions(-)
 create mode 100644 FixObj/MAT3vec.c
 rename FixObj/{Makefile => Makefile.am} (73%)
 create mode 100644 FixObj/Makefile.in
 create mode 100644 FixObj/mat3.h
 create mode 100644 SplitTris/MAT3vec.c
 rename SplitTris/{Makefile => Makefile.am} (74%)
 create mode 100644 SplitTris/Makefile.in
 create mode 100644 SplitTris/fg_geodesy.c
 create mode 100644 SplitTris/fg_geodesy.h
 create mode 100644 SplitTris/mat3.h
 create mode 100644 SplitTris/polar.c
 create mode 100644 SplitTris/polar.h
 delete mode 100644 Tools/Makefile
 create mode 100644 Tools/Makefile.am
 create mode 100644 Tools/Makefile.in
 delete mode 100644 Tools/make.inc
 create mode 100644 Tri2obj/MAT3vec.c
 delete mode 100644 Tri2obj/Makefile
 create mode 100644 Tri2obj/Makefile.am
 create mode 100644 Tri2obj/Makefile.in
 create mode 100644 Tri2obj/fg_geodesy.c
 create mode 100644 Tri2obj/fg_geodesy.h
 create mode 100644 Tri2obj/mat3.h
 create mode 100644 Tri2obj/polar.c
 create mode 100644 Tri2obj/polar.h
 delete mode 100644 Triangle/Makefile
 create mode 100644 Triangle/Makefile.am
 create mode 100644 Triangle/Makefile.in
 delete mode 100644 Triangle/depend
 create mode 100644 Triangle/triangle.doc

diff --git a/FixObj/MAT3vec.c b/FixObj/MAT3vec.c
new file mode 100644
index 000000000..24f2939af
--- /dev/null
+++ b/FixObj/MAT3vec.c
@@ -0,0 +1,149 @@
+/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
+
+/* --------------------------------------------------------------------------
+ * This file contains routines that operate on matrices and vectors, or
+ * vectors and vectors.
+ * -------------------------------------------------------------------------*/
+
+/* #include "sphigslocal.h" */
+
+/* --------------------------  Static Routines	---------------------------- */
+
+/* -------------------------  Internal Routines  --------------------------- */
+
+/* --------------------------  Public Routines	---------------------------- */
+
+/*
+ * Multiplies a vector by a matrix, setting the result vector.
+ * It assumes all homogeneous coordinates are 1.
+ * The two vectors involved may be the same.
+ */
+
+#include <Math/mat3.h>
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+
+void
+MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
+{
+   MAT3vec		tempvec;
+   register double	*temp = tempvec;
+
+   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
+		vec[2] * mat[2][0] +	      mat[3][0];
+   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
+		vec[2] * mat[2][1] +	      mat[3][1];
+   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
+		vec[2] * mat[2][2] +	      mat[3][2];
+
+   MAT3_COPY_VEC(result_vec, temp);
+}
+
+/*
+ * Multiplies a vector of size 4 by a matrix, setting the result vector.
+ * The fourth element of the vector is the homogeneous coordinate, which
+ * may or may not be 1.  If the "normalize" parameter is TRUE, then the
+ * result vector will be normalized so that the homogeneous coordinate is 1.
+ * The two vectors involved may be the same.
+ * This returns zero if the vector was to be normalized, but couldn't be.
+ */
+
+int
+MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
+{
+   MAT3hvec             tempvec;
+   double		norm_fac;
+   register double	*temp = tempvec;
+   register int 	ret = TRUE;
+
+   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
+		vec[2] * mat[2][0] + vec[3] * mat[3][0];
+   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
+		vec[2] * mat[2][1] + vec[3] * mat[3][1];
+   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
+		vec[2] * mat[2][2] + vec[3] * mat[3][2];
+   temp[3] =	vec[0] * mat[0][3] + vec[1] * mat[1][3] +
+		vec[2] * mat[2][3] + vec[3] * mat[3][3];
+
+   /* Normalize if asked for, possible, and necessary */
+   if (normalize) {
+      if (MAT3_IS_ZERO(temp[3])) {
+#ifndef THINK_C
+	 fprintf (stderr,
+		  "Can't normalize vector: homogeneous coordinate is 0");
+#endif
+	 ret = FALSE;
+      }
+      else {
+	 norm_fac = 1.0 / temp[3];
+	 MAT3_SCALE_VEC(result_vec, temp, norm_fac);
+	 result_vec[3] = 1.0;
+      }
+   }
+   else MAT3_COPY_HVEC(result_vec, temp);
+
+   return(ret);
+}
+
+/*
+ * Sets the first vector to be the cross-product of the last two vectors.
+ */
+
+void
+MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
+{
+   MAT3vec		tempvec;
+   register double	*temp = tempvec;
+
+   temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
+   temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
+   temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
+
+   MAT3_COPY_VEC(result_vec, temp);
+}
+
+/*
+ * Finds a vector perpendicular to vec and stores it in result_vec.
+ * Method:  take any vector (we use <0,1,0>) and subtract the
+ * portion of it pointing in the vec direction.  This doesn't
+ * work if vec IS <0,1,0> or is very near it.  So if this is
+ * the case, use <0,0,1> instead.
+ * If "is_unit" is TRUE, the given vector is assumed to be unit length.
+ */
+
+#define SELECT	.7071	/* selection constant (roughly .5*sqrt(2) */
+
+void
+MAT3perp_vec(double *result_vec, double *vec, int is_unit)
+{
+   MAT3vec	norm;
+   double	dot;
+
+   MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
+
+   MAT3_COPY_VEC(norm, vec);
+
+   if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
+
+   /* See if vector is too close to <0,1,0>.  If so, use <0,0,1> */
+   if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
+      result_vec[1] = 0.0;
+      result_vec[2] = 1.0;
+      dot = MAT3_DOT_PRODUCT(norm, result_vec);
+   }
+
+   /* Subtract off non-perpendicular part */
+   result_vec[0] -= dot * norm[0];
+   result_vec[1] -= dot * norm[1];
+   result_vec[2] -= dot * norm[2];
+
+   /* Make result unit length */
+   MAT3_NORMALIZE_VEC(result_vec, dot);
+}
diff --git a/FixObj/Makefile b/FixObj/Makefile.am
similarity index 73%
rename from FixObj/Makefile
rename to FixObj/Makefile.am
index 64a5bc17d..3e33b5d82 100644
--- a/FixObj/Makefile
+++ b/FixObj/Makefile.am
@@ -3,7 +3,7 @@
 #
 # Written by Curtis Olson, started October 1997.
 #
-# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+# Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -24,28 +24,20 @@
 #---------------------------------------------------------------------------
 
 
-TARGET = fixobj
+bin_PROGRAMS = fixobj
 
-CFILES = main.c obj.c
-LDLIBS = -lMath -lm
+fixobj_SOURCES = main.c mat3.h obj.c obj.h MAT3vec.c
 
+fixobj_LDADD =
 
-include $(FG_ROOT_SRC)/commondefs
-
-
-#---------------------------------------------------------------------------
-# Rule for TARGET
-#---------------------------------------------------------------------------
-
-$(TARGET): $(OBJECTS)
-	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
-
-
-include $(COMMONRULES)
+INCLUDES += -I../../Simulator
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.1  1998/04/08 23:19:35  curt
+# Adopted Gnu automake/autoconf system.
+#
 # Revision 1.2  1998/01/21 02:55:53  curt
 # Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
 #
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
new file mode 100644
index 000000000..6c2a3683e
--- /dev/null
+++ b/FixObj/Makefile.in
@@ -0,0 +1,358 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started October 1997.
+#
+# Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = fixobj
+
+fixobj_SOURCES = main.c mat3.h obj.c obj.h MAT3vec.c
+
+fixobj_LDADD =
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+fixobj_OBJECTS =  main.o obj.o MAT3vec.o
+fixobj_DEPENDENCIES = 
+fixobj_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/MAT3vec.P .deps/main.P .deps/obj.P
+SOURCES = $(fixobj_SOURCES)
+OBJECTS = $(fixobj_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/FixObj/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+fixobj: $(fixobj_OBJECTS) $(fixobj_DEPENDENCIES)
+	@rm -f fixobj
+	$(LINK) $(fixobj_LDFLAGS) $(fixobj_OBJECTS) $(fixobj_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/FixObj
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/FixObj/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+INCLUDES += -I../../Simulator
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/08 23:19:36  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.2  1998/01/21 02:55:53  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1997/12/08 19:28:54  curt
+# Initial revision.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/FixObj/mat3.h b/FixObj/mat3.h
new file mode 100644
index 000000000..58c4b9e07
--- /dev/null
+++ b/FixObj/mat3.h
@@ -0,0 +1,147 @@
+/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
+
+/* -------------------------------------------------------------------------
+		       Public MAT3 include file
+   ------------------------------------------------------------------------- */
+
+#ifndef MAT3_HAS_BEEN_INCLUDED
+#define MAT3_HAS_BEEN_INCLUDED
+
+/* -----------------------------  Constants  ------------------------------ */
+
+/*
+ * Make sure the math library .h file is included, in case it wasn't.
+ */
+
+#ifndef HUGE
+#include <math.h>
+#endif
+#include <stdio.h>
+
+
+#define MAT3_DET0	-1			/* Indicates singular mat */
+#define MAT3_EPSILON	1e-12			/* Close enough to zero   */
+#define MAT3_PI 	3.141592653589793	/* Pi			  */
+
+/* ------------------------------  Types  --------------------------------- */
+
+typedef double MAT3mat[4][4];		/* 4x4 matrix			 */
+typedef double MAT3vec[3];		/* Vector			 */
+typedef double MAT3hvec[4];             /* Vector with homogeneous coord */
+
+/* ------------------------------  Macros  -------------------------------- */
+
+/* Tests if a number is within EPSILON of zero */
+#define MAT3_IS_ZERO(N) 	((N) < MAT3_EPSILON && (N) > -MAT3_EPSILON)
+
+/* Sets a vector to the three given values */
+#define MAT3_SET_VEC(V,X,Y,Z)	((V)[0]=(X), (V)[1]=(Y), (V)[2]=(Z))
+
+/* Tests a vector for all components close to zero */
+#define MAT3_IS_ZERO_VEC(V)	(MAT3_IS_ZERO((V)[0]) && \
+				 MAT3_IS_ZERO((V)[1]) && \
+				 MAT3_IS_ZERO((V)[2]))
+
+/* Dot product of two vectors */
+#define MAT3_DOT_PRODUCT(V1,V2) \
+			((V1)[0]*(V2)[0] + (V1)[1]*(V2)[1] + (V1)[2]*(V2)[2])
+
+/* Copy one vector to other */
+#define MAT3_COPY_VEC(TO,FROM)	((TO)[0] = (FROM)[0], \
+				 (TO)[1] = (FROM)[1], \
+				 (TO)[2] = (FROM)[2])
+
+/* Normalize vector to unit length, using TEMP as temporary variable.
+ * TEMP will be zero if vector has zero length */
+#define MAT3_NORMALIZE_VEC(V,TEMP) \
+	if ((TEMP = sqrt(MAT3_DOT_PRODUCT(V,V))) > MAT3_EPSILON) { \
+	   TEMP = 1.0 / TEMP; \
+	   MAT3_SCALE_VEC(V,V,TEMP); \
+	} else TEMP = 0.0
+
+/* Scale vector by given factor, storing result vector in RESULT_V */
+#define MAT3_SCALE_VEC(RESULT_V,V,SCALE) \
+	MAT3_SET_VEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), (V)[2]*(SCALE))
+
+/* Adds vectors V1 and V2, storing result in RESULT_V */
+#define MAT3_ADD_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
+			       (V1)[2]+(V2)[2])
+
+/* Subtracts vector V2 from V1, storing result in RESULT_V */
+#define MAT3_SUB_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
+			       (V1)[2]-(V2)[2])
+
+/* Multiplies vectors V1 and V2, storing result in RESULT_V */
+#define MAT3_MULT_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
+			       (V1)[2]*(V2)[2])
+
+/* Sets RESULT_V to the linear combination of V1 and V2, scaled by
+ * SCALE1 and SCALE2, respectively */
+#define MAT3_LINEAR_COMB(RESULT_V,SCALE1,V1,SCALE2,V2) \
+	MAT3_SET_VEC(RESULT_V,	(SCALE1)*(V1)[0] + (SCALE2)*(V2)[0], \
+				(SCALE1)*(V1)[1] + (SCALE2)*(V2)[1], \
+				(SCALE1)*(V1)[2] + (SCALE2)*(V2)[2])
+
+/* Several of the vector macros are useful for homogeneous-coord vectors */
+#define MAT3_SET_HVEC(V,X,Y,Z,W) ((V)[0]=(X), (V)[1]=(Y), \
+				  (V)[2]=(Z), (V)[3]=(W))
+
+#define MAT3_COPY_HVEC(TO,FROM) ((TO)[0] = (FROM)[0], \
+				 (TO)[1] = (FROM)[1], \
+				 (TO)[2] = (FROM)[2], \
+				 (TO)[3] = (FROM)[3])
+
+#define MAT3_SCALE_HVEC(RESULT_V,V,SCALE) \
+	MAT3_SET_HVEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), \
+				(V)[2]*(SCALE), (V)[3]*(SCALE))
+
+#define MAT3_ADD_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
+				(V1)[2]+(V2)[2], (V1)[3]+(V2)[3])
+
+#define MAT3_SUB_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
+				(V1)[2]-(V2)[2], (V1)[3]-(V2)[3])
+
+#define MAT3_MULT_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
+				(V1)[2]*(V2)[2], (V1)[3]*(V2)[3])
+
+/* ------------------------------  Entries  ------------------------------- */
+
+
+/* In MAT3geom.c */
+void 		MAT3direction_matrix (MAT3mat result_mat, MAT3mat mat);
+int 		MAT3normal_matrix (MAT3mat result_mat, MAT3mat mat);
+void		MAT3rotate (MAT3mat result_mat, MAT3vec axis, double angle_in_radians);
+void		MAT3translate (MAT3mat result_mat, MAT3vec trans);
+void		MAT3scale (MAT3mat result_mat, MAT3vec scale);
+void		MAT3shear(MAT3mat result_mat, double xshear, double yshear);
+
+/* In MAT3mat.c */
+void		MAT3identity(MAT3mat);
+void		MAT3zero(MAT3mat);
+void		MAT3copy (MAT3mat to, MAT3mat from);
+void		MAT3mult (MAT3mat result, MAT3mat, MAT3mat);
+void		MAT3transpose (MAT3mat result, MAT3mat);
+int			MAT3invert (MAT3mat result, MAT3mat);
+void		MAT3print (MAT3mat, FILE *fp);
+void		MAT3print_formatted (MAT3mat, FILE *fp, 
+			 	     char *title, char *head, char *format, char *tail);
+extern int		MAT3equal( void );
+extern double		MAT3trace( void );
+extern int		MAT3power( void );
+extern int		MAT3column_reduce( void );
+extern int		MAT3kernel_basis( void );
+
+/* In MAT3vec.c */
+void		MAT3mult_vec(MAT3vec result_vec, MAT3vec vec, MAT3mat mat);
+int		MAT3mult_hvec (MAT3hvec result_vec, MAT3hvec vec, MAT3mat mat, int normalize);
+void		MAT3cross_product(MAT3vec result,MAT3vec,MAT3vec);
+void		MAT3perp_vec(MAT3vec result_vec, MAT3vec vec, int is_unit);
+
+#endif /* MAT3_HAS_BEEN_INCLUDED */
+
diff --git a/FixObj/obj.c b/FixObj/obj.c
index 8d2deceb8..9fec7f7e6 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -29,7 +29,7 @@
 
 #include "obj.h"
 
-#include "../../Src/Math/mat3.h"
+#include "mat3.h"
 
 
 /* what do ya' know, here's some global variables */
@@ -291,9 +291,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.7  1998/03/19 02:51:41  curt
-/* Added special case handling to compensate for bugs in our beloved tri striper
+/* Revision 1.8  1998/04/08 23:19:37  curt
+/* Adopted Gnu automake/autoconf system.
 /*
+ * Revision 1.7  1998/03/19 02:51:41  curt
+ * Added special case handling to compensate for bugs in our beloved tri striper
+ *
  * Revision 1.6  1998/03/03 15:36:12  curt
  * Tweaks for compiling with g++
  *
diff --git a/SplitTris/MAT3vec.c b/SplitTris/MAT3vec.c
new file mode 100644
index 000000000..24f2939af
--- /dev/null
+++ b/SplitTris/MAT3vec.c
@@ -0,0 +1,149 @@
+/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
+
+/* --------------------------------------------------------------------------
+ * This file contains routines that operate on matrices and vectors, or
+ * vectors and vectors.
+ * -------------------------------------------------------------------------*/
+
+/* #include "sphigslocal.h" */
+
+/* --------------------------  Static Routines	---------------------------- */
+
+/* -------------------------  Internal Routines  --------------------------- */
+
+/* --------------------------  Public Routines	---------------------------- */
+
+/*
+ * Multiplies a vector by a matrix, setting the result vector.
+ * It assumes all homogeneous coordinates are 1.
+ * The two vectors involved may be the same.
+ */
+
+#include <Math/mat3.h>
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+
+void
+MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
+{
+   MAT3vec		tempvec;
+   register double	*temp = tempvec;
+
+   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
+		vec[2] * mat[2][0] +	      mat[3][0];
+   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
+		vec[2] * mat[2][1] +	      mat[3][1];
+   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
+		vec[2] * mat[2][2] +	      mat[3][2];
+
+   MAT3_COPY_VEC(result_vec, temp);
+}
+
+/*
+ * Multiplies a vector of size 4 by a matrix, setting the result vector.
+ * The fourth element of the vector is the homogeneous coordinate, which
+ * may or may not be 1.  If the "normalize" parameter is TRUE, then the
+ * result vector will be normalized so that the homogeneous coordinate is 1.
+ * The two vectors involved may be the same.
+ * This returns zero if the vector was to be normalized, but couldn't be.
+ */
+
+int
+MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
+{
+   MAT3hvec             tempvec;
+   double		norm_fac;
+   register double	*temp = tempvec;
+   register int 	ret = TRUE;
+
+   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
+		vec[2] * mat[2][0] + vec[3] * mat[3][0];
+   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
+		vec[2] * mat[2][1] + vec[3] * mat[3][1];
+   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
+		vec[2] * mat[2][2] + vec[3] * mat[3][2];
+   temp[3] =	vec[0] * mat[0][3] + vec[1] * mat[1][3] +
+		vec[2] * mat[2][3] + vec[3] * mat[3][3];
+
+   /* Normalize if asked for, possible, and necessary */
+   if (normalize) {
+      if (MAT3_IS_ZERO(temp[3])) {
+#ifndef THINK_C
+	 fprintf (stderr,
+		  "Can't normalize vector: homogeneous coordinate is 0");
+#endif
+	 ret = FALSE;
+      }
+      else {
+	 norm_fac = 1.0 / temp[3];
+	 MAT3_SCALE_VEC(result_vec, temp, norm_fac);
+	 result_vec[3] = 1.0;
+      }
+   }
+   else MAT3_COPY_HVEC(result_vec, temp);
+
+   return(ret);
+}
+
+/*
+ * Sets the first vector to be the cross-product of the last two vectors.
+ */
+
+void
+MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
+{
+   MAT3vec		tempvec;
+   register double	*temp = tempvec;
+
+   temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
+   temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
+   temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
+
+   MAT3_COPY_VEC(result_vec, temp);
+}
+
+/*
+ * Finds a vector perpendicular to vec and stores it in result_vec.
+ * Method:  take any vector (we use <0,1,0>) and subtract the
+ * portion of it pointing in the vec direction.  This doesn't
+ * work if vec IS <0,1,0> or is very near it.  So if this is
+ * the case, use <0,0,1> instead.
+ * If "is_unit" is TRUE, the given vector is assumed to be unit length.
+ */
+
+#define SELECT	.7071	/* selection constant (roughly .5*sqrt(2) */
+
+void
+MAT3perp_vec(double *result_vec, double *vec, int is_unit)
+{
+   MAT3vec	norm;
+   double	dot;
+
+   MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
+
+   MAT3_COPY_VEC(norm, vec);
+
+   if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
+
+   /* See if vector is too close to <0,1,0>.  If so, use <0,0,1> */
+   if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
+      result_vec[1] = 0.0;
+      result_vec[2] = 1.0;
+      dot = MAT3_DOT_PRODUCT(norm, result_vec);
+   }
+
+   /* Subtract off non-perpendicular part */
+   result_vec[0] -= dot * norm[0];
+   result_vec[1] -= dot * norm[1];
+   result_vec[2] -= dot * norm[2];
+
+   /* Make result unit length */
+   MAT3_NORMALIZE_VEC(result_vec, dot);
+}
diff --git a/SplitTris/Makefile b/SplitTris/Makefile.am
similarity index 74%
rename from SplitTris/Makefile
rename to SplitTris/Makefile.am
index 27313a425..ca10cc328 100644
--- a/SplitTris/Makefile
+++ b/SplitTris/Makefile.am
@@ -3,7 +3,7 @@
 #
 # Written by Curtis Olson, started January 1998.
 #
-# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -24,28 +24,26 @@
 #---------------------------------------------------------------------------
 
 
-TARGET = splittris
+bin_PROGRAMS = splittris
 
-CFILES = splittris.c
-LDLIBS = -lMath -lScenery -lm
+splittris_SOURCES = \
+	MAT3vec.c \
+	fg_geodesy.c fg_geodesy.h \
+	mat3.h \
+	polar.c polar.h \
+	splittris.c splittris.h
 
+splittris_LDADD = \
+	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
 
-include $(FG_ROOT_SRC)/commondefs
-
-
-#---------------------------------------------------------------------------
-# Rule for TARGET
-#---------------------------------------------------------------------------
-
-$(TARGET): $(OBJECTS)
-	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
-
-
-include $(COMMONRULES)
+INCLUDES += -I../../Simulator
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.1  1998/04/08 23:21:10  curt
+# Adopted Gnu automake/autoconf system.
+#
 # Revision 1.3  1998/01/21 02:55:55  curt
 # Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
 #
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
new file mode 100644
index 000000000..7eab72fae
--- /dev/null
+++ b/SplitTris/Makefile.in
@@ -0,0 +1,369 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = splittris
+
+splittris_SOURCES = \
+	MAT3vec.c \
+	fg_geodesy.c fg_geodesy.h \
+	mat3.h \
+	polar.c polar.h \
+	splittris.c splittris.h
+
+splittris_LDADD = \
+	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+splittris_OBJECTS =  MAT3vec.o fg_geodesy.o polar.o splittris.o
+splittris_DEPENDENCIES =  \
+$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+splittris_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/MAT3vec.P .deps/fg_geodesy.P .deps/polar.P \
+.deps/splittris.P
+SOURCES = $(splittris_SOURCES)
+OBJECTS = $(splittris_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/SplitTris/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+splittris: $(splittris_OBJECTS) $(splittris_DEPENDENCIES)
+	@rm -f splittris
+	$(LINK) $(splittris_LDFLAGS) $(splittris_OBJECTS) $(splittris_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/SplitTris
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/SplitTris/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+INCLUDES += -I../../Simulator
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/08 23:21:11  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.3  1998/01/21 02:55:55  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.2  1998/01/14 15:54:42  curt
+# Initial revision completed.
+#
+# Revision 1.1  1998/01/14 02:11:30  curt
+# Initial revision.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/SplitTris/fg_geodesy.c b/SplitTris/fg_geodesy.c
new file mode 100644
index 000000000..773010375
--- /dev/null
+++ b/SplitTris/fg_geodesy.c
@@ -0,0 +1,230 @@
+/**************************************************************************
+ * fg_geodesy.c -- routines to convert between geodetic and geocentric 
+ *                 coordinate systems.
+ *
+ * Copied and adapted directly from LaRCsim/ls_geodesy.c
+ *
+ * See below for the complete original LaRCsim comments.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#include <math.h>
+
+#include <Include/fg_constants.h>
+
+#include "fg_geodesy.h"
+
+
+/* ONE_SECOND is pi/180/60/60, or about 100 feet at earths' equator */
+#define ONE_SECOND 4.848136811E-6
+
+
+/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
+ *     INPUTS:	
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *         radius	C.G. radius to earth center, ft
+ *
+ *     OUTPUTS:
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *         sea_level_r	radius from earth center to sea level at
+ *                      local vertical (surface normal) of C.G.
+ */
+
+void fgGeocToGeod( double lat_geoc, double radius, double
+		   *lat_geod, double *alt, double *sea_level_r )
+{
+    double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
+    double sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
+
+    if( ( (FG_PI_2 - lat_geoc) < ONE_SECOND )     /* near North pole */
+	|| ( (FG_PI_2 + lat_geoc) < ONE_SECOND ) )   /* near South pole */
+    {
+	*lat_geod = lat_geoc;
+	*sea_level_r = EQUATORIAL_RADIUS_KM*E;
+	*alt = radius - *sea_level_r;
+    } else {
+	t_lat = tan(lat_geoc);
+	x_alpha = E*EQUATORIAL_RADIUS_KM/sqrt(t_lat*t_lat + E*E);
+	mu_alpha = atan2(sqrt(RESQ_KM - x_alpha*x_alpha),E*x_alpha);
+	if (lat_geoc < 0) mu_alpha = - mu_alpha;
+	sin_mu_a = sin(mu_alpha);
+	delt_lambda = mu_alpha - lat_geoc;
+	r_alpha = x_alpha/cos(lat_geoc);
+	l_point = radius - r_alpha;
+	*alt = l_point*cos(delt_lambda);
+	denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
+	rho_alpha = EQUATORIAL_RADIUS_KM*(1-EPS)/
+	    (denom*denom*denom);
+	delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
+	*lat_geod = mu_alpha - delt_mu;
+	lambda_sl = atan( E*E * tan(*lat_geod) ); /* SL geoc. latitude */
+	sin_lambda_sl = sin( lambda_sl );
+	*sea_level_r = 
+	    sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
+    }
+}
+
+
+/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
+ *     INPUTS:	
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *
+ *     OUTPUTS:
+ *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
+ *                      get true distance from earth center.
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *
+ */
+
+void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
+		      double *lat_geoc )
+{
+    double lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
+    
+    lambda_sl = atan( E*E * tan(lat_geod) ); /* sea level geocentric latitude */
+    sin_lambda_sl = sin( lambda_sl );
+    cos_lambda_sl = cos( lambda_sl );
+    sin_mu = sin(lat_geod);	/* Geodetic (map makers') latitude */
+    cos_mu = cos(lat_geod);
+    *sl_radius = 
+	sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
+    py = *sl_radius*sin_lambda_sl + alt*sin_mu;
+    px = *sl_radius*cos_lambda_sl + alt*cos_mu;
+    *lat_geoc = atan2( py, px );
+}
+
+
+/***************************************************************************
+
+	TITLE:	ls_geodesy
+	
+----------------------------------------------------------------------------
+
+	FUNCTION:	Converts geocentric coordinates to geodetic positions
+
+----------------------------------------------------------------------------
+
+	MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	DESIGNED BY:	E. B. Jackson
+	
+	CODED BY:	E. B. Jackson
+	
+	MAINTAINED BY:	E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	MODIFICATION HISTORY:
+	
+	DATE	PURPOSE						BY
+	
+	930208	Modified to avoid singularity near polar region.	EBJ
+	930602	Moved backwards calcs here from ls_step.		EBJ
+	931214	Changed erroneous Latitude and Altitude variables to 
+		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
+	940111	Changed header files from old ls_eom.h style to ls_types, 
+		and ls_constants.  Also replaced old DATA type with new
+		SCALAR type.						EBJ
+
+	CURRENT RCS HEADER:
+
+$Header$
+$Log$
+Revision 1.1  1998/04/08 23:21:11  curt
+Adopted Gnu automake/autoconf system.
+
+Revision 1.4  1998/01/27 00:47:59  curt
+Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+system and commandline/config file processing code.
+
+Revision 1.3  1998/01/19 19:27:12  curt
+Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+This should simplify things tremendously.
+
+Revision 1.2  1997/12/15 23:54:54  curt
+Add xgl wrappers for debugging.
+Generate terrain normals on the fly.
+
+Revision 1.1  1997/07/31 23:13:14  curt
+Initial revision.
+
+Revision 1.1  1997/05/29 00:09:56  curt
+Initial Flight Gear revision.
+
+ * Revision 1.5  1994/01/11  18:47:05  bjax
+ * Changed include files to use types and constants, not ls_eom.h
+ * Also changed DATA type to SCALAR type.
+ *
+ * Revision 1.4  1993/12/14  21:06:47  bjax
+ * Removed global variable references Altitude and Latitude.   EBJ
+ *
+ * Revision 1.3  1993/06/02  15:03:40  bjax
+ * Made new subroutine for calculating geodetic to geocentric; changed name
+ * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
+ *
+
+----------------------------------------------------------------------------
+
+	REFERENCES:
+
+		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
+			Control and Simulation", Wiley and Sons, 1992.
+			ISBN 0-471-61397-5		      
+
+
+----------------------------------------------------------------------------
+
+	CALLED BY:	ls_aux
+
+----------------------------------------------------------------------------
+
+	CALLS TO:
+
+----------------------------------------------------------------------------
+
+	INPUTS:	
+		lat_geoc	Geocentric latitude, radians, + = North
+		radius		C.G. radius to earth center, ft
+
+----------------------------------------------------------------------------
+
+	OUTPUTS:
+		lat_geod	Geodetic latitude, radians, + = North
+		alt		C.G. altitude above mean sea level, ft
+		sea_level_r	radius from earth center to sea level at
+				local vertical (surface normal) of C.G.
+
+--------------------------------------------------------------------------*/
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:21:11  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.4  1998/01/27 00:47:59  curt
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+ * system and commandline/config file processing code.
+ *
+ * Revision 1.3  1998/01/19 19:27:12  curt
+ * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+ * This should simplify things tremendously.
+ *
+ * Revision 1.2  1997/12/15 23:54:54  curt
+ * Add xgl wrappers for debugging.
+ * Generate terrain normals on the fly.
+ *
+ * Revision 1.1  1997/07/31 23:13:14  curt
+ * Initial revision.
+ *
+ */
diff --git a/SplitTris/fg_geodesy.h b/SplitTris/fg_geodesy.h
new file mode 100644
index 000000000..a40b22df4
--- /dev/null
+++ b/SplitTris/fg_geodesy.h
@@ -0,0 +1,163 @@
+/**************************************************************************
+ * fg_geodesy.h -- routines to convert between geodetic and geocentric 
+ *                 coordinate systems.
+ *
+ * Copied and adapted directly from LaRCsim/ls_geodesy.c
+ *
+ * See below for the complete original LaRCsim comments.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#ifndef _FG_GEODESY_H
+#define _FG_GEODESY_H
+
+
+/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
+ *     INPUTS:	
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *         radius	C.G. radius to earth center, ft
+ *
+ *     OUTPUTS:
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *         sea_level_r	radius from earth center to sea level at
+ *                      local vertical (surface normal) of C.G.
+ */
+
+void fgGeocToGeod( double lat_geoc, double radius, double
+		   *lat_geod, double *alt, double *sea_level_r );
+
+/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
+ *     INPUTS:	
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *
+ *     OUTPUTS:
+ *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
+ *                      get true distance from earth center.
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *
+ */
+
+void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
+		   double *lat_geoc );
+
+
+
+/***************************************************************************
+
+	TITLE:	ls_geodesy
+	
+----------------------------------------------------------------------------
+
+	FUNCTION:	Converts geocentric coordinates to geodetic positions
+
+----------------------------------------------------------------------------
+
+	MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	DESIGNED BY:	E. B. Jackson
+	
+	CODED BY:	E. B. Jackson
+	
+	MAINTAINED BY:	E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	MODIFICATION HISTORY:
+	
+	DATE	PURPOSE						BY
+	
+	930208	Modified to avoid singularity near polar region.	EBJ
+	930602	Moved backwards calcs here from ls_step.		EBJ
+	931214	Changed erroneous Latitude and Altitude variables to 
+		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
+	940111	Changed header files from old ls_eom.h style to ls_types, 
+		and ls_constants.  Also replaced old DATA type with new
+		SCALAR type.						EBJ
+
+	CURRENT RCS HEADER:
+
+$Header$
+$Log$
+Revision 1.1  1998/04/08 23:21:12  curt
+Adopted Gnu automake/autoconf system.
+
+Revision 1.2  1998/01/22 02:59:38  curt
+Changed #ifdef FILE_H to #ifdef _FILE_H
+
+Revision 1.1  1997/07/31 23:13:14  curt
+Initial revision.
+
+Revision 1.1  1997/05/29 00:09:56  curt
+Initial Flight Gear revision.
+
+ * Revision 1.5  1994/01/11  18:47:05  bjax
+ * Changed include files to use types and constants, not ls_eom.h
+ * Also changed DATA type to SCALAR type.
+ *
+ * Revision 1.4  1993/12/14  21:06:47  bjax
+ * Removed global variable references Altitude and Latitude.   EBJ
+ *
+ * Revision 1.3  1993/06/02  15:03:40  bjax
+ * Made new subroutine for calculating geodetic to geocentric; changed name
+ * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
+ *
+
+----------------------------------------------------------------------------
+
+	REFERENCES:
+
+		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
+			Control and Simulation", Wiley and Sons, 1992.
+			ISBN 0-471-61397-5		      
+
+
+----------------------------------------------------------------------------
+
+	CALLED BY:	ls_aux
+
+----------------------------------------------------------------------------
+
+	CALLS TO:
+
+----------------------------------------------------------------------------
+
+	INPUTS:	
+		lat_geoc	Geocentric latitude, radians, + = North
+		radius		C.G. radius to earth center, ft
+
+----------------------------------------------------------------------------
+
+	OUTPUTS:
+		lat_geod	Geodetic latitude, radians, + = North
+		alt		C.G. altitude above mean sea level, ft
+		sea_level_r	radius from earth center to sea level at
+				local vertical (surface normal) of C.G.
+
+--------------------------------------------------------------------------*/
+
+
+#endif /* _FG_GEODESY_H */
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:21:12  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.2  1998/01/22 02:59:38  curt
+ * Changed #ifdef FILE_H to #ifdef _FILE_H
+ *
+ * Revision 1.1  1997/07/31 23:13:14  curt
+ * Initial revision.
+ *
+ */
diff --git a/SplitTris/mat3.h b/SplitTris/mat3.h
new file mode 100644
index 000000000..58c4b9e07
--- /dev/null
+++ b/SplitTris/mat3.h
@@ -0,0 +1,147 @@
+/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
+
+/* -------------------------------------------------------------------------
+		       Public MAT3 include file
+   ------------------------------------------------------------------------- */
+
+#ifndef MAT3_HAS_BEEN_INCLUDED
+#define MAT3_HAS_BEEN_INCLUDED
+
+/* -----------------------------  Constants  ------------------------------ */
+
+/*
+ * Make sure the math library .h file is included, in case it wasn't.
+ */
+
+#ifndef HUGE
+#include <math.h>
+#endif
+#include <stdio.h>
+
+
+#define MAT3_DET0	-1			/* Indicates singular mat */
+#define MAT3_EPSILON	1e-12			/* Close enough to zero   */
+#define MAT3_PI 	3.141592653589793	/* Pi			  */
+
+/* ------------------------------  Types  --------------------------------- */
+
+typedef double MAT3mat[4][4];		/* 4x4 matrix			 */
+typedef double MAT3vec[3];		/* Vector			 */
+typedef double MAT3hvec[4];             /* Vector with homogeneous coord */
+
+/* ------------------------------  Macros  -------------------------------- */
+
+/* Tests if a number is within EPSILON of zero */
+#define MAT3_IS_ZERO(N) 	((N) < MAT3_EPSILON && (N) > -MAT3_EPSILON)
+
+/* Sets a vector to the three given values */
+#define MAT3_SET_VEC(V,X,Y,Z)	((V)[0]=(X), (V)[1]=(Y), (V)[2]=(Z))
+
+/* Tests a vector for all components close to zero */
+#define MAT3_IS_ZERO_VEC(V)	(MAT3_IS_ZERO((V)[0]) && \
+				 MAT3_IS_ZERO((V)[1]) && \
+				 MAT3_IS_ZERO((V)[2]))
+
+/* Dot product of two vectors */
+#define MAT3_DOT_PRODUCT(V1,V2) \
+			((V1)[0]*(V2)[0] + (V1)[1]*(V2)[1] + (V1)[2]*(V2)[2])
+
+/* Copy one vector to other */
+#define MAT3_COPY_VEC(TO,FROM)	((TO)[0] = (FROM)[0], \
+				 (TO)[1] = (FROM)[1], \
+				 (TO)[2] = (FROM)[2])
+
+/* Normalize vector to unit length, using TEMP as temporary variable.
+ * TEMP will be zero if vector has zero length */
+#define MAT3_NORMALIZE_VEC(V,TEMP) \
+	if ((TEMP = sqrt(MAT3_DOT_PRODUCT(V,V))) > MAT3_EPSILON) { \
+	   TEMP = 1.0 / TEMP; \
+	   MAT3_SCALE_VEC(V,V,TEMP); \
+	} else TEMP = 0.0
+
+/* Scale vector by given factor, storing result vector in RESULT_V */
+#define MAT3_SCALE_VEC(RESULT_V,V,SCALE) \
+	MAT3_SET_VEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), (V)[2]*(SCALE))
+
+/* Adds vectors V1 and V2, storing result in RESULT_V */
+#define MAT3_ADD_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
+			       (V1)[2]+(V2)[2])
+
+/* Subtracts vector V2 from V1, storing result in RESULT_V */
+#define MAT3_SUB_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
+			       (V1)[2]-(V2)[2])
+
+/* Multiplies vectors V1 and V2, storing result in RESULT_V */
+#define MAT3_MULT_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
+			       (V1)[2]*(V2)[2])
+
+/* Sets RESULT_V to the linear combination of V1 and V2, scaled by
+ * SCALE1 and SCALE2, respectively */
+#define MAT3_LINEAR_COMB(RESULT_V,SCALE1,V1,SCALE2,V2) \
+	MAT3_SET_VEC(RESULT_V,	(SCALE1)*(V1)[0] + (SCALE2)*(V2)[0], \
+				(SCALE1)*(V1)[1] + (SCALE2)*(V2)[1], \
+				(SCALE1)*(V1)[2] + (SCALE2)*(V2)[2])
+
+/* Several of the vector macros are useful for homogeneous-coord vectors */
+#define MAT3_SET_HVEC(V,X,Y,Z,W) ((V)[0]=(X), (V)[1]=(Y), \
+				  (V)[2]=(Z), (V)[3]=(W))
+
+#define MAT3_COPY_HVEC(TO,FROM) ((TO)[0] = (FROM)[0], \
+				 (TO)[1] = (FROM)[1], \
+				 (TO)[2] = (FROM)[2], \
+				 (TO)[3] = (FROM)[3])
+
+#define MAT3_SCALE_HVEC(RESULT_V,V,SCALE) \
+	MAT3_SET_HVEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), \
+				(V)[2]*(SCALE), (V)[3]*(SCALE))
+
+#define MAT3_ADD_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
+				(V1)[2]+(V2)[2], (V1)[3]+(V2)[3])
+
+#define MAT3_SUB_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
+				(V1)[2]-(V2)[2], (V1)[3]-(V2)[3])
+
+#define MAT3_MULT_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
+				(V1)[2]*(V2)[2], (V1)[3]*(V2)[3])
+
+/* ------------------------------  Entries  ------------------------------- */
+
+
+/* In MAT3geom.c */
+void 		MAT3direction_matrix (MAT3mat result_mat, MAT3mat mat);
+int 		MAT3normal_matrix (MAT3mat result_mat, MAT3mat mat);
+void		MAT3rotate (MAT3mat result_mat, MAT3vec axis, double angle_in_radians);
+void		MAT3translate (MAT3mat result_mat, MAT3vec trans);
+void		MAT3scale (MAT3mat result_mat, MAT3vec scale);
+void		MAT3shear(MAT3mat result_mat, double xshear, double yshear);
+
+/* In MAT3mat.c */
+void		MAT3identity(MAT3mat);
+void		MAT3zero(MAT3mat);
+void		MAT3copy (MAT3mat to, MAT3mat from);
+void		MAT3mult (MAT3mat result, MAT3mat, MAT3mat);
+void		MAT3transpose (MAT3mat result, MAT3mat);
+int			MAT3invert (MAT3mat result, MAT3mat);
+void		MAT3print (MAT3mat, FILE *fp);
+void		MAT3print_formatted (MAT3mat, FILE *fp, 
+			 	     char *title, char *head, char *format, char *tail);
+extern int		MAT3equal( void );
+extern double		MAT3trace( void );
+extern int		MAT3power( void );
+extern int		MAT3column_reduce( void );
+extern int		MAT3kernel_basis( void );
+
+/* In MAT3vec.c */
+void		MAT3mult_vec(MAT3vec result_vec, MAT3vec vec, MAT3mat mat);
+int		MAT3mult_hvec (MAT3hvec result_vec, MAT3hvec vec, MAT3mat mat, int normalize);
+void		MAT3cross_product(MAT3vec result,MAT3vec,MAT3vec);
+void		MAT3perp_vec(MAT3vec result_vec, MAT3vec vec, int is_unit);
+
+#endif /* MAT3_HAS_BEEN_INCLUDED */
+
diff --git a/SplitTris/polar.c b/SplitTris/polar.c
new file mode 100644
index 000000000..c304f183b
--- /dev/null
+++ b/SplitTris/polar.c
@@ -0,0 +1,124 @@
+/**************************************************************************
+ * polar.c -- routines to deal with polar math and transformations
+ *
+ * Written by Curtis Olson, started June 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#include <math.h>
+#include <stdio.h>
+
+#include <Math/polar.h>
+#include <Include/fg_constants.h>
+
+
+/* we can save these values between calls for efficiency */
+static double st, ct, sp, cp;
+
+
+/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
+ * must be specified in radians.  The FG convention is for distances
+ * to be specified in meters */
+struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius) {
+    struct fgCartesianPoint pnew;
+
+    pnew.x = cos(lon) * cos(lat) * radius;
+    pnew.y = sin(lon) * cos(lat) * radius;
+    pnew.z = sin(lat) * radius;
+
+    return(pnew);
+}
+
+
+/* Precalculate as much as possible so we can do a batch of transforms
+ * through the same angles, will rotates a cartesian point about the
+ * center of the earth by Theta (longitude axis) and Phi (latitude
+ * axis) */
+
+/* Here are the unoptimized transformation equations 
+
+   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
+	     sin(Phi) * z
+   y' = -sin(Theta) * x + cos(Theta) * y
+   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
+	     cos(Phi) * z;
+
+ */
+void fgRotateBatchInit(double Theta, double Phi) {
+    printf("Theta = %.3f, Phi = %.3f\n", Theta, Phi);
+
+    st = sin(Theta);
+    ct = cos(Theta);
+    sp = sin(-Phi);
+    cp = cos(-Phi);
+}
+
+/* Rotates a cartesian point about the center of the earth by Theta
+ * (longitude axis) and Phi (latitude axis) */
+struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p) {
+    struct fgCartesianPoint p1, p2;
+
+    /* printf("start = %.3f %.3f %.3f\n", p.x, p.y, p.z); */
+
+    /* rotate about the z axis */
+    p1.x = ct * p.x - st * p.y;
+    p1.y = st * p.x + ct * p.y;
+    p1.z = p.z;
+
+    /* printf("step 1 = %.3f %.3f %.3f\n", p1.x, p1.y, p1.z); */
+
+    /* rotate new point about y axis */
+    p2.x = cp * p1.x + sp * p1.z;
+    p2.y = p1.y;
+    p2.z = cp * p1.z - sp * p1.x;
+
+    /* printf("cp = %.5f, sp = %.5f\n", cp, sp); */
+    /* printf("(1) = %.5f, (2) = %.5f\n", cp * p1.z, sp * p1.x); */
+
+    /* printf("step 2 = %.3f %.3f %.3f\n", p2.x, p2.y, p2.z); */
+
+    return(p2);
+}
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:21:12  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.5  1998/01/27 00:48:00  curt
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+ * system and commandline/config file processing code.
+ *
+ * Revision 1.4  1998/01/19 19:27:12  curt
+ * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+ * This should simplify things tremendously.
+ *
+ * Revision 1.3  1997/12/15 23:54:54  curt
+ * Add xgl wrappers for debugging.
+ * Generate terrain normals on the fly.
+ *
+ * Revision 1.2  1997/07/31 22:52:27  curt
+ * Working on redoing internal coordinate systems & scenery transformations.
+ *
+ * Revision 1.1  1997/07/07 21:02:36  curt
+ * Initial revision.
+ * */
diff --git a/SplitTris/polar.h b/SplitTris/polar.h
new file mode 100644
index 000000000..2164d995a
--- /dev/null
+++ b/SplitTris/polar.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+ * polar.h -- routines to deal with polar math and transformations
+ *
+ * Written by Curtis Olson, started June 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#ifndef _POLAR_H
+#define _POLAR_H
+
+
+#include <Include/fg_types.h>
+
+
+/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
+ * must be specified in radians.  The FG convention is for distances
+ * to be specified in meters */
+struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius);
+
+
+/* Precalculate as much as possible so we can do a batch of transforms
+ * through the same angles, will rotates a cartesian point about the
+ * center of the earth by Theta (longitude axis) and Phi (latitude
+ * axis) */
+
+/* Here are the unoptimized transformation equations 
+
+   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
+	     sin(Phi) * z
+   y' = -sin(Theta) * x + cos(Theta) * y
+   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
+	     cos(Phi) * z;
+
+ */
+void fgRotateBatchInit(double Theta, double Phi);
+
+
+/* Rotates a cartesian point about the center of the earth by Theta
+ * (longitude axis) and Phi (latitude axis) */
+struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p);
+
+
+#endif /* _POLAR_H */
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:21:13  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.7  1998/01/27 00:48:00  curt
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+ * system and commandline/config file processing code.
+ *
+ * Revision 1.6  1998/01/22 02:59:39  curt
+ * Changed #ifdef FILE_H to #ifdef _FILE_H
+ *
+ * Revision 1.5  1998/01/19 19:27:13  curt
+ * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+ * This should simplify things tremendously.
+ *
+ * Revision 1.4  1997/12/15 23:54:55  curt
+ * Add xgl wrappers for debugging.
+ * Generate terrain normals on the fly.
+ *
+ * Revision 1.3  1997/07/31 22:52:28  curt
+ * Working on redoing internal coordinate systems & scenery transformations.
+ *
+ * Revision 1.2  1997/07/23 21:52:21  curt
+ * Put comments around the text after an #endif for increased portability.
+ *
+ * Revision 1.1  1997/07/07 21:02:37  curt
+ * Initial revision.
+ *
+ */
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index 36b8db356..38b87b227 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -36,11 +36,11 @@
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
-#include <Math/fg_geodesy.h>
-#include <Math/mat3.h>
-#include <Math/polar.h>
-#include <Scenery/bucketutils.h>
+#include <Scenery/Bucket/bucketutils.h>
 
+#include "fg_geodesy.h"
+#include "mat3.h"
+#include "polar.h"
 
 int nodecount, tricount;
 double xmin, xmax, ymin, ymax;
@@ -612,9 +612,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.6  1998/03/03 15:36:13  curt
-/* Tweaks for compiling with g++
+/* Revision 1.7  1998/04/08 23:21:13  curt
+/* Adopted Gnu automake/autoconf system.
 /*
+ * Revision 1.6  1998/03/03 15:36:13  curt
+ * Tweaks for compiling with g++
+ *
  * Revision 1.5  1998/03/03 03:37:04  curt
  * Cumulative tweaks.
  *
diff --git a/Tools/Makefile b/Tools/Makefile
deleted file mode 100644
index 8c1a7750b..000000000
--- a/Tools/Makefile
+++ /dev/null
@@ -1,141 +0,0 @@
-#---------------------------------------------------------------------------
-# Toplevel FGTools Makefile
-#
-# Written by Curtis Olson, started October 1997.
-#
-# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-include $(FG_ROOT_SRC)/commondefs
-
-
-LIBDIRS = DEM gpc2.01
-SUBDIRS = Areas AssemTris Dem2node DemRaw2Ascii FixNode FixObj \
-	SplitTris Stripe_u Tri2obj Triangle
-ORDEREDDIRS = $(LIBDIRS) $(SUBDIRS)
-
-
-all: 
-	for dir in $(ORDEREDDIRS); do \
-	    ( cd $$dir; $(MAKE) ) ; \
-	done
-
-depend:
-	for dir in $(ORDEREDDIRS); do \
-	    ( echo "Making depend in $$dir"; \
-	      cd $$dir; $(CC) $(CFLAGS) -M *.c > depend ) ; \
-	done
-
-Makefile-os2:
-	cat Makefile | perl mkmfos2.pl > Makefile.os2; \
-	for dir in $(ORDEREDDIRS); do \
-	    ( echo "Making Makefile.os2 in $$dir"; \
-	      cat $$dir/Makefile | perl mkmfos2.pl > $$dir/Makefile.os2; \
-	      cat $$dir/depend   | perl mkmfos2.pl > $$dir/depend.os2) ; \
-	done
-
-clean:
-	-rm -f *.os2 *~
-	for dir in $(ORDEREDDIRS); do \
-	    (cd $$dir; $(MAKE) clean) ; \
-	done
-
-
-source-tar: clean
-	(cd ..; \
-	tar cvzf demtools-$(FG_VERSION).tar.gz Tools/Makefile Tools/README \
-	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
-        Tools/DEM Tools/gpc2.01 Tools/Dem2node Tools/DemRaw2Ascii \
-	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
-	Tools/Tri2obj Tools/Triangle)
-
-source-zip: clean
-	(cd ..; \
-	zip -r demtools-$(FG_VERSION).zip Tools/Makefile Tools/README \
-	Tools/Todo Tools/make.inc Tools/process-dem.pl Tools/AssemTris \
-        Tools/DEM Tools/gpc2.01 Tools/Dem2node Tools/DemRaw2Ascii \
-	Tools/FixNode Tools/FixObj Tools/SplitTris Tools/Stripe_u \
-	Tools/Tri2obj Tools/Triangle)
-
-bin-tar: all
-	echo "need to fix this"
-#	cp GLUT/fg0 GLUT/runfg ..
-#	(cd ../..; \
-#	tar cvzf bin-$(FG_VERSION).tar.gz FlightGear/fgtop FlightGear/fg0 \
-#	FlightGear/runfg FlightGear/COPYING FlightGear/Docs FlightGear/Thanks)
-
-bin-zip: 
-	echo "need to fix this"
-#	cp GLUT/fg0.exe GLUT/runfg.bat GLUT/cygwin.dll ..
-#	(cd ../..; \
-#	zip -r bin-$(FG_VERSION).zip FlightGear/fgtop FlightGear/fg0.exe \
-#	FlightGear/runfg.bat FlightGear/cygwin.dll FlightGear/COPYING \
-#	FlightGear/Docs FlightGear/Thanks)
-
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.14  1998/04/06 21:09:37  curt
-# Additional win32 support.
-# Fixed a bad bug in dem file parsing that was causing the output to be
-# flipped about x = y.
-#
-# Revision 1.13  1998/03/19 02:52:51  curt
-# Updated to reflect some minor tool reorganization and the creation of class
-# to handle DEM processing needs.
-#
-# Revision 1.12  1998/03/19 01:48:34  curt
-# Added gpc-2.01 (generic polygon clipping library)
-#
-# Revision 1.11  1998/03/03 21:54:43  curt
-# Changes to process 30 arcsec binary DEM files.
-#
-# Revision 1.10  1998/03/03 15:36:11  curt
-# Tweaks for compiling with g++
-#
-# Revision 1.9  1998/03/03 01:21:17  curt
-# Added DemRaw2Ascii
-#
-# Revision 1.8  1998/01/31 00:41:19  curt
-# Made a few changes converting floats to doubles.
-#
-# Revision 1.7  1998/01/27 18:36:53  curt
-# Lots of updates to get back in sync with changes made over in .../Src/
-#
-# Revision 1.6  1998/01/21 02:55:42  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.5  1998/01/14 15:55:34  curt
-# Finished splittris, started assemtris.
-#
-# Revision 1.4  1997/12/10 01:18:25  curt
-# Initial revision.
-#
-# Revision 1.3  1997/11/27 00:18:26  curt
-# Added FixNode
-#
-# Revision 1.2  1997/11/14 00:31:06  curt
-# Abandon Tri2terrain ... replace with Tri2obj so we can use an existing
-# tri-stripper.
-#
-# Revision 1.1  1997/10/20 19:52:18  curt
-# Initial revision.
-#
diff --git a/Tools/Makefile.am b/Tools/Makefile.am
new file mode 100644
index 000000000..e8ab79034
--- /dev/null
+++ b/Tools/Makefile.am
@@ -0,0 +1,14 @@
+EXTRA_DIST = process-dem.pl
+
+SUBDIRS = \
+	AssemTris \
+	DEM \
+	Dem2node \
+	FixNode \
+	FixObj \
+	SplitTris \
+	Stripe_u \
+	Tri2obj \
+	Triangle
+
+bin_SCRIPTS = process-dem.pl
diff --git a/Tools/Makefile.in b/Tools/Makefile.in
new file mode 100644
index 000000000..03dc3845e
--- /dev/null
+++ b/Tools/Makefile.in
@@ -0,0 +1,297 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+EXTRA_DIST = process-dem.pl
+
+SUBDIRS = \
+	AssemTris \
+	DEM \
+	Dem2node \
+	FixNode \
+	FixObj \
+	SplitTris \
+	Stripe_u \
+	Tri2obj \
+	Triangle
+
+bin_SCRIPTS = process-dem.pl
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+SCRIPTS =  $(bin_SCRIPTS)
+
+DIST_COMMON =  README Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+all: all-recursive all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+install-binSCRIPTS: $(bin_SCRIPTS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_SCRIPTS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; fi; \
+	done
+
+uninstall-binSCRIPTS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_SCRIPTS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive  \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+	@set fnord $(MAKEFLAGS); amf=$$2; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  target=`echo $@ | sed s/-recursive//`; \
+	  echo "Making $$target in $$subdir"; \
+	  (cd $$subdir && $(MAKE) $$target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@set fnord $(MAKEFLAGS); amf=$$2; \
+	rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+	  rev="$$subdir $$rev"; \
+	done; \
+	for subdir in $$rev; do \
+	  target=`echo $@ | sed s/-recursive//`; \
+	  echo "Making $$target in $$subdir"; \
+	  (cd $$subdir && $(MAKE) $$target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  (cd $$subdir && $(MAKE) tags); \
+	done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+	done; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+	for subdir in $(SUBDIRS); do \
+	  test -d $(distdir)/$$subdir \
+	  || mkdir $(distdir)/$$subdir \
+	  || exit 1; \
+	  chmod 777 $(distdir)/$$subdir; \
+	  (cd $$subdir && $(MAKE) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
+	    || exit 1; \
+	done
+info: info-recursive
+dvi: dvi-recursive
+check: all-am
+	$(MAKE) check-recursive
+installcheck: installcheck-recursive
+all-am: Makefile $(SCRIPTS)
+
+install-exec-am: install-binSCRIPTS
+
+uninstall-am: uninstall-binSCRIPTS
+
+install-exec: install-exec-recursive install-exec-am
+	@$(NORMAL_INSTALL)
+
+install-data: install-data-recursive
+	@$(NORMAL_INSTALL)
+
+install: install-recursive install-exec-am
+	@:
+
+uninstall: uninstall-recursive uninstall-am
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs: installdirs-recursive
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean-am:  mostlyclean-tags mostlyclean-generic
+
+clean-am:  clean-tags clean-generic mostlyclean-am
+
+distclean-am:  distclean-tags distclean-generic clean-am
+
+maintainer-clean-am:  maintainer-clean-tags maintainer-clean-generic \
+		distclean-am
+
+mostlyclean:  mostlyclean-recursive mostlyclean-am
+
+clean:  clean-recursive clean-am
+
+distclean:  distclean-recursive distclean-am
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-recursive maintainer-clean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: uninstall-binSCRIPTS install-binSCRIPTS install-data-recursive \
+uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info dvi \
+installcheck all-am install-exec-am uninstall-am install-exec \
+install-data install uninstall all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Tools/make.inc b/Tools/make.inc
deleted file mode 100644
index da1c732bc..000000000
--- a/Tools/make.inc
+++ /dev/null
@@ -1,128 +0,0 @@
-# Hey Emacs, this is a Makefile. -*- Mode: Makefile -*-
-#
-# Common FGTools Makefile section
-#
-# Written by Curtis Olson, started October 1997.
-#
-# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-VERSION = 0.02
-
-#---------------------------------------------------------------------------
-# Choose your weapons
-#---------------------------------------------------------------------------
-
-CC = gcc
-FLEX = flex -f -L
-BISON = bison -v --no-lines
-AR = ar
-RANLIB = ranlib
-
-
-#---------------------------------------------------------------------------
-# Global Compile Options
-#
-# You may set FG_CFLAGS to include any of the following options depending on 
-# your environment:
-#
-# -g           - Compile with debugging symbols
-#
-# -Wall        - Enable full compiler warnings
-#
-# -O2          - Enable compiler optimization
-#
-#---------------------------------------------------------------------------
-
-GLOBAL_CFLAGS = -g -Wall -DVERSION=\"$(VERSION)\"
-
-
-#---------------------------------------------------------------------------
-# Platform specific compile options, these should be set with FG_CFLAGS
-# below.  These have been predefined for the supported platforms below.
-#
-# -DNO_PRINTF -  Disable all printf()'s.  Works by replacing the printf
-#                fuction with an empty function.
-#
-# -DUSE_ITIMER - Use setitimer(), getitimer(), and signal() to mimic
-#                a real time system and call the flight model routines
-#                at a regular interval, rather than between screen updates
-#                which can be highly variable.  This can make the flight
-#                model calculations much smoother.
-#
-# -DUSE_FTIME -  Use ftime() to get an accurate current time instead of
-#                gettimeofday()
-#
-# -DUSE_RAND  -  Use rand() instead of random()
-#
-#---------------------------------------------------------------------------
-
-
-#---------------------------------------------------------------------------
-# Uncomment one of the following sections depending on your system
-#
-# You may set FG_GRAPHICS to include any of the following options depending
-# on your environment:
-#---------------------------------------------------------------------------
-
-#---------------------------------------------------------------------------
-# SGI IRIX with the GLUT toolkit 
-#     (Surprisingly, this also works on our SunOS 4.x machine with the 
-#     way we have Mesa & Glut installed.)
-#
-# INTERFACE_FLAGS = -DGLUT
-# INTERFACE_LIBS = -lglut
-# INTERFACE_FILES = GLUTmain.c GLUTkey.c
-# GRAPHICS_LIBS = -lGLU -lGL -lXmu -lX11
-# FG_CFLAGS = $(GLOBAL_CFLAGS)
-#---------------------------------------------------------------------------
-
-#---------------------------------------------------------------------------
-# Linux/Mesa with the GLUT toolkit
-#
-INTERFACE_FLAGS = -DGLUT
-INTERFACE_LIBS = -lglut
-INTERFACE_FILES = GLUTmain.c GLUTkey.c
-MESA_LIBS = -L/usr/lib/mesa -lMesatk -lMesaaux -lMesaGLU -lMesaGL
-X11_LIBS =  -L/usr/X11R6/lib -lXext -lXmu -lXi -lX11
-GRAPHICS_LIBS = $(MESA_LIBS) $(X11_LIBS)
-FG_CFLAGS = $(GLOBAL_CFLAGS)
-#---------------------------------------------------------------------------
-
-#---------------------------------------------------------------------------
-# Cygnus Win32 (gcc based) with a static version of the GLUT toolkit
-#
-# INTERFACE_FLAGS = -DGLUT 
-# INTERFACE_LIBS = ../Win32/libglut.a
-# INTERFACE_FILES = GLUTmain.c GLUTkey.c
-# GRAPHICS_LIBS = -lglu32 -lopengl32 -luser32 -lgdi32
-# FG_CFLAGS = $(GLOBAL_CFLAGS) -DWIN32 -DUSE_RAND
-#---------------------------------------------------------------------------
-
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.2  1997/12/10 01:18:26  curt
-# Initial revision.
-#
-# Revision 1.1  1997/10/20 19:52:18  curt
-# Initial revision.
-#
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index d82b9b5ce..a9454b0b8 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -28,7 +28,7 @@
 
 $| = 1;                         # flush buffers after every write
 
-$do_demfit =     1;
+$do_dem2node =     1;
 $do_triangle_1 = 1;
 $do_fixnode =    1;
 $do_splittris =  1;
@@ -69,8 +69,8 @@ while ( $dem_file = shift(@ARGV) ) {
     }
 
 
-    if ( $do_demfit ) {
-	demfit() ;
+    if ( $do_dem2node ) {
+	dem2node() ;
     } else {
 	$subdir = "../Scenery/w100n040/w093n045";
 	print "WARNING:  Hardcoding subdir = $subdir\n";
@@ -123,7 +123,7 @@ sub file_root {
 #     splits dem file into 64 file.node's which contain the
 #     irregularly fitted vertices
 
-sub demfit {
+sub dem2node {
     if ( $dem_file =~ m/.gz$/ ) {
 	$command = "gzip -dc $dem_file | Dem2node/dem2node $ENV{FG_ROOT} - $error";
     } else {
@@ -387,6 +387,9 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.15  1998/04/08 23:24:07  curt
+# Adopted Gnu automake/autoconf system.
+#
 # Revision 1.14  1998/04/06 21:09:38  curt
 # Additional win32 support.
 # Fixed a bad bug in dem file parsing that was causing the output to be
diff --git a/Tri2obj/MAT3vec.c b/Tri2obj/MAT3vec.c
new file mode 100644
index 000000000..24f2939af
--- /dev/null
+++ b/Tri2obj/MAT3vec.c
@@ -0,0 +1,149 @@
+/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
+
+/* --------------------------------------------------------------------------
+ * This file contains routines that operate on matrices and vectors, or
+ * vectors and vectors.
+ * -------------------------------------------------------------------------*/
+
+/* #include "sphigslocal.h" */
+
+/* --------------------------  Static Routines	---------------------------- */
+
+/* -------------------------  Internal Routines  --------------------------- */
+
+/* --------------------------  Public Routines	---------------------------- */
+
+/*
+ * Multiplies a vector by a matrix, setting the result vector.
+ * It assumes all homogeneous coordinates are 1.
+ * The two vectors involved may be the same.
+ */
+
+#include <Math/mat3.h>
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+
+void
+MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
+{
+   MAT3vec		tempvec;
+   register double	*temp = tempvec;
+
+   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
+		vec[2] * mat[2][0] +	      mat[3][0];
+   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
+		vec[2] * mat[2][1] +	      mat[3][1];
+   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
+		vec[2] * mat[2][2] +	      mat[3][2];
+
+   MAT3_COPY_VEC(result_vec, temp);
+}
+
+/*
+ * Multiplies a vector of size 4 by a matrix, setting the result vector.
+ * The fourth element of the vector is the homogeneous coordinate, which
+ * may or may not be 1.  If the "normalize" parameter is TRUE, then the
+ * result vector will be normalized so that the homogeneous coordinate is 1.
+ * The two vectors involved may be the same.
+ * This returns zero if the vector was to be normalized, but couldn't be.
+ */
+
+int
+MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
+{
+   MAT3hvec             tempvec;
+   double		norm_fac;
+   register double	*temp = tempvec;
+   register int 	ret = TRUE;
+
+   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
+		vec[2] * mat[2][0] + vec[3] * mat[3][0];
+   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
+		vec[2] * mat[2][1] + vec[3] * mat[3][1];
+   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
+		vec[2] * mat[2][2] + vec[3] * mat[3][2];
+   temp[3] =	vec[0] * mat[0][3] + vec[1] * mat[1][3] +
+		vec[2] * mat[2][3] + vec[3] * mat[3][3];
+
+   /* Normalize if asked for, possible, and necessary */
+   if (normalize) {
+      if (MAT3_IS_ZERO(temp[3])) {
+#ifndef THINK_C
+	 fprintf (stderr,
+		  "Can't normalize vector: homogeneous coordinate is 0");
+#endif
+	 ret = FALSE;
+      }
+      else {
+	 norm_fac = 1.0 / temp[3];
+	 MAT3_SCALE_VEC(result_vec, temp, norm_fac);
+	 result_vec[3] = 1.0;
+      }
+   }
+   else MAT3_COPY_HVEC(result_vec, temp);
+
+   return(ret);
+}
+
+/*
+ * Sets the first vector to be the cross-product of the last two vectors.
+ */
+
+void
+MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
+{
+   MAT3vec		tempvec;
+   register double	*temp = tempvec;
+
+   temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
+   temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
+   temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
+
+   MAT3_COPY_VEC(result_vec, temp);
+}
+
+/*
+ * Finds a vector perpendicular to vec and stores it in result_vec.
+ * Method:  take any vector (we use <0,1,0>) and subtract the
+ * portion of it pointing in the vec direction.  This doesn't
+ * work if vec IS <0,1,0> or is very near it.  So if this is
+ * the case, use <0,0,1> instead.
+ * If "is_unit" is TRUE, the given vector is assumed to be unit length.
+ */
+
+#define SELECT	.7071	/* selection constant (roughly .5*sqrt(2) */
+
+void
+MAT3perp_vec(double *result_vec, double *vec, int is_unit)
+{
+   MAT3vec	norm;
+   double	dot;
+
+   MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
+
+   MAT3_COPY_VEC(norm, vec);
+
+   if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
+
+   /* See if vector is too close to <0,1,0>.  If so, use <0,0,1> */
+   if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
+      result_vec[1] = 0.0;
+      result_vec[2] = 1.0;
+      dot = MAT3_DOT_PRODUCT(norm, result_vec);
+   }
+
+   /* Subtract off non-perpendicular part */
+   result_vec[0] -= dot * norm[0];
+   result_vec[1] -= dot * norm[1];
+   result_vec[2] -= dot * norm[2];
+
+   /* Make result unit length */
+   MAT3_NORMALIZE_VEC(result_vec, dot);
+}
diff --git a/Tri2obj/Makefile b/Tri2obj/Makefile
deleted file mode 100644
index abc733a89..000000000
--- a/Tri2obj/Makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started October 1997.
-#
-# Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-TARGET = tri2obj
-
-CFILES = tri2obj.c
-LDLIBS = -lMath -lScenery -lm
-
-
-include $(FG_ROOT_SRC)/commondefs
-
-
-#---------------------------------------------------------------------------
-# Primary Targets
-#---------------------------------------------------------------------------
-
-$(TARGET): $(OBJECTS)
-	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
-
-
-include $(COMMONRULES)
-
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.5  1998/01/21 02:55:56  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.4  1998/01/17 01:25:39  curt
-# Added support for shared normals.
-#
-# Revision 1.3  1997/12/02 13:13:32  curt
-# Fixed problem with averaged vertex normals.
-#
-# Revision 1.2  1997/11/14 00:29:13  curt
-# Transform scenery coordinates at this point in pipeline when scenery is
-# being translated to .obj format, not when it is being loaded into the end
-# renderer.  Precalculate normals for each node as average of the normals
-# of each containing polygon so Garoude shading is now supportable.
-#
-# Revision 1.1  1997/10/29 23:05:14  curt
-# Initial revision.
-#
-# Revision 1.1  1997/10/23 23:12:09  curt
-# Initial revision.
-#
diff --git a/Tri2obj/Makefile.am b/Tri2obj/Makefile.am
new file mode 100644
index 000000000..4b3cba1f1
--- /dev/null
+++ b/Tri2obj/Makefile.am
@@ -0,0 +1,53 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+bin_PROGRAMS = tri2obj
+
+tri2obj_SOURCES = \
+	tri2obj.c tri2obj.h \
+	MAT3vec.c \
+	fg_geodesy.c fg_geodesy.h \
+	mat3.h \
+	polar.c polar.h
+
+tri2obj_LDADD = \
+	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+
+INCLUDES += -I../../Simulator
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/08 23:22:13  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.2  1998/01/21 02:55:46  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1998/01/15 02:45:25  curt
+# Initial revision.
+#
+
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
new file mode 100644
index 000000000..7bac2edd1
--- /dev/null
+++ b/Tri2obj/Makefile.in
@@ -0,0 +1,366 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = tri2obj
+
+tri2obj_SOURCES = \
+	tri2obj.c tri2obj.h \
+	MAT3vec.c \
+	fg_geodesy.c fg_geodesy.h \
+	mat3.h \
+	polar.c polar.h
+
+tri2obj_LDADD = \
+	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+tri2obj_OBJECTS =  tri2obj.o MAT3vec.o fg_geodesy.o polar.o
+tri2obj_DEPENDENCIES =  \
+$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+tri2obj_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/MAT3vec.P .deps/fg_geodesy.P .deps/polar.P \
+.deps/tri2obj.P
+SOURCES = $(tri2obj_SOURCES)
+OBJECTS = $(tri2obj_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Tri2obj/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+tri2obj: $(tri2obj_OBJECTS) $(tri2obj_DEPENDENCIES)
+	@rm -f tri2obj
+	$(LINK) $(tri2obj_LDFLAGS) $(tri2obj_OBJECTS) $(tri2obj_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/Tri2obj
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Tri2obj/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+INCLUDES += -I../../Simulator
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/08 23:22:14  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.2  1998/01/21 02:55:46  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1998/01/15 02:45:25  curt
+# Initial revision.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Tri2obj/fg_geodesy.c b/Tri2obj/fg_geodesy.c
new file mode 100644
index 000000000..bedd202b4
--- /dev/null
+++ b/Tri2obj/fg_geodesy.c
@@ -0,0 +1,230 @@
+/**************************************************************************
+ * fg_geodesy.c -- routines to convert between geodetic and geocentric 
+ *                 coordinate systems.
+ *
+ * Copied and adapted directly from LaRCsim/ls_geodesy.c
+ *
+ * See below for the complete original LaRCsim comments.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#include <math.h>
+
+#include <Include/fg_constants.h>
+
+#include "fg_geodesy.h"
+
+
+/* ONE_SECOND is pi/180/60/60, or about 100 feet at earths' equator */
+#define ONE_SECOND 4.848136811E-6
+
+
+/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
+ *     INPUTS:	
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *         radius	C.G. radius to earth center, ft
+ *
+ *     OUTPUTS:
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *         sea_level_r	radius from earth center to sea level at
+ *                      local vertical (surface normal) of C.G.
+ */
+
+void fgGeocToGeod( double lat_geoc, double radius, double
+		   *lat_geod, double *alt, double *sea_level_r )
+{
+    double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
+    double sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
+
+    if( ( (FG_PI_2 - lat_geoc) < ONE_SECOND )     /* near North pole */
+	|| ( (FG_PI_2 + lat_geoc) < ONE_SECOND ) )   /* near South pole */
+    {
+	*lat_geod = lat_geoc;
+	*sea_level_r = EQUATORIAL_RADIUS_KM*E;
+	*alt = radius - *sea_level_r;
+    } else {
+	t_lat = tan(lat_geoc);
+	x_alpha = E*EQUATORIAL_RADIUS_KM/sqrt(t_lat*t_lat + E*E);
+	mu_alpha = atan2(sqrt(RESQ_KM - x_alpha*x_alpha),E*x_alpha);
+	if (lat_geoc < 0) mu_alpha = - mu_alpha;
+	sin_mu_a = sin(mu_alpha);
+	delt_lambda = mu_alpha - lat_geoc;
+	r_alpha = x_alpha/cos(lat_geoc);
+	l_point = radius - r_alpha;
+	*alt = l_point*cos(delt_lambda);
+	denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
+	rho_alpha = EQUATORIAL_RADIUS_KM*(1-EPS)/
+	    (denom*denom*denom);
+	delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
+	*lat_geod = mu_alpha - delt_mu;
+	lambda_sl = atan( E*E * tan(*lat_geod) ); /* SL geoc. latitude */
+	sin_lambda_sl = sin( lambda_sl );
+	*sea_level_r = 
+	    sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
+    }
+}
+
+
+/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
+ *     INPUTS:	
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *
+ *     OUTPUTS:
+ *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
+ *                      get true distance from earth center.
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *
+ */
+
+void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
+		      double *lat_geoc )
+{
+    double lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
+    
+    lambda_sl = atan( E*E * tan(lat_geod) ); /* sea level geocentric latitude */
+    sin_lambda_sl = sin( lambda_sl );
+    cos_lambda_sl = cos( lambda_sl );
+    sin_mu = sin(lat_geod);	/* Geodetic (map makers') latitude */
+    cos_mu = cos(lat_geod);
+    *sl_radius = 
+	sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
+    py = *sl_radius*sin_lambda_sl + alt*sin_mu;
+    px = *sl_radius*cos_lambda_sl + alt*cos_mu;
+    *lat_geoc = atan2( py, px );
+}
+
+
+/***************************************************************************
+
+	TITLE:	ls_geodesy
+	
+----------------------------------------------------------------------------
+
+	FUNCTION:	Converts geocentric coordinates to geodetic positions
+
+----------------------------------------------------------------------------
+
+	MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	DESIGNED BY:	E. B. Jackson
+	
+	CODED BY:	E. B. Jackson
+	
+	MAINTAINED BY:	E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	MODIFICATION HISTORY:
+	
+	DATE	PURPOSE						BY
+	
+	930208	Modified to avoid singularity near polar region.	EBJ
+	930602	Moved backwards calcs here from ls_step.		EBJ
+	931214	Changed erroneous Latitude and Altitude variables to 
+		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
+	940111	Changed header files from old ls_eom.h style to ls_types, 
+		and ls_constants.  Also replaced old DATA type with new
+		SCALAR type.						EBJ
+
+	CURRENT RCS HEADER:
+
+$Header$
+$Log$
+Revision 1.1  1998/04/08 23:22:14  curt
+Adopted Gnu automake/autoconf system.
+
+Revision 1.4  1998/01/27 00:47:59  curt
+Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+system and commandline/config file processing code.
+
+Revision 1.3  1998/01/19 19:27:12  curt
+Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+This should simplify things tremendously.
+
+Revision 1.2  1997/12/15 23:54:54  curt
+Add xgl wrappers for debugging.
+Generate terrain normals on the fly.
+
+Revision 1.1  1997/07/31 23:13:14  curt
+Initial revision.
+
+Revision 1.1  1997/05/29 00:09:56  curt
+Initial Flight Gear revision.
+
+ * Revision 1.5  1994/01/11  18:47:05  bjax
+ * Changed include files to use types and constants, not ls_eom.h
+ * Also changed DATA type to SCALAR type.
+ *
+ * Revision 1.4  1993/12/14  21:06:47  bjax
+ * Removed global variable references Altitude and Latitude.   EBJ
+ *
+ * Revision 1.3  1993/06/02  15:03:40  bjax
+ * Made new subroutine for calculating geodetic to geocentric; changed name
+ * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
+ *
+
+----------------------------------------------------------------------------
+
+	REFERENCES:
+
+		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
+			Control and Simulation", Wiley and Sons, 1992.
+			ISBN 0-471-61397-5		      
+
+
+----------------------------------------------------------------------------
+
+	CALLED BY:	ls_aux
+
+----------------------------------------------------------------------------
+
+	CALLS TO:
+
+----------------------------------------------------------------------------
+
+	INPUTS:	
+		lat_geoc	Geocentric latitude, radians, + = North
+		radius		C.G. radius to earth center, ft
+
+----------------------------------------------------------------------------
+
+	OUTPUTS:
+		lat_geod	Geodetic latitude, radians, + = North
+		alt		C.G. altitude above mean sea level, ft
+		sea_level_r	radius from earth center to sea level at
+				local vertical (surface normal) of C.G.
+
+--------------------------------------------------------------------------*/
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:22:14  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.4  1998/01/27 00:47:59  curt
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+ * system and commandline/config file processing code.
+ *
+ * Revision 1.3  1998/01/19 19:27:12  curt
+ * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+ * This should simplify things tremendously.
+ *
+ * Revision 1.2  1997/12/15 23:54:54  curt
+ * Add xgl wrappers for debugging.
+ * Generate terrain normals on the fly.
+ *
+ * Revision 1.1  1997/07/31 23:13:14  curt
+ * Initial revision.
+ *
+ */
diff --git a/Tri2obj/fg_geodesy.h b/Tri2obj/fg_geodesy.h
new file mode 100644
index 000000000..22a030ffb
--- /dev/null
+++ b/Tri2obj/fg_geodesy.h
@@ -0,0 +1,163 @@
+/**************************************************************************
+ * fg_geodesy.h -- routines to convert between geodetic and geocentric 
+ *                 coordinate systems.
+ *
+ * Copied and adapted directly from LaRCsim/ls_geodesy.c
+ *
+ * See below for the complete original LaRCsim comments.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#ifndef _FG_GEODESY_H
+#define _FG_GEODESY_H
+
+
+/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
+ *     INPUTS:	
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *         radius	C.G. radius to earth center, ft
+ *
+ *     OUTPUTS:
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *         sea_level_r	radius from earth center to sea level at
+ *                      local vertical (surface normal) of C.G.
+ */
+
+void fgGeocToGeod( double lat_geoc, double radius, double
+		   *lat_geod, double *alt, double *sea_level_r );
+
+/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
+ *     INPUTS:	
+ *         lat_geod	Geodetic latitude, radians, + = North
+ *         alt		C.G. altitude above mean sea level, ft
+ *
+ *     OUTPUTS:
+ *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
+ *                      get true distance from earth center.
+ *         lat_geoc	Geocentric latitude, radians, + = North
+ *
+ */
+
+void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
+		   double *lat_geoc );
+
+
+
+/***************************************************************************
+
+	TITLE:	ls_geodesy
+	
+----------------------------------------------------------------------------
+
+	FUNCTION:	Converts geocentric coordinates to geodetic positions
+
+----------------------------------------------------------------------------
+
+	MODULE STATUS:	developmental
+
+----------------------------------------------------------------------------
+
+	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	DESIGNED BY:	E. B. Jackson
+	
+	CODED BY:	E. B. Jackson
+	
+	MAINTAINED BY:	E. B. Jackson
+
+----------------------------------------------------------------------------
+
+	MODIFICATION HISTORY:
+	
+	DATE	PURPOSE						BY
+	
+	930208	Modified to avoid singularity near polar region.	EBJ
+	930602	Moved backwards calcs here from ls_step.		EBJ
+	931214	Changed erroneous Latitude and Altitude variables to 
+		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
+	940111	Changed header files from old ls_eom.h style to ls_types, 
+		and ls_constants.  Also replaced old DATA type with new
+		SCALAR type.						EBJ
+
+	CURRENT RCS HEADER:
+
+$Header$
+$Log$
+Revision 1.1  1998/04/08 23:22:15  curt
+Adopted Gnu automake/autoconf system.
+
+Revision 1.2  1998/01/22 02:59:38  curt
+Changed #ifdef FILE_H to #ifdef _FILE_H
+
+Revision 1.1  1997/07/31 23:13:14  curt
+Initial revision.
+
+Revision 1.1  1997/05/29 00:09:56  curt
+Initial Flight Gear revision.
+
+ * Revision 1.5  1994/01/11  18:47:05  bjax
+ * Changed include files to use types and constants, not ls_eom.h
+ * Also changed DATA type to SCALAR type.
+ *
+ * Revision 1.4  1993/12/14  21:06:47  bjax
+ * Removed global variable references Altitude and Latitude.   EBJ
+ *
+ * Revision 1.3  1993/06/02  15:03:40  bjax
+ * Made new subroutine for calculating geodetic to geocentric; changed name
+ * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
+ *
+
+----------------------------------------------------------------------------
+
+	REFERENCES:
+
+		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
+			Control and Simulation", Wiley and Sons, 1992.
+			ISBN 0-471-61397-5		      
+
+
+----------------------------------------------------------------------------
+
+	CALLED BY:	ls_aux
+
+----------------------------------------------------------------------------
+
+	CALLS TO:
+
+----------------------------------------------------------------------------
+
+	INPUTS:	
+		lat_geoc	Geocentric latitude, radians, + = North
+		radius		C.G. radius to earth center, ft
+
+----------------------------------------------------------------------------
+
+	OUTPUTS:
+		lat_geod	Geodetic latitude, radians, + = North
+		alt		C.G. altitude above mean sea level, ft
+		sea_level_r	radius from earth center to sea level at
+				local vertical (surface normal) of C.G.
+
+--------------------------------------------------------------------------*/
+
+
+#endif /* _FG_GEODESY_H */
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:22:15  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.2  1998/01/22 02:59:38  curt
+ * Changed #ifdef FILE_H to #ifdef _FILE_H
+ *
+ * Revision 1.1  1997/07/31 23:13:14  curt
+ * Initial revision.
+ *
+ */
diff --git a/Tri2obj/mat3.h b/Tri2obj/mat3.h
new file mode 100644
index 000000000..58c4b9e07
--- /dev/null
+++ b/Tri2obj/mat3.h
@@ -0,0 +1,147 @@
+/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
+
+/* -------------------------------------------------------------------------
+		       Public MAT3 include file
+   ------------------------------------------------------------------------- */
+
+#ifndef MAT3_HAS_BEEN_INCLUDED
+#define MAT3_HAS_BEEN_INCLUDED
+
+/* -----------------------------  Constants  ------------------------------ */
+
+/*
+ * Make sure the math library .h file is included, in case it wasn't.
+ */
+
+#ifndef HUGE
+#include <math.h>
+#endif
+#include <stdio.h>
+
+
+#define MAT3_DET0	-1			/* Indicates singular mat */
+#define MAT3_EPSILON	1e-12			/* Close enough to zero   */
+#define MAT3_PI 	3.141592653589793	/* Pi			  */
+
+/* ------------------------------  Types  --------------------------------- */
+
+typedef double MAT3mat[4][4];		/* 4x4 matrix			 */
+typedef double MAT3vec[3];		/* Vector			 */
+typedef double MAT3hvec[4];             /* Vector with homogeneous coord */
+
+/* ------------------------------  Macros  -------------------------------- */
+
+/* Tests if a number is within EPSILON of zero */
+#define MAT3_IS_ZERO(N) 	((N) < MAT3_EPSILON && (N) > -MAT3_EPSILON)
+
+/* Sets a vector to the three given values */
+#define MAT3_SET_VEC(V,X,Y,Z)	((V)[0]=(X), (V)[1]=(Y), (V)[2]=(Z))
+
+/* Tests a vector for all components close to zero */
+#define MAT3_IS_ZERO_VEC(V)	(MAT3_IS_ZERO((V)[0]) && \
+				 MAT3_IS_ZERO((V)[1]) && \
+				 MAT3_IS_ZERO((V)[2]))
+
+/* Dot product of two vectors */
+#define MAT3_DOT_PRODUCT(V1,V2) \
+			((V1)[0]*(V2)[0] + (V1)[1]*(V2)[1] + (V1)[2]*(V2)[2])
+
+/* Copy one vector to other */
+#define MAT3_COPY_VEC(TO,FROM)	((TO)[0] = (FROM)[0], \
+				 (TO)[1] = (FROM)[1], \
+				 (TO)[2] = (FROM)[2])
+
+/* Normalize vector to unit length, using TEMP as temporary variable.
+ * TEMP will be zero if vector has zero length */
+#define MAT3_NORMALIZE_VEC(V,TEMP) \
+	if ((TEMP = sqrt(MAT3_DOT_PRODUCT(V,V))) > MAT3_EPSILON) { \
+	   TEMP = 1.0 / TEMP; \
+	   MAT3_SCALE_VEC(V,V,TEMP); \
+	} else TEMP = 0.0
+
+/* Scale vector by given factor, storing result vector in RESULT_V */
+#define MAT3_SCALE_VEC(RESULT_V,V,SCALE) \
+	MAT3_SET_VEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), (V)[2]*(SCALE))
+
+/* Adds vectors V1 and V2, storing result in RESULT_V */
+#define MAT3_ADD_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
+			       (V1)[2]+(V2)[2])
+
+/* Subtracts vector V2 from V1, storing result in RESULT_V */
+#define MAT3_SUB_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
+			       (V1)[2]-(V2)[2])
+
+/* Multiplies vectors V1 and V2, storing result in RESULT_V */
+#define MAT3_MULT_VEC(RESULT_V,V1,V2) \
+	MAT3_SET_VEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
+			       (V1)[2]*(V2)[2])
+
+/* Sets RESULT_V to the linear combination of V1 and V2, scaled by
+ * SCALE1 and SCALE2, respectively */
+#define MAT3_LINEAR_COMB(RESULT_V,SCALE1,V1,SCALE2,V2) \
+	MAT3_SET_VEC(RESULT_V,	(SCALE1)*(V1)[0] + (SCALE2)*(V2)[0], \
+				(SCALE1)*(V1)[1] + (SCALE2)*(V2)[1], \
+				(SCALE1)*(V1)[2] + (SCALE2)*(V2)[2])
+
+/* Several of the vector macros are useful for homogeneous-coord vectors */
+#define MAT3_SET_HVEC(V,X,Y,Z,W) ((V)[0]=(X), (V)[1]=(Y), \
+				  (V)[2]=(Z), (V)[3]=(W))
+
+#define MAT3_COPY_HVEC(TO,FROM) ((TO)[0] = (FROM)[0], \
+				 (TO)[1] = (FROM)[1], \
+				 (TO)[2] = (FROM)[2], \
+				 (TO)[3] = (FROM)[3])
+
+#define MAT3_SCALE_HVEC(RESULT_V,V,SCALE) \
+	MAT3_SET_HVEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), \
+				(V)[2]*(SCALE), (V)[3]*(SCALE))
+
+#define MAT3_ADD_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
+				(V1)[2]+(V2)[2], (V1)[3]+(V2)[3])
+
+#define MAT3_SUB_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
+				(V1)[2]-(V2)[2], (V1)[3]-(V2)[3])
+
+#define MAT3_MULT_HVEC(RESULT_V,V1,V2) \
+	MAT3_SET_HVEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
+				(V1)[2]*(V2)[2], (V1)[3]*(V2)[3])
+
+/* ------------------------------  Entries  ------------------------------- */
+
+
+/* In MAT3geom.c */
+void 		MAT3direction_matrix (MAT3mat result_mat, MAT3mat mat);
+int 		MAT3normal_matrix (MAT3mat result_mat, MAT3mat mat);
+void		MAT3rotate (MAT3mat result_mat, MAT3vec axis, double angle_in_radians);
+void		MAT3translate (MAT3mat result_mat, MAT3vec trans);
+void		MAT3scale (MAT3mat result_mat, MAT3vec scale);
+void		MAT3shear(MAT3mat result_mat, double xshear, double yshear);
+
+/* In MAT3mat.c */
+void		MAT3identity(MAT3mat);
+void		MAT3zero(MAT3mat);
+void		MAT3copy (MAT3mat to, MAT3mat from);
+void		MAT3mult (MAT3mat result, MAT3mat, MAT3mat);
+void		MAT3transpose (MAT3mat result, MAT3mat);
+int			MAT3invert (MAT3mat result, MAT3mat);
+void		MAT3print (MAT3mat, FILE *fp);
+void		MAT3print_formatted (MAT3mat, FILE *fp, 
+			 	     char *title, char *head, char *format, char *tail);
+extern int		MAT3equal( void );
+extern double		MAT3trace( void );
+extern int		MAT3power( void );
+extern int		MAT3column_reduce( void );
+extern int		MAT3kernel_basis( void );
+
+/* In MAT3vec.c */
+void		MAT3mult_vec(MAT3vec result_vec, MAT3vec vec, MAT3mat mat);
+int		MAT3mult_hvec (MAT3hvec result_vec, MAT3hvec vec, MAT3mat mat, int normalize);
+void		MAT3cross_product(MAT3vec result,MAT3vec,MAT3vec);
+void		MAT3perp_vec(MAT3vec result_vec, MAT3vec vec, int is_unit);
+
+#endif /* MAT3_HAS_BEEN_INCLUDED */
+
diff --git a/Tri2obj/polar.c b/Tri2obj/polar.c
new file mode 100644
index 000000000..fae264766
--- /dev/null
+++ b/Tri2obj/polar.c
@@ -0,0 +1,124 @@
+/**************************************************************************
+ * polar.c -- routines to deal with polar math and transformations
+ *
+ * Written by Curtis Olson, started June 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#include <math.h>
+#include <stdio.h>
+
+#include <Math/polar.h>
+#include <Include/fg_constants.h>
+
+
+/* we can save these values between calls for efficiency */
+static double st, ct, sp, cp;
+
+
+/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
+ * must be specified in radians.  The FG convention is for distances
+ * to be specified in meters */
+struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius) {
+    struct fgCartesianPoint pnew;
+
+    pnew.x = cos(lon) * cos(lat) * radius;
+    pnew.y = sin(lon) * cos(lat) * radius;
+    pnew.z = sin(lat) * radius;
+
+    return(pnew);
+}
+
+
+/* Precalculate as much as possible so we can do a batch of transforms
+ * through the same angles, will rotates a cartesian point about the
+ * center of the earth by Theta (longitude axis) and Phi (latitude
+ * axis) */
+
+/* Here are the unoptimized transformation equations 
+
+   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
+	     sin(Phi) * z
+   y' = -sin(Theta) * x + cos(Theta) * y
+   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
+	     cos(Phi) * z;
+
+ */
+void fgRotateBatchInit(double Theta, double Phi) {
+    printf("Theta = %.3f, Phi = %.3f\n", Theta, Phi);
+
+    st = sin(Theta);
+    ct = cos(Theta);
+    sp = sin(-Phi);
+    cp = cos(-Phi);
+}
+
+/* Rotates a cartesian point about the center of the earth by Theta
+ * (longitude axis) and Phi (latitude axis) */
+struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p) {
+    struct fgCartesianPoint p1, p2;
+
+    /* printf("start = %.3f %.3f %.3f\n", p.x, p.y, p.z); */
+
+    /* rotate about the z axis */
+    p1.x = ct * p.x - st * p.y;
+    p1.y = st * p.x + ct * p.y;
+    p1.z = p.z;
+
+    /* printf("step 1 = %.3f %.3f %.3f\n", p1.x, p1.y, p1.z); */
+
+    /* rotate new point about y axis */
+    p2.x = cp * p1.x + sp * p1.z;
+    p2.y = p1.y;
+    p2.z = cp * p1.z - sp * p1.x;
+
+    /* printf("cp = %.5f, sp = %.5f\n", cp, sp); */
+    /* printf("(1) = %.5f, (2) = %.5f\n", cp * p1.z, sp * p1.x); */
+
+    /* printf("step 2 = %.3f %.3f %.3f\n", p2.x, p2.y, p2.z); */
+
+    return(p2);
+}
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:22:16  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.5  1998/01/27 00:48:00  curt
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+ * system and commandline/config file processing code.
+ *
+ * Revision 1.4  1998/01/19 19:27:12  curt
+ * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+ * This should simplify things tremendously.
+ *
+ * Revision 1.3  1997/12/15 23:54:54  curt
+ * Add xgl wrappers for debugging.
+ * Generate terrain normals on the fly.
+ *
+ * Revision 1.2  1997/07/31 22:52:27  curt
+ * Working on redoing internal coordinate systems & scenery transformations.
+ *
+ * Revision 1.1  1997/07/07 21:02:36  curt
+ * Initial revision.
+ * */
diff --git a/Tri2obj/polar.h b/Tri2obj/polar.h
new file mode 100644
index 000000000..fc54a77c5
--- /dev/null
+++ b/Tri2obj/polar.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+ * polar.h -- routines to deal with polar math and transformations
+ *
+ * Written by Curtis Olson, started June 1997.
+ *
+ * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * (Log is kept at end of this file)
+ **************************************************************************/
+
+
+#ifndef _POLAR_H
+#define _POLAR_H
+
+
+#include <Include/fg_types.h>
+
+
+/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
+ * must be specified in radians.  The FG convention is for distances
+ * to be specified in meters */
+struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius);
+
+
+/* Precalculate as much as possible so we can do a batch of transforms
+ * through the same angles, will rotates a cartesian point about the
+ * center of the earth by Theta (longitude axis) and Phi (latitude
+ * axis) */
+
+/* Here are the unoptimized transformation equations 
+
+   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
+	     sin(Phi) * z
+   y' = -sin(Theta) * x + cos(Theta) * y
+   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
+	     cos(Phi) * z;
+
+ */
+void fgRotateBatchInit(double Theta, double Phi);
+
+
+/* Rotates a cartesian point about the center of the earth by Theta
+ * (longitude axis) and Phi (latitude axis) */
+struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p);
+
+
+#endif /* _POLAR_H */
+
+
+/* $Log$
+/* Revision 1.1  1998/04/08 23:22:17  curt
+/* Adopted Gnu automake/autoconf system.
+/*
+ * Revision 1.7  1998/01/27 00:48:00  curt
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
+ * system and commandline/config file processing code.
+ *
+ * Revision 1.6  1998/01/22 02:59:39  curt
+ * Changed #ifdef FILE_H to #ifdef _FILE_H
+ *
+ * Revision 1.5  1998/01/19 19:27:13  curt
+ * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+ * This should simplify things tremendously.
+ *
+ * Revision 1.4  1997/12/15 23:54:55  curt
+ * Add xgl wrappers for debugging.
+ * Generate terrain normals on the fly.
+ *
+ * Revision 1.3  1997/07/31 22:52:28  curt
+ * Working on redoing internal coordinate systems & scenery transformations.
+ *
+ * Revision 1.2  1997/07/23 21:52:21  curt
+ * Put comments around the text after an #endif for increased portability.
+ *
+ * Revision 1.1  1997/07/07 21:02:37  curt
+ * Initial revision.
+ *
+ */
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index e44f5559d..fb0f8ddb2 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -34,10 +34,11 @@
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
-#include <Math/fg_geodesy.h>
-#include <Math/mat3.h>
-#include <Math/polar.h>
-#include <Scenery/bucketutils.h>
+#include <Scenery/Bucket/bucketutils.h>
+
+#include "fg_geodesy.h"
+#include "mat3.h"
+#include "polar.h"
 
 
 int nodecount, tricount;
@@ -639,9 +640,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.11  1998/03/03 16:01:00  curt
-/* More c++ compile tweaks.
+/* Revision 1.12  1998/04/08 23:22:18  curt
+/* Adopted Gnu automake/autoconf system.
 /*
+ * Revision 1.11  1998/03/03 16:01:00  curt
+ * More c++ compile tweaks.
+ *
  * Revision 1.10  1998/01/31 00:41:27  curt
  * Made a few changes converting floats to doubles.
  *
diff --git a/Triangle/Makefile b/Triangle/Makefile
deleted file mode 100644
index cccdf2b1c..000000000
--- a/Triangle/Makefile
+++ /dev/null
@@ -1,111 +0,0 @@
-# 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 -f
-
-# 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 -L/usr/X11R6/lib -lX11
-
-clean: distclean
-
-distclean:
-	$(RM) $(BIN)triangle $(BIN)triangle.o $(BIN)showme
diff --git a/Triangle/Makefile.am b/Triangle/Makefile.am
new file mode 100644
index 000000000..99c292410
--- /dev/null
+++ b/Triangle/Makefile.am
@@ -0,0 +1,18 @@
+# DEFS 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 DEFS line is:
+#
+#   DEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
+
+DEFS += 
+
+bin_PROGRAMS = triangle # showme
+
+triangle_SOURCES = triangle.c triangle.h
+
+# showme_SOURCES = showme.c
diff --git a/Triangle/Makefile.in b/Triangle/Makefile.in
new file mode 100644
index 000000000..eed70e754
--- /dev/null
+++ b/Triangle/Makefile.in
@@ -0,0 +1,333 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# DEFS 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 DEFS line is:
+#
+#   DEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = triangle # showme
+
+triangle_SOURCES = triangle.c triangle.h
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+triangle_OBJECTS =  triangle.o
+triangle_LDADD = $(LDADD)
+triangle_DEPENDENCIES = 
+triangle_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  README Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/triangle.P
+SOURCES = $(triangle_SOURCES)
+OBJECTS = $(triangle_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Triangle/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+triangle: $(triangle_OBJECTS) $(triangle_DEPENDENCIES)
+	@rm -f triangle
+	$(LINK) $(triangle_LDFLAGS) $(triangle_OBJECTS) $(triangle_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/Triangle
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Triangle/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+DEFS += 
+
+# showme_SOURCES = showme.c
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Triangle/depend b/Triangle/depend
deleted file mode 100644
index 3293c1b40..000000000
--- a/Triangle/depend
+++ /dev/null
@@ -1,27 +0,0 @@
-showme.o: showme.c /usr/include/stdio.h /usr/include/features.h \
- /usr/include/sys/cdefs.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/string.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
- /usr/include/X11/Xlib.h /usr/include/sys/types.h \
- /usr/include/linux/types.h /usr/include/linux/posix_types.h \
- /usr/include/asm/posix_types.h /usr/include/asm/types.h \
- /usr/include/sys/bitypes.h /usr/include/X11/X.h \
- /usr/include/X11/Xfuncproto.h /usr/include/X11/Xosdefs.h \
- /usr/include/X11/Xutil.h /usr/include/X11/Xatom.h
-triangle.o: triangle.c /usr/include/stdio.h /usr/include/features.h \
- /usr/include/sys/cdefs.h /usr/include/libio.h \
- /usr/include/_G_config.h /usr/include/string.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/stddef.h \
- /usr/include/math.h /usr/include/huge_val.h /usr/include/endian.h \
- /usr/include/bytesex.h /usr/include/nan.h \
- /usr/lib/gcc-lib/i486-linux/2.7.2.1/include/float.h \
- /usr/include/values.h /usr/include/ieee754.h \
- /usr/include/i386/ieeefp.h /usr/include/ieee854.h \
- /usr/include/sys/time.h /usr/include/linux/types.h \
- /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h \
- /usr/include/asm/types.h /usr/include/linux/time.h \
- /usr/include/time.h /usr/include/sys/types.h \
- /usr/include/sys/bitypes.h
-tricall.o: tricall.c /usr/include/stdio.h /usr/include/features.h \
- /usr/include/sys/cdefs.h /usr/include/libio.h \
- /usr/include/_G_config.h triangle.h
diff --git a/Triangle/triangle.doc b/Triangle/triangle.doc
new file mode 100644
index 000000000..28b633978
--- /dev/null
+++ b/Triangle/triangle.doc
@@ -0,0 +1,817 @@
+Triangle
+A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.
+Version 1.3
+
+Copyright 1996 Jonathan Richard Shewchuk  (bugs/comments to jrs@cs.cmu.edu)
+School of Computer Science / Carnegie Mellon University
+5000 Forbes Avenue / Pittsburgh, Pennsylvania  15213-3891
+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.
+This executable is compiled for double precision arithmetic.
+
+
+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.  If no command line switches are specified, your .node
+input file will be read, and the Delaunay triangulation will be returned in
+.node and .ele output files.  The command syntax is:
+
+triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file
+
+Underscores indicate that numbers may optionally follow certain switches;
+do not leave any space between a switch and its numeric parameter.
+input_file must be a file with extension .node, or extension .poly if the
+-p switch is used.  If -r is used, you must supply .node and .ele files,
+and possibly a .poly file and .area file as well.  The formats of these
+files are described below.
+
+Command Line Switches:
+
+    -p  Reads a Planar Straight Line Graph (.poly file), which can specify
+        points, segments, holes, and regional attributes and area
+        constraints.  Will generate a constrained Delaunay triangulation
+        fitting the input; or, if -s, -q, or -a is used, a conforming
+        Delaunay triangulation.  If -p is not used, Triangle reads a .node
+        file by default.
+    -r  Refines a previously generated mesh.  The mesh is read from a .node
+        file and an .ele file.  If -p is also used, a .poly file is read
+        and used to constrain edges in the mesh.  Further details on
+        refinement are given below.
+    -q  Quality mesh generation by Jim Ruppert's Delaunay refinement
+        algorithm.  Adds points to the mesh to ensure that no angles
+        smaller than 20 degrees occur.  An alternative minimum angle may be
+        specified after the `q'.  If the minimum angle is 20.7 degrees or
+        smaller, the triangulation algorithm is theoretically guaranteed to
+        terminate (assuming infinite precision arithmetic - Triangle may
+        fail to terminate if you run out of precision).  In practice, the
+        algorithm often succeeds for minimum angles up to 33.8 degrees.
+        For highly refined meshes, however, it may be necessary to reduce
+        the minimum angle to well below 20 to avoid problems associated
+        with insufficient floating-point precision.  The specified angle
+        may include a decimal point.
+    -a  Imposes a maximum triangle area.  If a number follows the `a', no
+        triangle will be generated whose area is larger than that number.
+        If no number is specified, an .area file (if -r is used) or .poly
+        file (if -r is not used) specifies a number of maximum area
+        constraints.  An .area file contains a separate area constraint for
+        each triangle, and is useful for refining a finite element mesh
+        based on a posteriori error estimates.  A .poly file can optionally
+        contain an area constraint for each segment-bounded region, thereby
+        enforcing triangle densities in a first triangulation.  You can
+        impose both a fixed area constraint and a varying area constraint
+        by invoking the -a switch twice, once with and once without a
+        number following.  Each area specified may include a decimal point.
+    -A  Assigns an additional attribute to each triangle that identifies
+        what segment-bounded region each triangle belongs to.  Attributes
+        are assigned to regions by the .poly file.  If a region is not
+        explicitly marked by the .poly file, triangles in that region are
+        assigned an attribute of zero.  The -A switch has an effect only
+        when the -p switch is used and the -r switch is not.
+    -c  Creates segments on the convex hull of the triangulation.  If you
+        are triangulating a point set, this switch causes a .poly file to
+        be written, containing all edges in the convex hull.  (By default,
+        a .poly file is written only if a .poly file is read.)  If you are
+        triangulating a PSLG, this switch specifies that the interior of
+        the convex hull of the PSLG should be triangulated.  If you do not
+        use this switch when triangulating a PSLG, it is assumed that you
+        have identified the region to be triangulated by surrounding it
+        with segments of the input PSLG.  Beware:  if you are not careful,
+        this switch can cause the introduction of an extremely thin angle
+        between a PSLG segment and a convex hull segment, which can cause
+        overrefinement or failure if Triangle runs out of precision.  If
+        you are refining a mesh, the -c switch works differently; it
+        generates the set of boundary edges of the mesh, rather than the
+        convex hull.
+    -e  Outputs (to an .edge file) a list of edges of the triangulation.
+    -v  Outputs the Voronoi diagram associated with the triangulation.
+        Does not attempt to detect degeneracies.
+    -n  Outputs (to a .neigh file) a list of triangles neighboring each
+        triangle.
+    -g  Outputs the mesh to an Object File Format (.off) file, suitable for
+        viewing with the Geometry Center's Geomview package.
+    -B  No boundary markers in the output .node, .poly, and .edge output
+        files.  See the detailed discussion of boundary markers below.
+    -P  No output .poly file.  Saves disk space, but you lose the ability
+        to impose segment constraints on later refinements of the mesh.
+    -N  No output .node file.
+    -E  No output .ele file.
+    -I  No iteration numbers.  Suppresses the output of .node and .poly
+        files, so your input files won't be overwritten.  (If your input is
+        a .poly file only, a .node file will be written.)  Cannot be used
+        with the -r switch, because that would overwrite your input .ele
+        file.  Shouldn't be used with the -s, -q, or -a switch if you are
+        using a .node file for input, because no .node file will be
+        written, so there will be no record of any added points.
+    -O  No holes.  Ignores the holes in the .poly file.
+    -X  No exact arithmetic.  Normally, Triangle uses exact floating-point
+        arithmetic for certain tests if it thinks the inexact tests are not
+        accurate enough.  Exact arithmetic ensures the robustness of the
+        triangulation algorithms, despite floating-point roundoff error.
+        Disabling exact arithmetic with the -X switch will cause a small
+        improvement in speed and create the possibility (albeit small) that
+        Triangle will fail to produce a valid mesh.  Not recommended.
+    -z  Numbers all items starting from zero (rather than one).  Note that
+        this switch is normally overrided by the value used to number the
+        first point of the input .node or .poly file.  However, this switch
+        is useful when calling Triangle from another program.
+    -o2 Generates second-order subparametric elements with six nodes each.
+    -Y  No new points on the boundary.  This switch is useful when the mesh
+        boundary must be preserved so that it conforms to some adjacent
+        mesh.  Be forewarned that you will probably sacrifice some of the
+        quality of the mesh; Triangle will try, but the resulting mesh may
+        contain triangles of poor aspect ratio.  Works well if all the
+        boundary points are closely spaced.  Specify this switch twice
+        (`-YY') to prevent all segment splitting, including internal
+        boundaries.
+    -S  Specifies the maximum number of Steiner points (points that are not
+        in the input, but are added to meet the constraints of minimum
+        angle and maximum area).  The default is to allow an unlimited
+        number.  If you specify this switch with no number after it,
+        the limit is set to zero.  Triangle always adds points at segment
+        intersections, even if it needs to use more points than the limit
+        you set.  When Triangle inserts segments by splitting (-s), it
+        always adds enough points to ensure that all the segments appear in
+        the triangulation, again ignoring the limit.  Be forewarned that
+        the -S switch may result in a conforming triangulation that is not
+        truly Delaunay, because Triangle may be forced to stop adding
+        points when the mesh is in a state where a segment is non-Delaunay
+        and needs to be split.  If so, Triangle will print a warning.
+    -i  Uses an incremental rather than divide-and-conquer algorithm to
+        form a Delaunay triangulation.  Try it if the divide-and-conquer
+        algorithm fails.
+    -F  Uses Steven Fortune's sweepline algorithm to form a Delaunay
+        triangulation.  Warning:  does not use exact arithmetic for all
+        calculations.  An exact result is not guaranteed.
+    -l  Uses only vertical cuts in the divide-and-conquer algorithm.  By
+        default, Triangle uses alternating vertical and horizontal cuts,
+        which usually improve the speed except with point sets that are
+        small or short and wide.  This switch is primarily of theoretical
+        interest.
+    -s  Specifies that segments should be forced into the triangulation by
+        recursively splitting them at their midpoints, rather than by
+        generating a constrained Delaunay triangulation.  Segment splitting
+        is true to Ruppert's original algorithm, but can create needlessly
+        small triangles near external small features.
+    -C  Check the consistency of the final mesh.  Uses exact arithmetic for
+        checking, even if the -X switch is used.  Useful if you suspect
+        Triangle is buggy.
+    -Q  Quiet: Suppresses all explanation of what Triangle is doing, unless
+        an error occurs.
+    -V  Verbose: Gives detailed information about what Triangle is doing.
+        Add more `V's for increasing amount of detail.  `-V' gives
+        information on algorithmic progress and more detailed statistics.
+        `-VV' gives point-by-point details, and will print so much that
+        Triangle will run much more slowly.  `-VVV' gives information only
+        a debugger could love.
+    -h  Help:  Displays these instructions.
+
+Definitions:
+
+  A Delaunay triangulation of a point set is a triangulation whose vertices
+  are the point set, having the property that no point in the point set
+  falls in the interior of the circumcircle (circle that passes through all
+  three vertices) of any triangle in the triangulation.
+
+  A Voronoi diagram of a point set is a subdivision of the plane into
+  polygonal regions (some of which may be infinite), where each region is
+  the set of points in the plane that are closer to some input point than
+  to any other input point.  (The Voronoi diagram is the geometric dual of
+  the Delaunay triangulation.)
+
+  A Planar Straight Line Graph (PSLG) is a collection of points and
+  segments.  Segments are simply edges, whose endpoints are points in the
+  PSLG.  The file format for PSLGs (.poly files) is described below.
+
+  A constrained Delaunay triangulation of a PSLG is similar to a Delaunay
+  triangulation, but each PSLG segment is present as a single edge in the
+  triangulation.  (A constrained Delaunay triangulation is not truly a
+  Delaunay triangulation.)
+
+  A conforming Delaunay triangulation of a PSLG is a true Delaunay
+  triangulation in which each PSLG segment may have been subdivided into
+  several edges by the insertion of additional points.  These inserted
+  points are necessary to allow the segments to exist in the mesh while
+  maintaining the Delaunay property.
+
+File Formats:
+
+  All files may contain comments prefixed by the character '#'.  Points,
+  triangles, edges, holes, and maximum area constraints must be numbered
+  consecutively, starting from either 1 or 0.  Whichever you choose, all
+  input files must be consistent; if the nodes are numbered from 1, so must
+  be all other objects.  Triangle automatically detects your choice while
+  reading the .node (or .poly) file.  (When calling Triangle from another
+  program, use the -z switch if you wish to number objects from zero.)
+  Examples of these file formats are given below.
+
+  .node files:
+    First line:  <# of points> <dimension (must be 2)> <# of attributes>
+                                           <# of boundary markers (0 or 1)>
+    Remaining lines:  <point #> <x> <y> [attributes] [boundary marker]
+
+    The attributes, which are typically floating-point values of physical
+    quantities (such as mass or conductivity) associated with the nodes of
+    a finite element mesh, are copied unchanged to the output mesh.  If -s,
+    -q, or -a is selected, each new Steiner point added to the mesh will
+    have attributes assigned to it by linear interpolation.
+
+    If the fourth entry of the first line is `1', the last column of the
+    remainder of the file is assumed to contain boundary markers.  Boundary
+    markers are used to identify boundary points and points resting on PSLG
+    segments; a complete description appears in a section below.  The .node
+    file produced by Triangle will contain boundary markers in the last
+    column unless they are suppressed by the -B switch.
+
+  .ele files:
+    First line:  <# of triangles> <points per triangle> <# of attributes>
+    Remaining lines:  <triangle #> <point> <point> <point> ... [attributes]
+
+    Points are indices into the corresponding .node file.  The first three
+    points are the corners, and are listed in counterclockwise order around
+    each triangle.  (The remaining points, if any, depend on the type of
+    finite element used.)  The attributes are just like those of .node
+    files.  Because there is no simple mapping from input to output
+    triangles, an attempt is made to interpolate attributes, which may
+    result in a good deal of diffusion of attributes among nearby triangles
+    as the triangulation is refined.  Diffusion does not occur across
+    segments, so attributes used to identify segment-bounded regions remain
+    intact.  In output .ele files, all triangles have three points each
+    unless the -o2 switch is used, in which case they have six, and the
+    fourth, fifth, and sixth points lie on the midpoints of the edges
+    opposite the first, second, and third corners.
+
+  .poly files:
+    First line:  <# of points> <dimension (must be 2)> <# of attributes>
+                                           <# of boundary markers (0 or 1)>
+    Following lines:  <point #> <x> <y> [attributes] [boundary marker]
+    One line:  <# of segments> <# of boundary markers (0 or 1)>
+    Following lines:  <segment #> <endpoint> <endpoint> [boundary marker]
+    One line:  <# of holes>
+    Following lines:  <hole #> <x> <y>
+    Optional line:  <# of regional attributes and/or area constraints>
+    Optional following lines:  <constraint #> <x> <y> <attrib> <max area>
+
+    A .poly file represents a PSLG, as well as some additional information.
+    The first section lists all the points, and is identical to the format
+    of .node files.  <# of points> may be set to zero to indicate that the
+    points are listed in a separate .node file; .poly files produced by
+    Triangle always have this format.  This has the advantage that a point
+    set may easily be triangulated with or without segments.  (The same
+    effect can be achieved, albeit using more disk space, by making a copy
+    of the .poly file with the extension .node; all sections of the file
+    but the first are ignored.)
+
+    The second section lists the segments.  Segments are edges whose
+    presence in the triangulation is enforced.  Each segment is specified
+    by listing the indices of its two endpoints.  This means that you must
+    include its endpoints in the point list.  If -s, -q, and -a are not
+    selected, Triangle will produce a constrained Delaunay triangulation,
+    in which each segment appears as a single edge in the triangulation.
+    If -q or -a is selected, Triangle will produce a conforming Delaunay
+    triangulation, in which segments may be subdivided into smaller edges.
+    Each segment, like each point, may have a boundary marker.
+
+    The third section lists holes (and concavities, if -c is selected) in
+    the triangulation.  Holes are specified by identifying a point inside
+    each hole.  After the triangulation is formed, Triangle creates holes
+    by eating triangles, spreading out from each hole point until its
+    progress is blocked by PSLG segments; you must be careful to enclose
+    each hole in segments, or your whole triangulation may be eaten away.
+    If the two triangles abutting a segment are eaten, the segment itself
+    is also eaten.  Do not place a hole directly on a segment; if you do,
+    Triangle will choose one side of the segment arbitrarily.
+
+    The optional fourth section lists regional attributes (to be assigned
+    to all triangles in a region) and regional constraints on the maximum
+    triangle area.  Triangle will read this section only if the -A switch
+    is used or the -a switch is used without a number following it, and the
+    -r switch is not used.  Regional attributes and area constraints are
+    propagated in the same manner as holes; you specify a point for each
+    attribute and/or constraint, and the attribute and/or constraint will
+    affect the whole region (bounded by segments) containing the point.  If
+    two values are written on a line after the x and y coordinate, the
+    former is assumed to be a regional attribute (but will only be applied
+    if the -A switch is selected), and the latter is assumed to be a
+    regional area constraint (but will only be applied if the -a switch is
+    selected).  You may also specify just one value after the coordinates,
+    which can serve as both an attribute and an area constraint, depending
+    on the choice of switches.  If you are using the -A and -a switches
+    simultaneously and wish to assign an attribute to some region without
+    imposing an area constraint, use a negative maximum area.
+
+    When a triangulation is created from a .poly file, you must either
+    enclose the entire region to be triangulated in PSLG segments, or
+    use the -c switch, which encloses the convex hull of the input point
+    set.  If you do not use the -c switch, Triangle will eat all triangles
+    on the outer boundary that are not protected by segments; if you are
+    not careful, your whole triangulation may be eaten away.  If you do
+    use the -c switch, you can still produce concavities by appropriate
+    placement of holes just inside the convex hull.
+
+    An ideal PSLG has no intersecting segments, nor any points that lie
+    upon segments (except, of course, the endpoints of each segment.)  You
+    aren't required to make your .poly files ideal, but you should be aware
+    of what can go wrong.  Segment intersections are relatively safe -
+    Triangle will calculate the intersection points for you and add them to
+    the triangulation - as long as your machine's floating-point precision
+    doesn't become a problem.  You are tempting the fates if you have three
+    segments that cross at the same location, and expect Triangle to figure
+    out where the intersection point is.  Thanks to floating-point roundoff
+    error, Triangle will probably decide that the three segments intersect
+    at three different points, and you will find a minuscule triangle in
+    your output - unless Triangle tries to refine the tiny triangle, uses
+    up the last bit of machine precision, and fails to terminate at all.
+    You're better off putting the intersection point in the input files,
+    and manually breaking up each segment into two.  Similarly, if you
+    place a point at the middle of a segment, and hope that Triangle will
+    break up the segment at that point, you might get lucky.  On the other
+    hand, Triangle might decide that the point doesn't lie precisely on the
+    line, and you'll have a needle-sharp triangle in your output - or a lot
+    of tiny triangles if you're generating a quality mesh.
+
+    When Triangle reads a .poly file, it also writes a .poly file, which
+    includes all edges that are part of input segments.  If the -c switch
+    is used, the output .poly file will also include all of the edges on
+    the convex hull.  Hence, the output .poly file is useful for finding
+    edges associated with input segments and setting boundary conditions in
+    finite element simulations.  More importantly, you will need it if you
+    plan to refine the output mesh, and don't want segments to be missing
+    in later triangulations.
+
+  .area files:
+    First line:  <# of triangles>
+    Following lines:  <triangle #> <maximum area>
+
+    An .area file associates with each triangle a maximum area that is used
+    for mesh refinement.  As with other file formats, every triangle must
+    be represented, and they must be numbered consecutively.  A triangle
+    may be left unconstrained by assigning it a negative maximum area.
+
+  .edge files:
+    First line:  <# of edges> <# of boundary markers (0 or 1)>
+    Following lines:  <edge #> <endpoint> <endpoint> [boundary marker]
+
+    Endpoints are indices into the corresponding .node file.  Triangle can
+    produce .edge files (use the -e switch), but cannot read them.  The
+    optional column of boundary markers is suppressed by the -B switch.
+
+    In Voronoi diagrams, one also finds a special kind of edge that is an
+    infinite ray with only one endpoint.  For these edges, a different
+    format is used:
+
+        <edge #> <endpoint> -1 <direction x> <direction y>
+
+    The `direction' is a floating-point vector that indicates the direction
+    of the infinite ray.
+
+  .neigh files:
+    First line:  <# of triangles> <# of neighbors per triangle (always 3)>
+    Following lines:  <triangle #> <neighbor> <neighbor> <neighbor>
+
+    Neighbors are indices into the corresponding .ele file.  An index of -1
+    indicates a mesh boundary, and therefore no neighbor.  Triangle can
+    produce .neigh files (use the -n switch), but cannot read them.
+
+    The first neighbor of triangle i is opposite the first corner of
+    triangle i, and so on.
+
+Boundary Markers:
+
+  Boundary markers are tags used mainly to identify which output points and
+  edges are associated with which PSLG segment, and to identify which
+  points and edges occur on a boundary of the triangulation.  A common use
+  is to determine where boundary conditions should be applied to a finite
+  element mesh.  You can prevent boundary markers from being written into
+  files produced by Triangle by using the -B switch.
+
+  The boundary marker associated with each segment in an output .poly file
+  or edge in an output .edge file is chosen as follows:
+    - If an output edge is part or all of a PSLG segment with a nonzero
+      boundary marker, then the edge is assigned the same marker.
+    - Otherwise, if the edge occurs on a boundary of the triangulation
+      (including boundaries of holes), then the edge is assigned the marker
+      one (1).
+    - Otherwise, the edge is assigned the marker zero (0).
+  The boundary marker associated with each point in an output .node file is
+  chosen as follows:
+    - If a point is assigned a nonzero boundary marker in the input file,
+      then it is assigned the same marker in the output .node file.
+    - Otherwise, if the point lies on a PSLG segment (including the
+      segment's endpoints) with a nonzero boundary marker, then the point
+      is assigned the same marker.  If the point lies on several such
+      segments, one of the markers is chosen arbitrarily.
+    - Otherwise, if the point occurs on a boundary of the triangulation,
+      then the point is assigned the marker one (1).
+    - Otherwise, the point is assigned the marker zero (0).
+
+  If you want Triangle to determine for you which points and edges are on
+  the boundary, assign them the boundary marker zero (or use no markers at
+  all) in your input files.  Alternatively, you can mark some of them and
+  leave others marked zero, allowing Triangle to label them.
+
+Triangulation Iteration Numbers:
+
+  Because Triangle can read and refine its own triangulations, input
+  and output files have iteration numbers.  For instance, Triangle might
+  read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the
+  triangulation, and output the files mesh.4.node, mesh.4.ele, and
+  mesh.4.poly.  Files with no iteration number are treated as if
+  their iteration number is zero; hence, Triangle might read the file
+  points.node, triangulate it, and produce the files points.1.node and
+  points.1.ele.
+
+  Iteration numbers allow you to create a sequence of successively finer
+  meshes suitable for multigrid methods.  They also allow you to produce a
+  sequence of meshes using error estimate-driven mesh refinement.
+
+  If you're not using refinement or quality meshing, and you don't like
+  iteration numbers, use the -I switch to disable them.  This switch will
+  also disable output of .node and .poly files to prevent your input files
+  from being overwritten.  (If the input is a .poly file that contains its
+  own points, a .node file will be written.)
+
+Examples of How to Use Triangle:
+
+  `triangle dots' will read points from dots.node, and write their Delaunay
+  triangulation to dots.1.node and dots.1.ele.  (dots.1.node will be
+  identical to dots.node.)  `triangle -I dots' writes the triangulation to
+  dots.ele instead.  (No additional .node file is needed, so none is
+  written.)
+
+  `triangle -pe object.1' will read a PSLG from object.1.poly (and possibly
+  object.1.node, if the points are omitted from object.1.poly) and write
+  their constrained Delaunay triangulation to object.2.node and
+  object.2.ele.  The segments will be copied to object.2.poly, and all
+  edges will be written to object.2.edge.
+
+  `triangle -pq31.5a.1 object' will read a PSLG from object.poly (and
+  possibly object.node), generate a mesh whose angles are all greater than
+  31.5 degrees and whose triangles all have area smaller than 0.1, and
+  write the mesh to object.1.node and object.1.ele.  Each segment may have
+  been broken up into multiple edges; the resulting constrained edges are
+  written to object.1.poly.
+
+  Here is a sample file `box.poly' describing a square with a square hole:
+
+    # A box with eight points in 2D, no attributes, one boundary marker.
+    8 2 0 1
+    # Outer box has these vertices:
+     1   0 0   0
+     2   0 3   0
+     3   3 0   0
+     4   3 3   33     # A special marker for this point.
+    # Inner square has these vertices:
+     5   1 1   0
+     6   1 2   0
+     7   2 1   0
+     8   2 2   0
+    # Five segments with boundary markers.
+    5 1
+     1   1 2   5      # Left side of outer box.
+     2   5 7   0      # Segments 2 through 5 enclose the hole.
+     3   7 8   0
+     4   8 6   10
+     5   6 5   0
+    # One hole in the middle of the inner square.
+    1
+     1   1.5 1.5
+
+  Note that some segments are missing from the outer square, so one must
+  use the `-c' switch.  After `triangle -pqc box.poly', here is the output
+  file `box.1.node', with twelve points.  The last four points were added
+  to meet the angle constraint.  Points 1, 2, and 9 have markers from
+  segment 1.  Points 6 and 8 have markers from segment 4.  All the other
+  points but 4 have been marked to indicate that they lie on a boundary.
+
+    12  2  0  1
+       1    0   0      5
+       2    0   3      5
+       3    3   0      1
+       4    3   3     33
+       5    1   1      1
+       6    1   2     10
+       7    2   1      1
+       8    2   2     10
+       9    0   1.5    5
+      10    1.5   0    1
+      11    3   1.5    1
+      12    1.5   3    1
+    # Generated by triangle -pqc box.poly
+
+  Here is the output file `box.1.ele', with twelve triangles.
+
+    12  3  0
+       1     5   6   9
+       2    10   3   7
+       3     6   8  12
+       4     9   1   5
+       5     6   2   9
+       6     7   3  11
+       7    11   4   8
+       8     7   5  10
+       9    12   2   6
+      10     8   7  11
+      11     5   1  10
+      12     8   4  12
+    # Generated by triangle -pqc box.poly
+
+  Here is the output file `box.1.poly'.  Note that segments have been added
+  to represent the convex hull, and some segments have been split by newly
+  added points.  Note also that <# of points> is set to zero to indicate
+  that the points should be read from the .node file.
+
+    0  2  0  1
+    12  1
+       1     1   9     5
+       2     5   7     1
+       3     8   7     1
+       4     6   8    10
+       5     5   6     1
+       6     3  10     1
+       7     4  11     1
+       8     2  12     1
+       9     9   2     5
+      10    10   1     1
+      11    11   3     1
+      12    12   4     1
+    1
+       1   1.5 1.5
+    # Generated by triangle -pqc box.poly
+
+Refinement and Area Constraints:
+
+  The -r switch causes a mesh (.node and .ele files) to be read and
+  refined.  If the -p switch is also used, a .poly file is read and used to
+  specify edges that are constrained and cannot be eliminated (although
+  they can be divided into smaller edges) by the refinement process.
+
+  When you refine a mesh, you generally want to impose tighter quality
+  constraints.  One way to accomplish this is to use -q with a larger
+  angle, or -a followed by a smaller area than you used to generate the
+  mesh you are refining.  Another way to do this is to create an .area
+  file, which specifies a maximum area for each triangle, and use the -a
+  switch (without a number following).  Each triangle's area constraint is
+  applied to that triangle.  Area constraints tend to diffuse as the mesh
+  is refined, so if there are large variations in area constraint between
+  adjacent triangles, you may not get the results you want.
+
+  If you are refining a mesh composed of linear (three-node) elements, the
+  output mesh will contain all the nodes present in the input mesh, in the
+  same order, with new nodes added at the end of the .node file.  However,
+  there is no guarantee that each output element is contained in a single
+  input element.  Often, output elements will overlap two input elements,
+  and input edges are not present in the output mesh.  Hence, a sequence of
+  refined meshes will form a hierarchy of nodes, but not a hierarchy of
+  elements.  If you a refining a mesh of higher-order elements, the
+  hierarchical property applies only to the nodes at the corners of an
+  element; other nodes may not be present in the refined mesh.
+
+  It is important to understand that maximum area constraints in .poly
+  files are handled differently from those in .area files.  A maximum area
+  in a .poly file applies to the whole (segment-bounded) region in which a
+  point falls, whereas a maximum area in an .area file applies to only one
+  triangle.  Area constraints in .poly files are used only when a mesh is
+  first generated, whereas area constraints in .area files are used only to
+  refine an existing mesh, and are typically based on a posteriori error
+  estimates resulting from a finite element simulation on that mesh.
+
+  `triangle -rq25 object.1' will read object.1.node and object.1.ele, then
+  refine the triangulation to enforce a 25 degree minimum angle, and then
+  write the refined triangulation to object.2.node and object.2.ele.
+
+  `triangle -rpaa6.2 z.3' will read z.3.node, z.3.ele, z.3.poly, and
+  z.3.area.  After reconstructing the mesh and its segments, Triangle will
+  refine the mesh so that no triangle has area greater than 6.2, and
+  furthermore the triangles satisfy the maximum area constraints in
+  z.3.area.  The output is written to z.4.node, z.4.ele, and z.4.poly.
+
+  The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1
+  x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,
+  suitable for multigrid.
+
+Convex Hulls and Mesh Boundaries:
+
+  If the input is a point set (rather than a PSLG), Triangle produces its
+  convex hull as a by-product in the output .poly file if you use the -c
+  switch.  There are faster algorithms for finding a two-dimensional convex
+  hull than triangulation, of course, but this one comes for free.  If the
+  input is an unconstrained mesh (you are using the -r switch but not the
+  -p switch), Triangle produces a list of its boundary edges (including
+  hole boundaries) as a by-product if you use the -c switch.
+
+Voronoi Diagrams:
+
+  The -v switch produces a Voronoi diagram, in files suffixed .v.node and
+  .v.edge.  For example, `triangle -v points' will read points.node,
+  produce its Delaunay triangulation in points.1.node and points.1.ele,
+  and produce its Voronoi diagram in points.1.v.node and points.1.v.edge.
+  The .v.node file contains a list of all Voronoi vertices, and the .v.edge
+  file contains a list of all Voronoi edges, some of which may be infinite
+  rays.  (The choice of filenames makes it easy to run the set of Voronoi
+  vertices through Triangle, if so desired.)
+
+  This implementation does not use exact arithmetic to compute the Voronoi
+  vertices, and does not check whether neighboring vertices are identical.
+  Be forewarned that if the Delaunay triangulation is degenerate or
+  near-degenerate, the Voronoi diagram may have duplicate points, crossing
+  edges, or infinite rays whose direction vector is zero.  Also, if you
+  generate a constrained (as opposed to conforming) Delaunay triangulation,
+  or if the triangulation has holes, the corresponding Voronoi diagram is
+  likely to have crossing edges and unlikely to make sense.
+
+Mesh Topology:
+
+  You may wish to know which triangles are adjacent to a certain Delaunay
+  edge in an .edge file, which Voronoi regions are adjacent to a certain
+  Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to
+  each other.  All of this information can be found by cross-referencing
+  output files with the recollection that the Delaunay triangulation and
+  the Voronoi diagrams are planar duals.
+
+  Specifically, edge i of an .edge file is the dual of Voronoi edge i of
+  the corresponding .v.edge file, and is rotated 90 degrees counterclock-
+  wise from the Voronoi edge.  Triangle j of an .ele file is the dual of
+  vertex j of the corresponding .v.node file; and Voronoi region k is the
+  dual of point k of the corresponding .node file.
+
+  Hence, to find the triangles adjacent to a Delaunay edge, look at the
+  vertices of the corresponding Voronoi edge; their dual triangles are on
+  the left and right of the Delaunay edge, respectively.  To find the
+  Voronoi regions adjacent to a Voronoi edge, look at the endpoints of the
+  corresponding Delaunay edge; their dual regions are on the right and left
+  of the Voronoi edge, respectively.  To find which Voronoi regions are
+  adjacent to each other, just read the list of Delaunay edges.
+
+Statistics:
+
+  After generating a mesh, Triangle prints a count of the number of points,
+  triangles, edges, boundary edges, and segments in the output mesh.  If
+  you've forgotten the statistics for an existing mesh, the -rNEP switches
+  (or -rpNEP if you've got a .poly file for the existing mesh) will
+  regenerate these statistics without writing any output.
+
+  The -V switch produces extended statistics, including a rough estimate
+  of memory use and a histogram of triangle aspect ratios and angles in the
+  mesh.
+
+Exact Arithmetic:
+
+  Triangle uses adaptive exact arithmetic to perform what computational
+  geometers call the `orientation' and `incircle' tests.  If the floating-
+  point arithmetic of your machine conforms to the IEEE 754 standard (as
+  most workstations do), and does not use extended precision internal
+  registers, then your output is guaranteed to be an absolutely true
+  Delaunay or conforming Delaunay triangulation, roundoff error
+  notwithstanding.  The word `adaptive' implies that these arithmetic
+  routines compute the result only to the precision necessary to guarantee
+  correctness, so they are usually nearly as fast as their approximate
+  counterparts.  The exact tests can be disabled with the -X switch.  On
+  most inputs, this switch will reduce the computation time by about eight
+  percent - it's not worth the risk.  There are rare difficult inputs
+  (having many collinear and cocircular points), however, for which the
+  difference could be a factor of two.  These are precisely the inputs most
+  likely to cause errors if you use the -X switch.
+
+  Unfortunately, these routines don't solve every numerical problem.  Exact
+  arithmetic is not used to compute the positions of points, because the
+  bit complexity of point coordinates would grow without bound.  Hence,
+  segment intersections aren't computed exactly; in very unusual cases,
+  roundoff error in computing an intersection point might actually lead to
+  an inverted triangle and an invalid triangulation.  (This is one reason
+  to compute your own intersection points in your .poly files.)  Similarly,
+  exact arithmetic is not used to compute the vertices of the Voronoi
+  diagram.
+
+  Underflow and overflow can also cause difficulties; the exact arithmetic
+  routines do not ameliorate out-of-bounds exponents, which can arise
+  during the orientation and incircle tests.  As a rule of thumb, you
+  should ensure that your input values are within a range such that their
+  third powers can be taken without underflow or overflow.  Underflow can
+  silently prevent the tests from being performed exactly, while overflow
+  will typically cause a floating exception.
+
+Calling Triangle from Another Program:
+
+  Read the file triangle.h for details.
+
+Troubleshooting:
+
+  Please read this section before mailing me bugs.
+
+  `My output mesh has no triangles!'
+
+    If you're using a PSLG, you've probably failed to specify a proper set
+    of bounding segments, or forgotten to use the -c switch.  Or you may
+    have placed a hole badly.  To test these possibilities, try again with
+    the -c and -O switches.  Alternatively, all your input points may be
+    collinear, in which case you can hardly expect to triangulate them.
+
+  `Triangle doesn't terminate, or just crashes.'
+
+    Bad things can happen when triangles get so small that the distance
+    between their vertices isn't much larger than the precision of your
+    machine's arithmetic.  If you've compiled Triangle for single-precision
+    arithmetic, you might do better by recompiling it for double-precision.
+    Then again, you might just have to settle for more lenient constraints
+    on the minimum angle and the maximum area than you had planned.
+
+    You can minimize precision problems by ensuring that the origin lies
+    inside your point set, or even inside the densest part of your
+    mesh.  On the other hand, if you're triangulating an object whose x
+    coordinates all fall between 6247133 and 6247134, you're not leaving
+    much floating-point precision for Triangle to work with.
+
+    Precision problems can occur covertly if the input PSLG contains two
+    segments that meet (or intersect) at a very small angle, or if such an
+    angle is introduced by the -c switch, which may occur if a point lies
+    ever-so-slightly inside the convex hull, and is connected by a PSLG
+    segment to a point on the convex hull.  If you don't realize that a
+    small angle is being formed, you might never discover why Triangle is
+    crashing.  To check for this possibility, use the -S switch (with an
+    appropriate limit on the number of Steiner points, found by trial-and-
+    error) to stop Triangle early, and view the output .poly file with
+    Show Me (described below).  Look carefully for small angles between
+    segments; zoom in closely, as such segments might look like a single
+    segment from a distance.
+
+    If some of the input values are too large, Triangle may suffer a
+    floating exception due to overflow when attempting to perform an
+    orientation or incircle test.  (Read the section on exact arithmetic
+    above.)  Again, I recommend compiling Triangle for double (rather
+    than single) precision arithmetic.
+
+  `The numbering of the output points doesn't match the input points.'
+
+    You may have eaten some of your input points with a hole, or by placing
+    them outside the area enclosed by segments.
+
+  `Triangle executes without incident, but when I look at the resulting
+  mesh, it has overlapping triangles or other geometric inconsistencies.'
+
+    If you select the -X switch, Triangle's divide-and-conquer Delaunay
+    triangulation algorithm occasionally makes mistakes due to floating-
+    point roundoff error.  Although these errors are rare, don't use the -X
+    switch.  If you still have problems, please report the bug.
+
+  Strange things can happen if you've taken liberties with your PSLG.  Do
+  you have a point lying in the middle of a segment?  Triangle sometimes
+  copes poorly with that sort of thing.  Do you want to lay out a collinear
+  row of evenly spaced, segment-connected points?  Have you simply defined
+  one long segment connecting the leftmost point to the rightmost point,
+  and a bunch of points lying along it?  This method occasionally works,
+  especially with horizontal and vertical lines, but often it doesn't, and
+  you'll have to connect each adjacent pair of points with a separate
+  segment.  If you don't like it, tough.
+
+  Furthermore, if you have segments that intersect other than at their
+  endpoints, try not to let the intersections fall extremely close to PSLG
+  points or each other.
+
+  If you have problems refining a triangulation not produced by Triangle:
+  Are you sure the triangulation is geometrically valid?  Is it formatted
+  correctly for Triangle?  Are the triangles all listed so the first three
+  points are their corners in counterclockwise order?
+
+Show Me:
+
+  Triangle comes with a separate program named `Show Me', whose primary
+  purpose is to draw meshes on your screen or in PostScript.  Its secondary
+  purpose is to check the validity of your input files, and do so more
+  thoroughly than Triangle does.  Show Me requires that you have the X
+  Windows system.  If you didn't receive Show Me with Triangle, complain to
+  whomever you obtained Triangle from, then send me mail.
+
+Triangle on the Web:
+
+  To see an illustrated, updated version of these instructions, check out
+
+    http://www.cs.cmu.edu/~quake/triangle.html
+
+A Brief Plea:
+
+  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 in a publication, please include
+  an acknowledgment as well.
+
+Research credit:
+
+  Of course, I can take credit for only a fraction of the ideas that made
+  this mesh generator possible.  Triangle owes its existence to the efforts
+  of many fine computational geometers and other researchers, including
+  Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David
+  Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.
+  Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,
+  Isaac Saias, Bruce J. Schachter, Micha Sharir, Jorge Stolfi, Christopher
+  J. Van Wyk, David F. Watson, and Binhai Zhu.  See the comments at the
+  beginning of the source code for references.
+

From 8deb5c5804d7b4a09ffb727d050b63212636427d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 9 Apr 1998 01:58:04 +0000
Subject: [PATCH 055/283] Initial revision.

---
 Stripe_u/Makefile.am    |   29 +
 Stripe_u/Makefile.in    |  349 ++++++++
 Stripe_u/add.c          |  386 +++++++++
 Stripe_u/add.h          |   25 +
 Stripe_u/bands.c        |  549 +++++++++++++
 Stripe_u/common.c       |  811 +++++++++++++++++++
 Stripe_u/common.h       |   41 +
 Stripe_u/define.h       |   13 +
 Stripe_u/extend.h       |   17 +
 Stripe_u/free.c         |  110 +++
 Stripe_u/free.h         |   22 +
 Stripe_u/global.h       |   37 +
 Stripe_u/glove.h        |  151 ++++
 Stripe_u/init.c         |  217 +++++
 Stripe_u/init.h         |   30 +
 Stripe_u/local.c        |  123 +++
 Stripe_u/local.h        |   19 +
 Stripe_u/my_global.h    |    3 +
 Stripe_u/newpolve.c     | 1667 +++++++++++++++++++++++++++++++++++++++
 Stripe_u/options.c      |  181 +++++
 Stripe_u/options.h      |   17 +
 Stripe_u/output.c       |  582 ++++++++++++++
 Stripe_u/output.h       |   26 +
 Stripe_u/outputex.c     |  518 ++++++++++++
 Stripe_u/outputex.h     |   23 +
 Stripe_u/partial.c      |  665 ++++++++++++++++
 Stripe_u/partial.h      |   15 +
 Stripe_u/polverts.h     |   87 ++
 Stripe_u/polvertsex.h   |   34 +
 Stripe_u/queue.c        |  226 ++++++
 Stripe_u/queue.h        |  283 +++++++
 Stripe_u/sgi_triang.c   |  631 +++++++++++++++
 Stripe_u/sgi_triangex.c |  584 ++++++++++++++
 Stripe_u/struct.c       |  549 +++++++++++++
 Stripe_u/struct.h       |    6 +
 Stripe_u/structex.c     |  553 +++++++++++++
 Stripe_u/sturcts.h      |   31 +
 Stripe_u/sturctsex.h    |   28 +
 Stripe_u/ties.c         |  304 +++++++
 Stripe_u/ties.h         |   15 +
 Stripe_u/triangulate.h  |   23 +
 Stripe_u/triangulatex.h |   23 +
 Stripe_u/util.c         |  272 +++++++
 Stripe_u/util.h         |   24 +
 44 files changed, 10299 insertions(+)
 create mode 100644 Stripe_u/Makefile.am
 create mode 100644 Stripe_u/Makefile.in
 create mode 100644 Stripe_u/add.c
 create mode 100644 Stripe_u/add.h
 create mode 100644 Stripe_u/bands.c
 create mode 100644 Stripe_u/common.c
 create mode 100644 Stripe_u/common.h
 create mode 100644 Stripe_u/define.h
 create mode 100644 Stripe_u/extend.h
 create mode 100644 Stripe_u/free.c
 create mode 100644 Stripe_u/free.h
 create mode 100644 Stripe_u/global.h
 create mode 100644 Stripe_u/glove.h
 create mode 100644 Stripe_u/init.c
 create mode 100644 Stripe_u/init.h
 create mode 100644 Stripe_u/local.c
 create mode 100644 Stripe_u/local.h
 create mode 100644 Stripe_u/my_global.h
 create mode 100644 Stripe_u/newpolve.c
 create mode 100644 Stripe_u/options.c
 create mode 100644 Stripe_u/options.h
 create mode 100644 Stripe_u/output.c
 create mode 100644 Stripe_u/output.h
 create mode 100644 Stripe_u/outputex.c
 create mode 100644 Stripe_u/outputex.h
 create mode 100644 Stripe_u/partial.c
 create mode 100644 Stripe_u/partial.h
 create mode 100644 Stripe_u/polverts.h
 create mode 100644 Stripe_u/polvertsex.h
 create mode 100644 Stripe_u/queue.c
 create mode 100644 Stripe_u/queue.h
 create mode 100644 Stripe_u/sgi_triang.c
 create mode 100644 Stripe_u/sgi_triangex.c
 create mode 100644 Stripe_u/struct.c
 create mode 100644 Stripe_u/struct.h
 create mode 100644 Stripe_u/structex.c
 create mode 100644 Stripe_u/sturcts.h
 create mode 100644 Stripe_u/sturctsex.h
 create mode 100644 Stripe_u/ties.c
 create mode 100644 Stripe_u/ties.h
 create mode 100644 Stripe_u/triangulate.h
 create mode 100644 Stripe_u/triangulatex.h
 create mode 100644 Stripe_u/util.c
 create mode 100644 Stripe_u/util.h

diff --git a/Stripe_u/Makefile.am b/Stripe_u/Makefile.am
new file mode 100644
index 000000000..56308ad51
--- /dev/null
+++ b/Stripe_u/Makefile.am
@@ -0,0 +1,29 @@
+bin_PROGRAMS = strips
+
+strips_SOURCES = \
+	add.c add.h \
+	bands.c \
+	common.c common.h \
+	define.h \
+	extend.h \
+	free.c free.h \
+	global.h \
+	glove.h \
+	init.c init.h \
+	local.c local.h \
+	my_global.h \
+	newpolve.c \
+	options.c options.h \
+	output.c output.h \
+	outputex.c outputex.h \
+	partial.c partial.h \
+	polverts.h polvertsex.h \
+	queue.c queue.h \
+	sgi_triang.c sgi_triangex.c \
+	struct.c struct.h \
+	structex.c \
+	sturcts.h sturctsex.h \
+	ties.c ties.h \
+	triangulate.h triangulatex.h \
+	util.c util.h
+
diff --git a/Stripe_u/Makefile.in b/Stripe_u/Makefile.in
new file mode 100644
index 000000000..f012c211e
--- /dev/null
+++ b/Stripe_u/Makefile.in
@@ -0,0 +1,349 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = strips
+
+strips_SOURCES = \
+	add.c add.h \
+	bands.c \
+	common.c common.h \
+	define.h \
+	extend.h \
+	free.c free.h \
+	global.h \
+	glove.h \
+	init.c init.h \
+	local.c local.h \
+	my_global.h \
+	newpolve.c \
+	options.c options.h \
+	output.c output.h \
+	outputex.c outputex.h \
+	partial.c partial.h \
+	polverts.h polvertsex.h \
+	queue.c queue.h \
+	sgi_triang.c sgi_triangex.c \
+	struct.c struct.h \
+	structex.c \
+	sturcts.h sturctsex.h \
+	ties.c ties.h \
+	triangulate.h triangulatex.h \
+	util.c util.h
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+strips_OBJECTS =  add.o bands.o common.o free.o init.o local.o \
+newpolve.o options.o output.o outputex.o partial.o queue.o sgi_triang.o \
+sgi_triangex.o struct.o structex.o ties.o util.o
+strips_LDADD = $(LDADD)
+strips_DEPENDENCIES = 
+strips_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/add.P .deps/bands.P .deps/common.P .deps/free.P \
+.deps/init.P .deps/local.P .deps/newpolve.P .deps/options.P \
+.deps/output.P .deps/outputex.P .deps/partial.P .deps/queue.P \
+.deps/sgi_triang.P .deps/sgi_triangex.P .deps/struct.P .deps/structex.P \
+.deps/ties.P .deps/util.P
+SOURCES = $(strips_SOURCES)
+OBJECTS = $(strips_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Stripe_u/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+strips: $(strips_OBJECTS) $(strips_DEPENDENCIES)
+	@rm -f strips
+	$(LINK) $(strips_LDFLAGS) $(strips_OBJECTS) $(strips_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/Stripe_u
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Stripe_u/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Stripe_u/add.c b/Stripe_u/add.c
new file mode 100644
index 000000000..7d90357fd
--- /dev/null
+++ b/Stripe_u/add.c
@@ -0,0 +1,386 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: add.c
+     This file contains the procedure code that will add information
+     to our data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "global.h"
+#include "queue.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "ties.h"
+#include "outputex.h"
+#include "options.h"
+#include "local.h"
+
+BOOL new_vertex(double difference, int id1,int id2,
+                struct vert_struct *n)
+{
+     /*   Is the difference between id1 and id2 (2 normal vertices that
+          mapped to the same vertex) greater than the
+          threshold that was specified?
+     */
+     struct vert_struct *pn1,*pn2;
+     double dot_product;
+     double distance1, distance2,distance;
+     double rad;
+     char arg1[100];
+     char arg2[100];
+
+     pn1 = n + id1;
+     pn2 = n + id2;
+ 
+     dot_product = ((pn1->x) * (pn2->x)) +
+                   ((pn1->y) * (pn2->y)) +
+                   ((pn1->z) * (pn2->z));
+     /*   Get the absolute value */
+     if (dot_product < 0)
+          dot_product = dot_product * -1;
+
+     distance1 = sqrt( (pn1->x * pn1->x) +
+                       (pn1->y * pn1->y) +
+                       (pn1->z * pn1->z) );
+     distance2 = sqrt( (pn2->x * pn2->x) +
+                       (pn2->y * pn2->y) +
+                       (pn2->z * pn2->z) );
+     distance = distance1 * distance2;
+
+     rad = acos((double)dot_product/(double)distance);
+     /*   convert to degrees */
+     rad = (180 * rad)/PI;
+    
+     if ( rad <= difference)
+         return FALSE;
+     
+     /*   double checking because of imprecision with floating
+          point acos function
+     */
+     sprintf( arg1,"%.5f", rad );
+     sprintf( arg2,"%.5f", difference );
+     if ( strcmp( arg1, arg2 ) <=0 )
+          return( FALSE );
+     if ( rad <= difference)
+         return FALSE;
+     else 
+          return TRUE;
+}
+
+BOOL Check_VN(int vertex,int normal, struct vert_added *added)
+{
+     /*   Check to see if we already added this vertex and normal */
+     register int x,n;
+
+     n = (added+vertex)->num;
+     for (x = 0; x < n; x++)
+     {
+          if (*((added+vertex)->normal+x) == normal)
+               return TRUE;
+     }
+     return FALSE;
+}
+
+BOOL norm_array(int id, int vertex, double normal_difference,
+                struct vert_struct *n, int num_vert)
+{
+     static int last;
+     static struct vert_added *added;
+     register int x;
+     static BOOL first = TRUE;
+
+     if (first)
+     {
+          /*   This is the first time that we are in here, so we will allocate
+               a structure that will save the vertices that we added, so that we
+               do not add the same thing twice
+          */
+          first = FALSE;
+          added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert);
+          /*   The number of vertices added for each vertex must be initialized to
+               zero
+          */
+          for (x = 0; x < num_vert; x++)
+               (added+x)->num = 0;
+     }
+     
+     if (vertex)
+          /*   Set the pointer to the vertex, we will be calling again with the
+               normal to fill it with
+          */
+          last = id;
+     else
+     {    
+          /*   Fill the pointer with the id of the normal */
+          if (*(vert_norms + last) == 0)
+               *(vert_norms + last) = id;
+          else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360))
+          {
+               /*   difference is big enough, we need to create a new vertex */
+               if (new_vertex(normal_difference,id,*(vert_norms + last),n))
+               {
+                    /*   First check to see if we added this vertex and normal already */
+                    if (Check_VN(last,id,added))
+                         return FALSE;
+                    /*   OK, create the new vertex, and have its id = the number of vertices
+                         and its normal what we have here
+                    */
+                    vert_norms = realloc(vert_norms, sizeof(int) * (num_vert + 1));
+                    if (!vert_norms)
+                    {
+                         printf("Allocation error - aborting\n");
+                         exit(1);
+                    }
+                    *(vert_norms + num_vert) = id;
+                    /*   We created a new vertex, now put it in our added structure so
+                         we do not add the same thing twice
+                    */
+                    (added+last)->num = (added+last)->num + 1;
+                    if ((added+last)->num == 1)
+                    {
+                         /*   First time */
+                         (added+last)->normal =  (int *) malloc (sizeof (int ) * 1);
+                         *((added+last)->normal) =  id;
+                    }
+                    else
+                    {
+                         /*   Not the first time, reallocate space */
+                         (added+last)->normal = realloc((added+last)->normal,sizeof(int) * (added+last)->num);
+                         *((added+last)->normal+((added+last)->num-1)) = id;
+                    }
+                    return TRUE;
+               }
+          }
+     }
+     return FALSE;
+}
+
+void add_texture(int id,BOOL vertex)
+{
+     /*   Save the texture with its vertex for future use when outputting */
+     static int last;
+
+     if (vertex)
+          last = id;
+     else
+          *(vert_texture+last) = id;
+}
+
+int	add_vert_id(int id, int	index_count)
+{
+	register int x;
+     
+     /*   Test if degenerate, if so do not add degenerate vertex */
+     for (x = 1; x < index_count ; x++)
+     {
+          if (ids[x] == id)
+               return 0;
+     }
+     ids[index_count] = id;
+     return 1;
+}
+
+void	add_norm_id(int id, int index_count)
+{
+	norms[index_count] = id;
+}
+
+void AddNewFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1])
+{
+PF_FACES pfNode;
+int	*pTempInt;
+int *pnorms;
+F_EDGES **pTempVertptr;
+int	*pTempmarked, *pTempwalked;
+register int	y,count = 0,sum = 0;
+	
+	/*   Add a new face into our face data structure */
+
+     pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
+     if ( pfNode )
+     {
+          pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
+     	pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
+          pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); 
+		pfNode->marked  = (int*)malloc(sizeof(int) * (vert_count));
+		pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
+	}
+	pTempInt =pfNode->pPolygon;
+	pnorms = pfNode->pNorms;
+     pTempmarked = pfNode->marked;
+	pTempwalked = pfNode->walked;
+	pTempVertptr = pfNode->VertandId;
+	pfNode->nPolSize = vert_count;
+	pfNode->seen = -1;
+     pfNode->seen2 = -1;
+	for (y=1;y<=vert_count;y++)
+	{
+		*(pTempInt + count) = ids[y];
+		*(pnorms + count) = norms[y];
+          *(pTempmarked + count) = FALSE;
+		*(pTempwalked + count) =  -1;
+		*(pTempVertptr+count) = NULL;
+		count++;
+	}
+        AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
+}	
+
+	
+void CopyFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1])
+{
+PF_FACES pfNode;
+int	*pTempInt;
+int *pnorms;
+F_EDGES **pTempVertptr;
+int	*pTempmarked, *pTempwalked;
+register int	y,count = 0,sum = 0;
+	
+	/*   Copy a face node into a new node, used after the global algorithm
+          is run, so that we can save whatever is left into a new structure
+     */
+     
+     pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
+     if ( pfNode )
+     {
+          pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
+     	pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
+          pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); 
+		pfNode->marked  = (int*)malloc(sizeof(int) * (vert_count));
+		pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
+	}
+	pTempInt =pfNode->pPolygon;
+	pnorms = pfNode->pNorms;
+     pTempmarked = pfNode->marked;
+	pTempwalked = pfNode->walked;
+	pTempVertptr = pfNode->VertandId;
+	pfNode->nPolSize = vert_count;
+	pfNode->seen = -1;
+     pfNode->seen2 = -1;
+	for (y=0;y<vert_count;y++)
+	{
+		*(pTempInt + count) = ids[y];
+		*(pnorms + count) = norms[y];
+          *(pTempmarked + count) = FALSE;
+		*(pTempwalked + count) =  -1;
+		*(pTempVertptr+count) = NULL;
+		count++;
+	}
+	AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
+}	
+	
+void Add_Edge(int v1,int v2)
+{
+PF_EDGES temp  = NULL;
+ListHead *pListHead;
+BOOL flag = TRUE;
+register int t,count = 0;
+	
+	/*   Add a new edge into the edge data structure */
+     if (v1 > v2)
+	{
+		t  = v1;
+		v1 = v2;
+		v2 = t;
+	}
+	
+     pListHead = PolEdges[v1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+	if (temp == NULL)
+     {
+          printf("Have the wrong edge \n:");
+          exit(1);
+     }
+	
+	while (flag)
+	{
+		if (v2 == temp->edge[0])
+               return;
+          else
+             	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,++count);
+
+	}                	
+}
+
+void Add_AdjEdge(int v1,int v2,int fnum,int index1 )
+{
+     PF_EDGES temp  = NULL;
+     PF_FACES temp2 = NULL;
+     PF_EDGES pfNode;
+     ListHead *pListHead;
+     ListHead *pListFace;
+     BOOL 	flag = TRUE;
+     register int	count = 0;
+     register int	t,v3 = -1;
+	
+	if (v1 > v2)
+	{
+		t  = v1;
+		v1 = v2;
+		v2 = t;
+	}
+	pListFace  = PolFaces[fnum];
+	temp2 = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+	pListHead = PolEdges[v1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+	if (temp == NULL)
+		flag = FALSE;
+	count++;
+	while (flag)
+	{
+		if (v2 == temp->edge[0])
+		{
+               /*   If greater than 2 polygons adjacent to an edge, then we will
+                    only save the first 2 that we found. We will have a small performance
+                    hit, but this does not happen often.
+               */
+               if (temp->edge[2] == -1)
+                    temp->edge[2] = fnum;
+               else
+                    v3 = temp->edge[2];
+			flag = FALSE;
+		}
+		else
+		{
+			temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+			count++;
+			if (temp == NULL)
+				flag = FALSE;
+		}
+	}
+                
+	/*   Did not find it */
+     if (temp == NULL)
+	{
+		pfNode = (PF_EDGES) malloc(sizeof(F_EDGES) );
+          if ( pfNode )
+          {
+               pfNode->edge[0] = v2;
+			pfNode->edge[1] = fnum;
+	          pfNode->edge[2] =  v3;
+			AddTail( PolEdges[v1], (PLISTINFO) pfNode );
+          }
+		else
+          {
+               printf("Out of memory!\n");
+               exit(1);
+          }
+		
+          *(temp2->VertandId+index1) = pfNode;
+	}
+	else
+		*(temp2->VertandId+index1) =  temp;
+		
+}
+
+
diff --git a/Stripe_u/add.h b/Stripe_u/add.h
new file mode 100644
index 000000000..607363e5e
--- /dev/null
+++ b/Stripe_u/add.h
@@ -0,0 +1,25 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: add.h
+-----------------------------------------------------------------------*/
+
+BOOL new_vertex();
+BOOL Check_VN();
+BOOL norm_array();
+void add_texture();
+int	add_vert_id();
+void	add_norm_id();
+void AddNewFace();
+void CopyFace();
+void Add_Edge();
+void Add_AdjEdge();
+
+
+
diff --git a/Stripe_u/bands.c b/Stripe_u/bands.c
new file mode 100644
index 000000000..14a9fe4c0
--- /dev/null
+++ b/Stripe_u/bands.c
@@ -0,0 +1,549 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: bands.c
+     This file contains the main procedure code that will read in the
+     object and then call the routines that produce the triangle strips.
+*/
+/*---------------------------------------------------------------------*/
+
+  
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "global.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "ties.h"
+#include "outputex.h"
+#include "options.h"
+#include "local.h"
+#include "init.h"
+#include "free.h"
+#include "add.h"
+
+#define MAX1 60
+/*   TIMING for Windows */
+#ifdef WIN32
+#include <sys/timeb.h>
+#include <time.h>
+/*   TIMING for UNIX */
+#else
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/times.h>
+#include        <sys/time.h>
+struct timeval   tm;
+struct timezone  tz;
+double           et;
+#define START gettimeofday(&tm,&tz);\
+                et = (tm.tv_sec)+ (0.000001* (tm.tv_usec));
+
+#define STOP gettimeofday(&tm,&tz);\
+                et = (tm.tv_sec)+(0.000001*(tm.tv_usec)) - et;
+#endif
+
+
+void get_time()
+{
+     /*   For timing */
+     #ifdef WIN32
+          struct _timeb timebuffer;
+          char *timeline;
+     #else
+          long timer;
+     #endif
+
+
+     #ifdef WIN32
+          _ftime( &timebuffer );
+          timeline = ctime( & ( timebuffer.time ) );
+          printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );
+     #else
+            printf("Time for last frame  = %lf seconds\n", et);
+     #endif
+}
+
+/*
+** 
+     Here the main program begins. It will start by loading in a .obj file
+     then it will convert the polygonal model into triangle strips.
+**  
+*/
+
+void main (int argc,char *argv[])
+{
+	char	*fname,*all,buff[255], *ptr, *ptr2;
+	FILE	*file, *bands;
+	int face_id=0, vert_count, loop, num=0,num2;
+	float center[3];
+     int temp[MAX1],vertex,strips, swaps,tempi,cost,triangles;
+     int f,t,tr,g;
+     char *file_open;
+	int	num_vert	= 0,
+		num_faces	= 0,
+		num_nvert	= 0,
+		num_edges	= 0,
+          num_texture = 0,
+          num_tris = 0;
+     double fra = 0.0;
+     BOOL texture, normal, normal_and_texture,quads = FALSE;
+
+     /*   Options variables */
+     float norm_difference;
+
+	/*   Structures for the object */
+     struct vert_struct	*vertices	= NULL,
+				*nvertices	= NULL,
+				*pvertices	= NULL,
+				*pnvertices	= NULL;
+
+     get_time();
+     START
+
+     /*   File that will contain the triangle strip data */
+     bands = fopen("bands.d","w");
+
+     /*
+	     Scan the file once to find out the number of vertices,
+	     vertice normals, and faces so we can set up some memory
+	     structures 
+	*/
+	/* Interpret the options specified */
+	norm_difference = get_options(argc,argv,&f,&t,&tr,&g);
+     if (f == BINARY)
+          file_open = "rb";
+     else
+          file_open = "r";
+
+	fname = argv[argc-1];
+     printf ("File: %s\n",fname);
+	/*printf ("Scanning...%s ",file_open);*/
+
+	    
+     /*   File can be in binary for faster reading */
+     if (file = fopen (fname,file_open))
+	{
+		while (!feof (file))
+		{
+			/*   Read a line */
+               if (f == BINARY)
+                    fread (buff,sizeof(char) * 255,1, file);
+			else
+                    fgets (buff, sizeof(char) * 255, file);
+          	num++;
+               /*   At a vertex */
+               if (*buff == 'v')
+			{
+				/*   At a normal */
+                    if (*(buff+1)=='n')
+					num_nvert++;
+				else if (*(buff+1)=='t')
+                         num_texture++;
+                    /*   At a regular vertex */
+                    else
+					num_vert++;
+			}
+			/*   At a face */
+               else if (*buff == 'f')
+			{  
+                    num_faces++;
+			     strtok(buff, " ");
+			     tempi = 0;
+			     while (strtok(NULL, " ") != NULL) tempi++;
+			     num_tris += tempi - 2;
+               }
+		}
+		fclose (file);
+	}
+
+	else
+     {
+		printf("Error in the file name\n");
+          exit(1);
+     }
+	
+	
+	/* Allocate structures for the information */
+	Start_Face_Struct(num_faces);
+	vertices = (struct vert_struct *)
+			malloc (sizeof (struct vert_struct) * num_vert);
+
+	if (num_nvert > 0) 
+     {
+          nvertices = (struct vert_struct *)
+			malloc (sizeof (struct vert_struct) * num_nvert);
+          vert_norms = (int *) 
+               malloc (sizeof (int) * num_vert);
+          /*   Initialize entries to zero, in case there are 2 hits
+               to the same vertex we will know it - used for determining
+               the normal difference
+          */
+          init_vert_norms(num_vert);
+     }
+	else 
+		nvertices = NULL;
+
+     if (num_texture > 0)
+     {
+          vert_texture = (int *) malloc (sizeof(int) * num_vert);
+          init_vert_texture(num_vert);
+     }
+     
+	/*   Set up the temporary 'p' pointers 
+     */
+	pvertices = vertices;
+	pnvertices = nvertices;
+
+	/* Load the object into memory */
+	/*printf (" Loading...");*/
+ 
+     fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname);
+ 
+     /*  File will be put in a list for faster execution if file is in binary */   
+     if (file = fopen(fname,file_open))
+     {
+          if (f == BINARY)
+          {
+               all = (char *) malloc (sizeof(char) * 255 * num);
+               fread(all,sizeof(char) * 255 * num, 1, file);
+          	ptr = all;
+          }
+          else
+               ptr = (char *) malloc (sizeof(char) * 255 * num);
+     }
+
+   
+     while (num > 0)
+	{
+          num--;
+		if (f == ASCII)
+               fgets (ptr, sizeof(char) * 255, file);
+          else
+               ptr = ptr + 255;
+
+          /* Load in vertices/normals */
+		if (*ptr == 'v')
+		{
+			if (*(ptr+1)=='n')
+			{
+				sscanf (ptr+3,"%lf%lf%lf",
+					&(pnvertices->x),
+					&(pnvertices->y),
+					&(pnvertices->z));
+	   			fprintf(bands,"vn %lf %lf %lf\n",
+					pnvertices->x,pnvertices->y,pnvertices->z); 
+     			++pnvertices;
+			}
+			else if (*(ptr+1)=='t')
+               {
+				sscanf (ptr+3,"%f%f%f",&center[0],&center[1],&center[2]);
+	   			fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]); 
+               }
+               else
+			{
+				sscanf (ptr+2,"%lf%lf%lf",
+					&(pvertices->x), 
+					&(pvertices->y), 
+					&(pvertices->z));
+     			fprintf(bands,"v %lf %lf %lf\n",
+					pvertices->x,pvertices->y,pvertices->z); 
+				++pvertices;
+               }
+		}
+		
+          else if (*ptr == 'f')
+		{
+			/* Read in faces */
+			num2 = 0;
+			face_id++;
+               ptr2 = ptr+1;
+               normal = FALSE; texture = FALSE, normal_and_texture = FALSE;
+               while (*ptr2)
+               {
+			   if (*ptr2 >='0' && *ptr2 <='9')
+			   {
+				num2++;
+				++ptr2;
+				while (*ptr2 && (*ptr2!=' ' && *ptr2!='/'))
+					ptr2++;
+                    /*   There are normals in this line */
+                    if (*ptr2 == '/')
+                    {
+                         if (*(ptr2+1) == '/')
+                              normal = TRUE;
+                         else
+                              texture = TRUE;
+			     }
+                    else if (*ptr2 == ' ')
+                    {
+                         if ((num2 == 3) && (texture))
+                              normal_and_texture = TRUE;
+                    }
+                  }
+			   else
+				   ++ptr2;
+			}
+
+               ptr2 = ptr+1;
+			
+               /* loop on the number of numbers in this line of face data 
+               */
+			vert_count = 0;
+								
+			for (loop=0;loop<num2;loop++)
+			{
+				/* skip the whitespace */
+				while (*ptr2<'0' || *ptr2>'9')
+                    {
+                         if (*ptr2 == '-')
+                              break;
+                         ptr2++;
+                    }
+				vertex = atoi(ptr2)-1;
+                    if (vertex < 0)
+                    {
+                         vertex = num_vert + vertex;
+                         *ptr2 = ' ';
+                         ptr2++;
+                    }
+                    /*   If there are either normals or textures with the vertices
+                         in this file, the data alternates so we must read it this way 
+                    */
+				if ( (normal) && (!normal_and_texture))
+				{
+					if (loop%2)
+                         {
+                              add_norm_id(vertex,vert_count);
+                              /*   Test here to see if we added a new vertex, since the
+                                   vertex has more than one normal and the 2 normals are greater
+                                   than the threshold specified
+                              */
+                              if (norm_array(vertex,0,norm_difference,nvertices,num_vert))
+                              {
+                                   /*   Add a new vertex and change the
+                                        id of the vertex that we just read to the id of the new
+                                        vertex that we just added
+                                   */
+                                   /*   Put it in the output file, note the added vertices will
+                                        be after the normals and separated from the rest of the 
+                                        vertices. Will not affect our viewer
+                                   */
+                                   fprintf(bands,"v %lf %lf %lf\n",
+                                          (vertices + temp[vert_count - 1])->x,
+                                          (vertices + temp[vert_count - 1])->y,
+                                          (vertices + temp[vert_count - 1])->z); 
+                                   num_vert++;
+                                   temp[vert_count - 1] = num_vert - 1;
+                                   if (!(add_vert_id(num_vert - 1,vert_count)))
+                                        vert_count--;
+                              }
+                         }
+					/*   the vertex */
+                         else 
+					{
+						temp[vert_count] = vertex ;
+						vert_count++;
+                              if (!(add_vert_id(vertex,vert_count)))
+                                   vert_count--;
+                              norm_array(vertex,1,norm_difference,nvertices,num_vert);
+					}
+                    }
+                         
+                    /*   Else there are vertices and textures with the data */
+                    else if (normal_and_texture)
+                    {
+                         if( !((loop+1)%3))
+                         {
+                              add_norm_id(vertex,vert_count);
+                              /*   Test here to see if we added a new vertex, since the
+                                   vertex has more than one normal and the 2 normals are greater
+                                   than the threshold specified
+                              */
+                              if (norm_array(vertex,0,norm_difference,nvertices,num_vert))
+                              {
+                                   /*   Add a new vertex and change the
+                                        id of the vertex that we just read to the id of the new
+                                        vertex that we just added
+                                   */
+                                   /*   Put it in the output file, note the added vertices will
+                                        be after the normals and separated from the rest of the 
+                                        vertices. Will not affect our viewer
+                                   */
+                                   fprintf(bands,"v %lf %lf %lf\n",
+                                          (vertices + temp[vert_count - 1])->x,
+                                          (vertices + temp[vert_count - 1])->y,
+                                          (vertices + temp[vert_count - 1])->z); 
+                                   num_vert++;
+                                   temp[vert_count - 1] = num_vert - 1;
+                                   if (!(add_vert_id(num_vert - 1,vert_count)))
+                                        vert_count--;
+                              }
+                         }
+                         /*   the vertex */
+                         else if ((loop == 0) || (*(ptr2-1) == ' '))
+					{
+						temp[vert_count] = vertex ;
+						vert_count++;
+                              if (vert_count == 4)
+                                   quads = TRUE;
+                              if (!(add_vert_id(vertex,vert_count)))
+                                   vert_count--;
+                              add_texture(vertex,TRUE);
+                              norm_array(vertex,1,norm_difference,nvertices,num_vert);
+					}
+                         else /*   The texture */
+                              add_texture(vertex,FALSE);
+                    }
+				
+ 				else if ( texture )
+				{
+					/*   the vertex */
+                         if (!(loop%2))
+					{
+						temp[vert_count] = vertex ;
+						vert_count++;
+                              if (vert_count == 4)
+                                   quads = TRUE;
+                              add_texture(vertex,TRUE);
+                              if (!(add_vert_id(vertex,vert_count)))
+                                   vert_count--;
+                              norm_array(vertex,1,norm_difference,nvertices,num_vert);
+					}
+                         else /*   texture */
+                              add_texture(vertex,FALSE);
+                    }
+ 
+                    else
+				{
+				    /*** no nvertices ***/
+					temp[vert_count] = vertex ;
+					vert_count++;
+                         if (vert_count == 4)
+                              quads = TRUE;
+                         if (!(add_vert_id(vertex,vert_count)))
+                              vert_count--;
+				}
+				while (*ptr2>='0' && *ptr2<='9')
+					ptr2++;
+               }
+			/* Done with the polygon */
+			num_edges += vert_count;
+			/* add it to face structure */
+			if (vert_count >= 3)
+                    AddNewFace(ids,vert_count,face_id,norms);
+               else
+                    face_id--;
+               if (vert_count == 4)
+                    quads = TRUE;
+          }
+          else if ((g == TRUE) && (face_id > 0)
+                      && ((*ptr == 'g') || (*ptr  == 's') || (*ptr == 'm') || (*ptr == 'o')))
+          {
+               /*   The user specified that the strips will be contained in each group
+                    from the data file, so we just finished a group and will find the
+                    triangle strips in it.
+               */
+               Start_Edge_Struct(num_vert);
+	          Find_Adjacencies(face_id);
+	          if (quads)
+               {
+     	          Init_Table_SGI();
+	               Build_SGI_Table(num_vert,face_id);
+                    /* Code for lengths of walks in each direction */
+	               Save_Walks(face_id,TRUE);
+	
+                    /* Code for finding the bands */
+	               Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
+
+                    /*  Remove the faces that we did  so that we can
+                         run the strip code on the rest of the faces that are left
+                    */
+                    if (cost != 0)
+                    {
+                         printf("Total %d triangles with %d cost\n",triangles,cost);
+                         Save_Rest(&face_id);
+                         printf("We saved %d .... now doing the local algorithm\n",face_id);
+                         fprintf(bands,"\n#local\n");
+	                    End_Edge_Struct(num_vert);
+                         Start_Edge_Struct(num_vert);
+	                    Find_Adjacencies(face_id);
+                    }
+              }
+	     
+          	SGI_Strip(num_vert,face_id,bands,t,tr);
+
+               /*   Get the total cost */
+               Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
+
+               End_Face_Struct(num_faces);
+               End_Edge_Struct(num_vert);
+               cost = 0;
+               face_id = 0;
+               quads = FALSE;
+              	Start_Face_Struct(num_faces-face_id);
+               num_faces = num_faces - face_id;
+               Free_Strips();
+          }
+}
+               
+     /*   Done reading in all the information into data structures */
+     num_faces = face_id;
+     fclose (file);
+	/*printf(" Done.\n\n");*/
+     free(vertices);
+     free(nvertices);
+
+	/*printf ("Vertices:	%d\nNormals:	%d\nFaces:		%d\n",num_vert,num_nvert,num_faces);*/
+	Start_Edge_Struct(num_vert);
+	Find_Adjacencies(num_faces);
+
+     /*	Initialize it */
+	Init_Table_SGI();
+	/*	Build it */
+	Build_SGI_Table(num_vert,num_faces);
+
+     InitStripTable();
+
+	
+	if (quads)
+     {
+          /* Code for lengths of walks in each direction */
+	     Save_Walks(num_faces,TRUE);
+	
+          /* Code for finding the bands */
+	     Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
+          /*printf("Total %d triangles with %d cost\n",triangles,cost);*/
+
+          /*  Remove the faces that we did  so that we can
+               run the strip code on the rest of the faces that are left
+          */
+          Save_Rest(&num_faces);
+          /*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/
+          fprintf(bands,"\n#local\n");
+	     End_Edge_Struct(num_vert);
+          Start_Edge_Struct(num_vert);
+	     Find_Adjacencies(num_faces);
+     }
+	     
+	SGI_Strip(num_vert,num_faces,bands,t,tr);
+
+     /*   Get the total cost */
+     Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
+
+     End_Face_Struct(num_faces);
+     End_Edge_Struct(num_vert);
+     fclose(bands);
+     STOP
+
+     get_time();
+
+}
+
diff --git a/Stripe_u/common.c b/Stripe_u/common.c
new file mode 100644
index 000000000..6e553f149
--- /dev/null
+++ b/Stripe_u/common.c
@@ -0,0 +1,811 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: common.c
+     This file contains common code used in both the local and global algorithm
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "extend.h"
+#include "output.h"
+#include "triangulate.h"
+#include "util.h"
+#include "add.h"
+
+int  Old_Adj(int face_id)
+{
+	/*	Find the bucket that the face_id is currently in,
+		because maybe we will be deleting it. 
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y;
+	
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	size = temp->nPolSize;
+	if (Done(face_id,size,&y) == NULL)
+	{
+		printf("There is an error in finding the face\n");
+		exit(0);
+	}
+	return y;
+}
+
+int Number_Adj(int id1, int id2, int curr_id)
+{
+	/*	Given edge whose endpoints are specified by id1 and id2,
+		determine how many polygons share this edge and return that
+		number minus one (since we do not want to include the polygon
+		that the caller has already).
+	*/
+
+	int size,y,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	BOOL there= FALSE;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	new edge that was created might not be here */
+		return 0;
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	This edge was not there in the original, which
+				mean that we created it in the partial triangulation.
+				So it is adjacent to nothing.
+			*/
+			return 0;
+	}
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return 0;
+	else
+	{
+		/*	It was adjacent to another polygon, but maybe we did this
+			polygon already, and it was done partially so that this edge
+			could have been done
+		*/
+		if (curr_id != temp->edge[1])
+		{
+			/*	Did we use this polygon already?and it was deleted
+				completely from the structure
+			*/
+			pListHead = PolFaces[temp->edge[1]];
+			temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+			if (Done(temp->edge[1],temp2->nPolSize,&size) == NULL)
+				return 0;
+		}
+		else
+		{
+			pListHead = PolFaces[temp->edge[2]];
+			temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+			if (Done(temp->edge[2],temp2->nPolSize,&size)== NULL)
+				return 0;
+		}
+
+		/*	Now we have to check whether it was partially done, before
+			we can say definitely if it is adjacent.
+			Check each edge of the face and tally the number of adjacent
+			polygons to this face. 
+		*/	      		
+		if ( temp2 != NULL )
+		{
+			/*	Size of the polygon */
+			size = temp2->nPolSize;
+			for (y = 0; y< size; y++)
+			{
+				/*	If we are doing partial triangulation, we must check
+					to see whether the edge is still there in the polygon,
+					since we might have done a portion of the polygon
+					and saved the rest for later.
+				*/
+				if (y != (size-1))
+				{
+					if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+						|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+						/*	edge is still there we are ok */
+						there = TRUE;
+				}
+				else
+				{
+					if( ((id1 == *(temp2->pPolygon)) && (id2 == *(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+						there = TRUE;
+				}
+			}
+		}
+		
+		if (there )
+			return 1;
+		return 0;
+	}
+}
+
+int Min_Adj(int id)
+{
+	/*	Used for the lookahead to break ties. It will
+		return the minimum adjacency found at this face.
+	*/
+	int y,numverts,t,x=60;
+	PF_FACES temp=NULL;
+	ListHead *pListHead;
+
+	/*	If polygon was used then we can't use this face */
+	if (Done(id,59,&y) == NULL)
+		return 60;
+		
+	/*	It was not used already */
+	pListHead = PolFaces[id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+     if ( temp != NULL )
+	{
+		numverts = temp->nPolSize;
+		for (y = 0; y< numverts; y++)
+		{
+			if (y != (numverts-1))
+				t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id);
+			else
+				t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id);
+			if (t < x)
+				x = t;
+		}
+	}
+	if (x == -1)
+	{
+		printf("Error in the look\n");
+		exit(0);
+	}
+	return x;
+}
+
+
+
+void Edge_Least(int *index,int *new1,int *new2,int face_id,int size)
+{
+    /*   We had a polygon without an input edge and now we re going to pick one
+         of the edges with the least number of adjacencies to be the input
+         edge
+    */
+    register int x,value,smallest=60;
+
+    for (x = 0; x<size; x++)
+    {
+        if (x != (size -1) )
+            value = Number_Adj(*(index+x),*(index+x+1),face_id);
+        else 
+            value = Number_Adj(*(index),*(index+size-1),face_id);
+        if (value < smallest)
+        {
+            smallest = value;
+            if (x != (size -1))
+            {
+                *new1 = *(index+x);
+                *new2 = *(index+x+1);
+            }
+            else
+            {
+                *new1 = *(index);
+                *new2 = *(index+size-1);
+            }
+        }
+    }
+    if ((smallest == 60) || (smallest < 0))
+    {
+        printf("There is an error in getting the least edge\n");
+        exit(0);
+    }
+}
+
+
+void Check_In_Polygon(int face_id, int *min, int size)
+{
+    /*  Check to see the adjacencies by going into a polygon that has
+        greater than 4 sides.
+    */
+    
+    ListHead *pListHead;
+    PF_FACES temp;
+    int y,id1,id2,id3,x=0,z=0;
+    int saved[2];
+    int big_saved[60];
+
+    pListHead = PolFaces[face_id];
+    temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+
+    /*   Get the input edge that we came in on */
+    Last_Edge(&id1,&id2,&id3,0);
+
+    /*  Find the number of adjacencies to the edges that are adjacent
+        to the input edge.
+    */
+    for (y=0; y< size; y++)
+    {
+        if (y != (size-1))
+        {
+            if (((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3))
+                || ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+                big_saved[z++] = saved[x-1];
+            }
+            else
+                big_saved[z++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+        }
+        else
+        {
+            if (((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) != id3))
+                || ((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+                big_saved[z++] = saved[x-1];
+            }
+            else
+                big_saved[z++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+        }
+    }
+    /*  There was an input edge */
+    if (x == 2)
+    {
+        if (saved[0] < saved[1])
+            /*  Count the polygon that we will be cutting as another adjacency*/
+            *min = saved[0] + 1;
+        else
+            *min = saved[1] + 1;
+    }
+    /*  There was not an input edge */
+    else
+    {
+        if (z != size)
+        {
+            printf("There is an error with the z %d %d\n",size,z);
+            exit(0);
+        }
+        *min = 60;
+        for (x = 0; x < size; x++)
+        {
+            if (*min > big_saved[x])
+                *min = big_saved[x];
+        }
+    }
+}
+
+
+void New_Face (int face_id, int v1, int v2, int v3)
+{
+	/*	We want to change the face that was face_id, we will
+		change it to a triangle, since the rest of the polygon
+		was already outputtted
+	*/
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	pListHead = PolFaces[face_id];
+     temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0);
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+	{
+		/*	Size of the polygon */
+		if (temp->nPolSize != 4)
+		{
+			printf("There is a miscalculation in the partial\n");
+			exit (0);
+		}
+		temp->nPolSize = 3;
+		*(temp->pPolygon) = v1;
+		*(temp->pPolygon+1) = v2;
+		*(temp->pPolygon+2) = v3;
+	}
+}
+
+void New_Size_Face (int face_id)
+{
+	/*	We want to change the face that was face_id, we will
+		change it to a triangle, since the rest of the polygon
+		was already outputtted
+	*/
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+		(temp->nPolSize)--;
+	else
+		printf("There is an error in updating the size\n");
+}
+
+
+
+void  Check_In_Quad(int face_id,int *min)
+{
+     /*   Check to see what the adjacencies are for the polygons that
+          are inside the quad, ie the 2 triangles that we can form.
+     */
+    ListHead *pListHead;
+    int y,id1,id2,id3,x=0;
+    int saved[4];
+    PF_FACES temp;
+    register int size = 4;
+
+    pListHead = PolFaces[face_id];
+    temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+     /*   Get the input edge that we came in on */
+    Last_Edge(&id1,&id2,&id3,0);
+	
+    /*    Now find the adjacencies for the inside triangles */
+    for (y = 0; y< size; y++)
+	{
+         /*     Will not do this if the edge is the input edge */
+         if (y != (size-1))
+         {
+              if ((((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) == id3))) ||
+             (((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) == id2))))
+                    saved[x++] = -1;
+              else
+              {
+                   if (x == 4)
+                   {
+                        printf("There is an error in the check in quad \n");
+                        exit(0);
+                   }
+                   /*    Save the number of Adjacent Polygons to this edge */
+                   saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+              }
+         }
+		else if ((((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) == id3))) ||
+             (((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) == id2))) )
+             saved[x++] = -1;
+        else
+        {
+               if (x == 4)
+               {
+                    printf("There is an error in the check in quad \n");
+                    exit(0);
+               }
+               /*    Save the number of Adjacent Polygons to this edge */
+               saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+
+        }
+    }
+    if (x != 4)
+    {
+         printf("Did not enter all the values %d \n",x);
+         exit(0);
+    }
+    
+    *min = 10;
+    for (x=0; x<4; x++)
+    {
+         if (x!= 3)
+         {
+              if ((saved[x] != -1) && (saved[x+1] != -1) && 
+                   ((saved[x] + saved[x+1]) < *min))
+                   *min = saved[x] + saved[x+1];
+         }
+         else
+         {
+              if ((saved[0] != -1) && (saved[x] != -1) &&
+                   ((saved[x] + saved[0]) < *min))
+                   *min = saved[0] + saved[x];
+         }
+    }
+}
+
+
+
+int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3)
+{
+    /*  Return the vertex adjacent to either input1 or input2 that
+        is adjacent to the least number of polygons on the edge that
+        is shared with either input1 or input2.
+    */
+    register int x=0,y;
+    int saved[2];
+    int edges[2][1];
+
+    for (y = 0; y < size; y++)
+    {
+        if (y != (size-1))
+        {
+            if (((*(index+y) == id2) && (*(index+y+1) != id3))
+                || ((*(index+y) == id3) && (*(index+y+1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id);
+                edges[x-1][0] = *(index+y+1);
+            }
+            else if (y != 0)
+            {
+                if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) ||
+                    ( (*(index+y) == id3) && (*(index+y-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id);
+                    edges[x-1][0] = *(index+y-1);
+                }
+            }
+            else if (y == 0)
+            {
+                if (( (*(index) == id2) && (*(index+size-1) != id3) ) ||
+                    ( (*(index) == id3) && (*(index+size-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
+                    edges[x-1][0] = *(index+size-1);
+                }
+            }
+
+        }
+        else
+        {
+            if (((*(index+size-1) == id2) && (*(index) != id3))
+                || ((*(index+size-1) == id3) && (*(index) != id2)))
+            {
+                saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
+                edges[x-1][0] = *(index);
+            }
+
+            if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) ||
+                    ( (*(index+size-1) == id3) && (*(index+y-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id);
+                    edges[x-1][0] = *(index+y-1);
+                }
+        }
+    }
+    if ((x != 2))
+    {
+        printf("There is an error in getting the input edge %d \n",x);
+        exit(0);
+    }
+    if (saved[0] < saved[1])
+        return edges[0][0];
+    else
+        return edges[1][0];
+
+}
+
+void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,int size,
+                    int face_id)
+{
+    /*  We had a polygon without an input edge and now we are going to pick one
+        as the input edge. The last triangle was id1,id2,id3, we will try to
+        get an edge to have something in common with one of those vertices, otherwise
+        we will pick the edge with the least number of adjacencies.
+    */
+
+    register int x;
+    int saved[3];
+
+    saved[0] = -1;
+    saved[1] = -1;
+    saved[2] = -1;
+    
+    /*  Go through the edges to see if there is one in common with one
+        of the vertices of the last triangle that we had, preferably id2 or
+        id3 since those are the last 2 things in the stack of size 2.
+    */
+    for (x=0; x< size; x++)
+    {
+        if (*(index+x) == id1)
+        {
+            if (x != (size-1))
+                saved[0] = *(index+x+1);
+            else
+                saved[0] = *(index);
+        }
+
+        if (*(index+x) == id2)
+        {
+            if (x != (size-1))
+                saved[1] = *(index+x+1);
+            else
+                saved[1] = *(index);
+        }
+        
+        if (*(index+x) == id3)
+        {
+            if (x != (size -1))
+                saved[2] = *(index+x+1);
+            else
+                saved[2] = *(index);
+        }
+    }
+    /*  Now see what we saved */
+    if (saved[2] != -1)
+    {
+        *new1 = id3;
+        *new2 = saved[2];
+        return;
+    }
+    else if (saved[1] != -1)
+    {
+        *new1 = id2;
+        *new2 = saved[1];
+        return;
+    }
+    else if (saved[0] != -1)
+    {
+        *new1 = id1;
+        *new2 = saved[0];
+        return;
+    }
+    /*  We did not find anything so get the edge with the least number of adjacencies */
+    Edge_Least(index,new1,new2,face_id,size);
+
+}
+
+int Find_Face(int current_face, int id1, int id2, int *bucket)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face.
+	*/
+	register int size,each_poly=0,y,tally=0,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	int next_face;
+	BOOL there = FALSE;
+
+    
+    /*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     /*  The input edge was a new edge */
+     if (temp == NULL)
+        return -1;
+        
+     while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          /*  The input edge was a new edge */
+          if (temp == NULL)
+            return -1;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return -1;
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. 
+	*/
+	pListHead = PolFaces[next_face];
+	temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+		
+     /*	See if the face was already deleted, and where
+              it is if it was not
+     */
+		
+     if (Done(next_face,59,bucket) == NULL)
+        return -1;
+
+     /*  Make sure the edge is still in this polygon, and that it is not
+         done
+     */
+		/*	Size of the polygon */
+		size = temp2->nPolSize;
+		for (y = 0; y< size; y++)
+		{
+			/*	Make sure that the edge is still in the
+				polygon and was not deleted, because if the edge was
+				deleted, then we used it already.
+			*/
+			if (y != (size-1))
+			{
+				if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+					|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{		
+				if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+		if (!there)
+			/*	Edge already used and deleted from the polygon*/
+			return -1;
+         else
+            return next_face;
+}
+
+BOOL Look_Up(int id1,int id2,int face_id)
+{
+	/*	See if the endpoints of the edge specified by id1 and id2
+		are adjacent to the face with face_id 
+	*/
+	register int count = 0;
+	PF_EDGES temp  = NULL;
+	ListHead *pListHead;
+	PF_FACES temp2 = NULL;
+	
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	Was a new edge that we created */
+		return 0;
+	
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	Was a new edge that we created */
+			return 0;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id))
+	{
+		/*	Edge was adjacent to face, make sure that edge is 
+			still there
+		*/
+		if (Exist(face_id,id1,id2))
+			return 1;
+		else
+			return 0;
+	}
+	else
+		return 0;
+}
+
+
+void Add_Id_Strips(int id, int where)
+{
+     /*    Just save the triangle for later  */
+     P_STRIPS pfNode;
+
+	pfNode = (P_STRIPS) malloc(sizeof(Strips) );
+	if ( pfNode )
+	{
+	     pfNode->face_id = id;
+	     if (where == 1)
+     		 AddTail(strips[0],(PLISTINFO) pfNode);
+	     /* We are backtracking in the strip */
+	     else
+		 AddHead(strips[0],(PLISTINFO) pfNode);
+	}
+	else
+	{
+	     printf("There is not enough memory to allocate for the strips\n");
+	     exit(0);
+	}
+}
+
+
+int Num_Adj(int id1, int id2)
+{
+	/*   Given edge whose endpoints are specified by id1 and id2,
+		determine how many polygons share this edge and return that
+		number minus one (since we do not want to include the polygon
+		that the caller has already).
+	*/
+
+	PF_EDGES temp = NULL;
+	ListHead *pListHead;
+	register count=-1;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+	{
+		printf("There is an error in the creation of the table \n");
+		exit(0);
+	}
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+	     if (temp == NULL)
+		{
+			printf("There is an error in the creation of the table\n");
+			exit(0);
+		}
+	}
+	/*      Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return 0;
+	return 1;
+}
+
+
+void Add_Sgi_Adj(int bucket,int face_id)
+{
+	/*   This routine will add the face to the proper bucket,
+		depending on how many faces are adjacent to it (what the
+		value bucket should be).
+	*/
+	P_ADJACENCIES pfNode;
+
+	pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+     if ( pfNode )
+     {
+		pfNode->face_id = face_id;
+	     AddHead(array[bucket],(PLISTINFO) pfNode);
+	}
+	else
+	{
+		printf("Out of memory for the SGI adj list!\n");
+		exit(0);
+	}
+}
+
+void Find_Adjacencies(int num_faces)
+{
+     register int	x,y;
+     register int	numverts;
+     PF_FACES temp=NULL;
+     ListHead *pListHead;
+
+	/*   Fill in the adjacencies data structure for all the faces */
+     for (x=0;x<num_faces;x++)
+	{
+        	pListHead = PolFaces[x];
+		temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+     	if ( temp != NULL )
+		{
+			numverts = temp->nPolSize;
+			if (numverts != 1)
+               {
+                    for (y = 0; y< numverts; y++)
+			     {
+				     if (y != (numverts-1))
+					     Add_AdjEdge(*(temp->pPolygon+y),*(temp->pPolygon+y+1),x,y);
+			
+				     else 
+					     Add_AdjEdge(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),x,numverts-1);
+			
+                    }
+               }
+			temp = NULL;
+		}
+	}
+}
+
+
diff --git a/Stripe_u/common.h b/Stripe_u/common.h
new file mode 100644
index 000000000..a220b3628
--- /dev/null
+++ b/Stripe_u/common.h
@@ -0,0 +1,41 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: common.h
+-----------------------------------------------------------------------*/
+
+void Add_AdjEdge();
+void Find_Adjacencies();
+void Add_Sgi_Adj();
+int Num_Adj();
+void Add_Id_Strips();
+BOOL Look_Up();
+int Number_Adj();
+int  Old_Adj();
+int Min_Adj();
+int Find_Face();
+void Edge_Least();
+void Get_Input_Edge();
+int Get_Output_Edge();
+void Check_In_Polygon();
+void  Check_In_Quad();
+void New_Size_Face ();
+void New_Face ();
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Stripe_u/define.h b/Stripe_u/define.h
new file mode 100644
index 000000000..931e5713f
--- /dev/null
+++ b/Stripe_u/define.h
@@ -0,0 +1,13 @@
+
+#define   VRDATA		double
+#define   MAX1            60
+	
+#define	TRUE	      	1
+#define	FALSE		0
+
+#define   PI	     	3.1415926573
+
+struct vert_struct {
+	VRDATA	x, y, z;	/* point coordinates */
+};
+
diff --git a/Stripe_u/extend.h b/Stripe_u/extend.h
new file mode 100644
index 000000000..78c135e3a
--- /dev/null
+++ b/Stripe_u/extend.h
@@ -0,0 +1,17 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: extend.h
+-----------------------------------------------------------------------*/
+
+int Bottom_Left();
+int Top_Left();
+void Start_Edge();
+
+
diff --git a/Stripe_u/free.c b/Stripe_u/free.c
new file mode 100644
index 000000000..9494f4fb4
--- /dev/null
+++ b/Stripe_u/free.c
@@ -0,0 +1,110 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: free.c
+     This file contains the code used to free the data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "polverts.h"
+
+void ParseAndFreeList( ListHead *pListHead )
+{
+    PLISTINFO value;
+    register int c,num;
+	  
+    /*    Freeing a linked list */
+    num = NumOnList(pListHead);
+    for (c = 0; c< num; c++)
+	     value =   RemHead(pListHead);
+} 
+
+void FreePolygonNode( PF_VERTS pfVerts)
+{
+	/*   Free a vertex node */
+     if ( pfVerts->pPolygon )
+		free( pfVerts->pPolygon );
+	free( pfVerts );
+
+}
+ 
+void Free_Strips()
+{
+    P_STRIPS temp = NULL;
+
+    /*    Free strips data structure */
+    if (strips[0] == NULL)
+         return;
+    else
+         ParseAndFreeList(strips[0]);
+}
+
+void FreeFaceNode( PF_FACES pfFaces)
+{
+	/*   Free face node */
+     if ( pfFaces->pPolygon )
+                free( pfFaces->pPolygon );
+        free( pfFaces );
+}
+
+
+void FreeFaceTable(int nSize)
+{
+     register int nIndex;
+
+     for ( nIndex=0; nIndex < nSize; nIndex++ )
+     { 
+    		if ( PolFaces[nIndex] != NULL ) 
+             ParseAndFreeList( PolFaces[nIndex] );
+     }
+     free( PolFaces );
+}
+
+void FreeEdgeTable(int nSize)
+{
+        register int nIndex;
+
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                if ( PolEdges[nIndex] != NULL )
+                        ParseAndFreeList( PolEdges[nIndex] );
+        }
+        free( PolEdges );
+}
+
+
+void Free_All_Strips()
+{
+
+	ListHead *pListHead;
+	register int y;
+
+	for (y =0; ; y++)
+	{
+		pListHead = all_strips[y];
+		if (pListHead == NULL)
+			return;
+		else
+			ParseAndFreeList(all_strips[y]);
+	}
+}
+
+void End_Face_Struct(int numfaces)
+{
+     FreeFaceTable(numfaces);
+}
+
+void End_Edge_Struct(int numverts)
+{
+     FreeEdgeTable(numverts);
+}	
+
+
diff --git a/Stripe_u/free.h b/Stripe_u/free.h
new file mode 100644
index 000000000..3303d05e1
--- /dev/null
+++ b/Stripe_u/free.h
@@ -0,0 +1,22 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: free.h
+-----------------------------------------------------------------------*/
+
+void Free_All_Strips();
+void ParseAndFreeList();
+void FreePolygonNode();
+void Free_Strips();
+void FreeFaceTable();
+void FreeEdgeTable();
+void End_Face_Struct();
+void End_Edge_Struct();
+
+
diff --git a/Stripe_u/global.h b/Stripe_u/global.h
new file mode 100644
index 000000000..3621b25e1
--- /dev/null
+++ b/Stripe_u/global.h
@@ -0,0 +1,37 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: global.h
+-----------------------------------------------------------------------*/
+
+#define   VRDATA		double
+#define   MAX1            60
+	
+#define	TRUE	      	1
+#define	FALSE		0
+
+#ifndef PI
+#  define   PI	     	3.1415926573
+#endif /* PI */
+#define   ATOI(C)        (C -'0')
+#define   X              0
+#define   Y              1
+#define   Z              2
+#define   EVEN(x)       (((x) & 1) == 0)
+#define   MAX_BAND      10000
+
+struct vert_struct {
+	VRDATA	x, y, z;	/* point coordinates */
+};
+
+int     ids[MAX1];
+int     norms[MAX1];
+int     *vert_norms;
+int     *vert_texture;
+
diff --git a/Stripe_u/glove.h b/Stripe_u/glove.h
new file mode 100644
index 000000000..74bcd07da
--- /dev/null
+++ b/Stripe_u/glove.h
@@ -0,0 +1,151 @@
+/*
+ * dg2lib.h - header file for the DG2 library libdg2.a
+ *
+ * copyright 1988-92 VPL Research Inc.
+ *
+ */
+
+
+
+/******** error returns from the library */
+
+extern int DG2_error;  		/* for error information */
+extern float DG2_lib_version;  	/* for the library version */
+extern int DG2_box_version;  	/* for the firmware version */
+extern int DG2_glove_sensors;	/* for the number of sensors in the glove */
+
+/* defines for DG2_error values */
+
+#define DG2_AOK			0 
+#define DG2_SETTINGS_FILE	-1
+#define DG2_SERIAL_OPEN		-2 
+#define DG2_SERIAL_PORT		-4   
+#define DG2_RESET		-6  
+#define DG2_PARAMETER		-7  
+#define DG2_FILE_IO		-8
+#define DG2_CALIBRATION_FILE	-9
+#define DG2_GESTURE_FILE	-10
+#define DG2_CAL_GEST_FILES	-11
+/* defines for DG2_response() */
+
+#define DATAGLOVE	1
+#define POLHEMUS	2
+#define GESTURE		8
+
+#define DG2_60Hz	1
+#define DG2_30Hz	2
+#define DG2_oneShot	3
+
+/* defines for DG2_DataGlove_select() */
+
+#define THUMB_INNER	0x1
+#define THUMB_OUTER	0x2
+#define INDEX_INNER	0x4
+#define INDEX_OUTER	0x8
+#define MIDDLE_INNER	0x10
+#define MIDDLE_OUTER	0x20
+#define RING_INNER	0x40
+#define RING_OUTER	0x80
+#define LITTLE_INNER	0x100
+#define LITTLE_OUTER	0x200
+#define NORMAL_JOINTS	0x3ff
+#define FLEX11		0x400
+#define FLEX12		0x800
+#define FLEX13		0x1000
+#define FLEX14		0x2000
+#define FLEX15		0x4000
+#define FLEX16		0x8000
+
+
+/* defines for DG2_DataGlove_trans_select() */
+
+#define DG2_TRANSLATED 	5
+#define DG2_RAW		6
+
+/* defines for DG2_Polhemus_units() */
+
+#define POL_RAW		0
+#define POL_INCHES	1
+#define POL_CM		2
+
+/* defines for DG2_user_IRQ() */
+
+#define IRQ_ON	1
+#define IRQ_OFF	2
+
+
+/* defines for DG2_get_data() */
+
+#define DG2_report	1
+#define DG2_userport	2
+
+
+/* dg2 command codes*/
+#define LEADINGBYTE 	0x24
+#define RPT60     	0x41	/* repeat 60 */
+#define RPT30     	0x42	/* repeat 30 */
+#define ONESHOT   	0x43	/* one shot */
+#define SYSID     	0x44	/* system ID */
+#define EPTBUF    	0x45 	/* empty buffer */
+#define USRRD     	0x46	/* user read */
+#define USRIRQ    	0x47	/* user IRQ */
+#define QBRT      	0x48	/* query bright */	
+#define CDRST     	0x49	/* cold reset */
+#define WMRST     	0x4A	/* warm reset */
+#define MEMALLO   	0x4B	/* memory alloc */
+#define DLTSND    	0x4C	/* delta send */
+#define SETBRT    	0x4D	/* set bright */
+#define SETDIM    	0x4E	/* set dim */
+#define FILBUF    	0x4F	/* fill buffer */
+#define LDTBL     	0x50	/* load table */
+#define LDPOL     	0x51	/* send up to 63 bytes to Polhemus  */
+#define ANGLE     	0x52	/* angles */
+#define NSNSR     	0x53	/* num sensors */
+#define SETFB     	0x54	/* set feedback */
+#define QCUT      	0X55	/* query cutoff*/
+#define SETCUT    	0X56	/* set cutoff */
+#define FLXVAL    	0X57	/* raw flex values */
+#define USRWR     	0X58	/* user write */
+#define JNTMAP    	0X59	/* joint map */
+#define ERRMESS		0XFF	/* error in command input */
+#define TIMOUT		0XFE	/* timed out during command */
+
+/* response structure */
+
+typedef struct DG2_data {
+	char gesture;
+	double location[3];  	/* X,Y,Z */
+	double orientation[3];	/* yaw, pitch, roll */
+	short flex[16];
+	char gesture_name[20];
+	short reserved[16];
+		/* user port data: */
+	char user_nibble;
+	char user_analog[3];
+} DG2_data;
+
+
+/**************function prototypes*************/
+/*NOTE: all DG2_ functions return -1 on error*/
+
+extern int DG2_open(char *portname, int baud);
+extern int DG2_close(int filedes);
+extern int DG2_direct(int filedes,char *message,int count);
+extern int DG2_response(int filedes,int devices,int rate);
+extern int DG2_DataGlove_select(int filedes,int flex_sensors);
+extern int DG2_DataGlove_translation(int filedes,int flex_sensors,char table[16][256]);
+extern int DG2_DataGlove_trans_select(int filedes,int status);
+extern int DG2_DataGlove_LED_set(int filedes,int LED);
+extern int DG2_DataGlove_LED_read(int filedes);
+extern int DG2_Polhemus_units(int filedes,char type);
+extern int DG2_Polhemus_direct(int filedes,char *message,int count);
+extern int DG2_user_write(int filedes,int nibble);
+extern int DG2_user_IRQ(int filedes,int mode);
+extern int DG2_user_read(int filedes,DG2_data *data);
+extern int DG2_get_data(int filedes,DG2_data *data);
+extern int DG2_gesture_load(int filedes,char *calib,char *gest);
+
+/*use this with caution since it does not return until it gets a correct
+ *response from the DG2
+*/
+extern int DG2U_get_reply(int filedes,char *buff,int response,int size);
diff --git a/Stripe_u/init.c b/Stripe_u/init.c
new file mode 100644
index 000000000..b3b218cec
--- /dev/null
+++ b/Stripe_u/init.c
@@ -0,0 +1,217 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: init.c
+     This file contains the initialization of data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "polverts.h"
+
+void init_vert_norms(int num_vert)
+{
+     /*   Initialize vertex/normal array to have all zeros to
+          start with.
+     */
+     register int x;
+
+     for (x = 0; x < num_vert; x++)
+          *(vert_norms + x) = 0;
+}
+
+void init_vert_texture(int num_vert)
+{
+     /*   Initialize vertex/normal array to have all zeros to
+          start with.
+     */
+     register int x;
+
+     for (x = 0; x < num_vert; x++)
+          *(vert_texture + x) = 0;
+}
+
+BOOL InitVertTable( int nSize )
+{
+     register int nIndex;
+
+	/*   Initialize the vertex table */
+     PolVerts = (ListHead**) malloc(sizeof(ListHead*) * nSize ); 
+	if ( PolVerts )
+	{
+		for ( nIndex=0; nIndex < nSize; nIndex++ )
+		{
+			PolVerts[nIndex] = NULL;
+		}
+		return( TRUE );	
+	}
+	return( FALSE );
+}  
+
+BOOL InitFaceTable( int nSize )
+{
+        register int nIndex;
+
+        /*     Initialize the face table */
+        PolFaces = (ListHead**) malloc(sizeof(ListHead*) * nSize ); 
+        if ( PolFaces )
+        {
+                for ( nIndex=0; nIndex < nSize; nIndex++ )
+                {
+                        PolFaces[nIndex] = NULL;
+                }
+                return( TRUE );
+        }
+        return( FALSE );
+} 
+
+BOOL InitEdgeTable( int nSize )
+{
+        register int nIndex;
+
+        /*     Initialize the edge table */
+        PolEdges = (ListHead**) malloc(sizeof(ListHead*) * nSize );
+        if ( PolEdges )
+        {
+                for ( nIndex=0; nIndex < nSize; nIndex++ )
+                {
+                        PolEdges[nIndex] = NULL;
+                }
+                return( TRUE );
+        }
+        return( FALSE );
+}
+
+
+void InitStripTable(  )
+{
+
+     PLISTHEAD pListHead;
+
+     /*   Initialize the strip table */
+     pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+	if ( pListHead )
+     {
+		InitList( pListHead );
+		strips[0] = pListHead;
+	}
+     else
+	{
+	     printf("Out of memory !\n");
+		exit(0);
+	}
+
+}
+
+void Init_Table_SGI()
+{
+	PLISTHEAD pListHead;
+	int max_adj = 60;
+	register int x;
+	
+	/*   This routine will initialize the table that will
+		have the faces sorted by the number of adjacent polygons
+		to it.
+	*/
+
+	for (x=0; x< max_adj; x++)
+	{
+		/*   We are allowing the max number of sides of a polygon
+			to be max_adj.
+		*/                      
+		pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+		if ( pListHead )
+	     {
+			InitList( pListHead );
+			array[x] = pListHead;
+		}
+	     else
+		{
+		     printf("Out of memory !\n");
+			exit(0);
+		}
+	}
+}
+
+void BuildVertTable( int nSize )
+{
+     register int nIndex;
+     PLISTHEAD pListHead;
+	
+	for ( nIndex=0; nIndex < nSize; nIndex++ )
+	{
+		pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+		if ( pListHead )
+        	{
+			InitList( pListHead );
+			PolVerts[nIndex] = pListHead;
+		}
+        	else
+        		return;	
+		
+	}
+}
+   
+
+void BuildFaceTable( int nSize )
+{
+        register int nIndex;
+        PLISTHEAD pListHead;
+        
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+                if ( pListHead )
+                {
+                        InitList( pListHead );
+                        PolFaces[nIndex] = pListHead;
+                }
+                else
+                        return; 
+                
+        }
+}
+   
+void BuildEdgeTable( int nSize )
+{
+        register int nIndex;
+        PLISTHEAD pListHead;
+
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+                if ( pListHead )
+                {
+                        InitList( pListHead );
+                        PolEdges[nIndex] = pListHead;
+                }
+                else
+                        return;
+        }
+}
+
+void Start_Face_Struct(int numfaces)
+{
+	if (InitFaceTable(numfaces))
+	{
+		BuildFaceTable(numfaces);
+	}
+}
+
+void Start_Edge_Struct(int numverts)
+{
+        if (InitEdgeTable(numverts))
+        {
+                BuildEdgeTable(numverts);
+        }
+}
+
+
diff --git a/Stripe_u/init.h b/Stripe_u/init.h
new file mode 100644
index 000000000..2faf0e838
--- /dev/null
+++ b/Stripe_u/init.h
@@ -0,0 +1,30 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: init.h
+-----------------------------------------------------------------------*/
+
+void init_vert_norms();
+void init_vert_texture();
+BOOL InitVertTable();
+BOOL InitFaceTable();
+BOOL InitEdgeTable();
+void InitStripTable();
+void Init_Table_SGI();
+void BuildVertTable();
+void BuildFaceTable();
+void BuildEdgeTable();
+void Start_Face_Struct();
+void Start_Edge_Struct();
+
+
+
+
+
+
diff --git a/Stripe_u/local.c b/Stripe_u/local.c
new file mode 100644
index 000000000..2db94904e
--- /dev/null
+++ b/Stripe_u/local.c
@@ -0,0 +1,123 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: local.c
+     This file contains the code that initializes the data structures for
+     the local algorithm, and starts the local algorithm going.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "polverts.h"
+#include "local.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "common.h"
+#include "outputex.h"
+#include "util.h"
+#include "init.h"
+
+void Find_StripsEx(FILE *output,FILE *strip,int *ties,
+				 int  tie, int triangulate,
+                 int  swaps,int *next_id)
+{
+	/*	This routine will peel off the strips from the model */
+
+	ListHead *pListHead;
+	P_ADJACENCIES temp = NULL;
+	register int max,bucket=0;
+	BOOL whole_flag = TRUE;
+     int dummy = 0;
+	
+	/*  Set the last known input edge to be null */
+     Last_Edge(&dummy,&dummy,&dummy,1);
+    
+     /*	Search for lowest adjacency polygon and output strips */
+	while (whole_flag)
+	{
+		bucket = -1;
+		/*	Search for polygons in increasing number of adjacencies */
+		while (bucket < 59)
+		{
+			bucket++;
+			pListHead = array[bucket];
+			max = NumOnList(pListHead);
+			if (max > 0)
+			{
+				temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0);
+				if (temp == NULL)
+				{
+					printf("Error in the buckets%d %d %d\n",bucket,max,0);
+					exit(0);
+				}
+				Polygon_OutputEx(temp,temp->face_id,bucket,pListHead,
+	       				       output,strip,ties,tie,triangulate,swaps,next_id,1);
+				/*  Try to extend backwards, if the starting polygon in the
+                        strip had 2 or more adjacencies to begin with
+                    */
+                    if (bucket >= 2)
+                         Extend_BackwardsEx(temp->face_id,output,strip,ties,tie,triangulate,
+                                            swaps,next_id);
+                    break;  
+			}
+		}
+		/*	Went through the whole structure, it is empty and we are done.
+		*/
+		if ((bucket == 59) && (max == 0))
+			whole_flag = FALSE;
+        
+          /*  We just finished a strip, send dummy data to signal the end
+              of the strip so that we can output it.
+          */
+         else
+         {
+             Output_TriEx(-1,-2,-3,output,-1,-10,1);
+             Last_Edge(&dummy,&dummy,&dummy,1);
+         }
+	}
+}
+
+
+
+void SGI_Strip(int num_verts,int num_faces,FILE *output,
+			   int ties,int triangulate)
+               
+{
+	FILE *strip;
+     int next_id = -1,t=0;
+
+     strip = fopen("output.d","w");
+     /*	We are going to output and find triangle strips
+		according the the method that SGI uses, ie always
+		choosing as the next triangle in our strip the triangle
+		that has the least number of adjacencies. We do not have
+		all triangles and will be triangulating on the fly those
+		polygons that have more than 3 sides.
+	*/
+
+	/*	Build a table that has all the polygons sorted by the number
+		of polygons adjacent to it.
+	*/
+	/*	Initialize it */
+	Init_Table_SGI();
+	/*	Build it */
+	Build_SGI_Table(num_verts,num_faces);
+
+	/*    We will have a structure to hold all the strips, until
+          outputted.
+     */
+     InitStripTable();
+     /*	Now we have the structure built to find the polygons according
+		to the number of adjacencies. Now use the SGI Method to find
+		strips according to the adjacencies
+	*/
+     Find_StripsEx(output,strip,&t,ties,triangulate,ON,&next_id);
+
+}
diff --git a/Stripe_u/local.h b/Stripe_u/local.h
new file mode 100644
index 000000000..34769ebb8
--- /dev/null
+++ b/Stripe_u/local.h
@@ -0,0 +1,19 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:local.h
+-----------------------------------------------------------------------*/
+
+void Local_Polygon_Output();
+void Local_Output_Tri();
+int Different();
+void Local_Non_Blind_Triangulate();
+void Local_Blind_Triangulate();
+void Local_Triangulate_Polygon();
+void SGI_Strip();
diff --git a/Stripe_u/my_global.h b/Stripe_u/my_global.h
new file mode 100644
index 000000000..629c12074
--- /dev/null
+++ b/Stripe_u/my_global.h
@@ -0,0 +1,3 @@
+int change_in_stripEx = 0;
+int change_in_strip = 0;
+
diff --git a/Stripe_u/newpolve.c b/Stripe_u/newpolve.c
new file mode 100644
index 000000000..9adbfd651
--- /dev/null
+++ b/Stripe_u/newpolve.c
@@ -0,0 +1,1667 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: newpolve.c
+     This routine contains the bulk of the code that will find the
+     patches of quads in the data model
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "extend.h"
+#include "output.h"
+#include "triangulate.h"
+#include "common.h"
+#include "util.h"
+#include "global.h"        
+#include "init.h"
+#include "add.h"
+
+ListHead **PolVerts;
+ListHead **PolFaces;
+ListHead **PolEdges;
+int length;
+BOOL resetting = FALSE;
+int     ids[MAX1];
+int 	added_quad = 0;
+BOOL reversed = FALSE;
+int patch = 0;
+int *vn;
+int *vt;
+
+int Calculate_Walks(int lastvert,int y, PF_FACES temp2)
+{
+	/* Find the length of the walk */
+	
+	int previous_edge1, previous_edge2;
+	register int nextvert,numverts,counter,walk=0;
+	BOOL flag;
+	F_EDGES *node;
+     ListHead *pListHead;
+     static int seen = 0;
+     
+	/* Find the edge that we are currently on */
+	if (y != 3)
+	{
+		previous_edge1 = *(temp2->pPolygon +y);
+		previous_edge2 = *(temp2->pPolygon + y + 1);
+	}
+	else
+	{
+		previous_edge1 = *(temp2->pPolygon +y);
+		previous_edge2 = *(temp2->pPolygon);
+	}
+
+	temp2->seen = seen;
+     counter = y;
+
+     /*Find the adjacent face to this edge */
+	node = *(temp2->VertandId+y);			
+	if (node->edge[2] != lastvert)
+        nextvert = node->edge[2];
+     else
+        nextvert = node->edge[1];
+					
+	/* Keep walking in this direction until we cannot do so */
+	while ((nextvert != lastvert) && (nextvert != -1))
+	{
+		walk++;
+		pListHead = PolFaces[nextvert];
+		temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		numverts = temp2->nPolSize;
+		if ((numverts != 4) || (temp2->seen == seen))
+		{
+			walk--;
+			nextvert = -1;
+		}
+		else
+		{
+			temp2->seen = seen;
+               /* Find edge that is not adjacent to the previous one */
+			counter = 0;
+			flag = TRUE;
+			while ((counter < 3) && (flag))
+			{
+				if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+					(*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+					((*(temp2->pPolygon+counter) == previous_edge2) || 
+					(*(temp2->pPolygon+counter+1) == previous_edge1)) )
+					counter++;		
+				else
+					flag = FALSE;	
+			}
+	     	/* Get the IDs of the next edge */
+		     if (counter < 3)
+		     {
+			     previous_edge1 = *(temp2->pPolygon + counter);
+			     previous_edge2 = *(temp2->pPolygon + counter + 1);
+		     }
+		     else
+		     {
+                    previous_edge1 = *(temp2->pPolygon + counter);
+                    previous_edge2 = *(temp2->pPolygon);
+		     }
+	
+		     node = *(temp2->VertandId + counter);
+		     if (node->edge[1] == nextvert)
+			     nextvert = node->edge[2];
+		     else
+			     nextvert = node->edge[1];
+		}
+	}
+     seen++;
+	return walk;
+}
+
+
+BOOL Check_Right(int last_seen,PF_FACES temp2,int y,int face_id)
+{
+	/* Check when we last saw the face to the right of the current
+	   one. We want to have seen it just before we started this strip
+	*/
+
+	F_EDGES *node;
+	ListHead *pListHead;
+	register int nextvert,oldy;
+	PF_FACES t;
+	
+     oldy = y;
+	if (y != 3)
+		y = y+1;
+	else
+		y = 0;
+	node = *(temp2->VertandId + y);
+	if (face_id == node->edge[1])
+		nextvert = node->edge[2];
+	else
+		nextvert = node->edge[1];
+	
+     if (nextvert == -1)
+          return FALSE;
+     
+     pListHead = PolFaces[nextvert];
+	t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+	if (t->seen != (last_seen - 1))
+	{
+		 /* maybe because of the numbering, we are not
+		    on the right orientation, so we have to check the
+		    opposite one to be sure 
+           */
+		if (oldy != 0)
+			y = oldy-1;
+		else
+			y = 3;
+		node = *(temp2->VertandId + y);
+		if (face_id == node->edge[1])
+			nextvert = node->edge[2];
+		else
+			nextvert = node->edge[1];
+		if (nextvert == -1)
+               return FALSE;
+          pListHead = PolFaces[nextvert];
+		t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		if (t->seen != (last_seen - 1))
+		 	return FALSE;
+	}
+	return TRUE;
+}
+
+
+int Update_and_Test(PF_FACES temp2,int y,BOOL first,int distance,int lastvert, int val)
+{
+	     
+        static int last_seen = 17;
+        int previous_edge1, previous_edge2;
+        register int original_distance,nextvert,numverts,counter;
+        BOOL flag;
+        F_EDGES *node;
+        ListHead *pListHead;
+                                                        
+        original_distance = distance;
+        /* Find the edge that we are currently on */
+        if (y != 3)
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon + y + 1);
+        }
+        else
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon);
+        }
+
+        temp2->seen = val;
+        temp2->seen2 = val;
+		
+        node = *(temp2->VertandId+y);                   
+        if (lastvert != node->edge[2])
+			nextvert = node->edge[2];
+	   else
+			nextvert = node->edge[1];
+                                        
+        /* Keep walking in this direction until we cannot do so  or
+		we go to distance */
+        while ((distance > 0)  && (nextvert != lastvert) && (nextvert != -1))
+        {
+                distance--;
+			           
+                pListHead = PolFaces[nextvert];
+                temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+                temp2->seen = val;
+				
+                if (temp2->seen2 == val)
+                {
+                     last_seen++;
+                     return (original_distance - distance);
+                }
+                
+                temp2->seen2 = val;
+                
+                numverts = temp2->nPolSize;
+                                
+	     	 if (numverts != 4)
+          	     nextvert = -1;
+		
+                else if ((!first) && (!(Check_Right(last_seen,temp2,y,nextvert))))
+                {
+                    last_seen++;
+                    return (original_distance - distance);
+                }
+		      else
+                {
+                        /* Find edge that is not adjacent to the previous one */
+                        counter = 0;
+                        flag = TRUE;
+                        while ((counter < 3) && (flag))
+                        {
+                                if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                        ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                        counter++;
+                                else
+                                        flag = FALSE;
+                        }
+                        /* Get the IDs of the next edge */
+                        if (counter < 3)
+                        {
+                              previous_edge1 = *(temp2->pPolygon + counter);
+                              previous_edge2 = *(temp2->pPolygon + counter + 1);
+                        }
+                        else
+                        {
+                              previous_edge1 = *(temp2->pPolygon + counter);
+                              previous_edge2 = *(temp2->pPolygon);
+                        }
+                        if      ( ((*(temp2->walked+counter) == -1) && 
+                                (*(temp2->walked+counter+2) == -1)))
+                        {
+                                printf("There is an error in the walks!\n");
+                                printf("1Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter+2));
+                                exit(0);
+                        }
+                        else
+                        {
+                                if      ((*(temp2->walked+counter) == -1) && 
+                                        (*(temp2->walked+counter-2) ==  -1))
+                                {
+                                        printf("There is an error in the walks!\n");
+                                        printf("2Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter-2));
+                                        exit(0);
+                                }
+                        }
+                        node = *(temp2->VertandId + counter);
+                        y = counter;
+		              if (node->edge[1] == nextvert)
+                              nextvert = node->edge[2];
+                        else
+                              nextvert = node->edge[1];
+             }
+    }
+	
+    last_seen++;
+
+    if  (distance != 0)  
+    {
+		if (((nextvert == -1) || (nextvert == lastvert)) && (distance != 1))
+			return (original_distance - distance);
+    }
+    return original_distance;
+}
+
+
+int Test_Adj(PF_FACES temp2,int x,int north,int distance,int lastvert, int value)
+{
+	/* if first time, then just update the last seen field */
+	if (x==1)
+		return(Update_and_Test(temp2,north,TRUE,distance,lastvert,value));
+	/* else we have to check if we are adjacent to the last strip */
+	else
+		return(Update_and_Test(temp2,north,FALSE,distance,lastvert,value));
+}
+  
+void Get_Band_Walk(PF_FACES temp2,int face_id,int *dir1,int *dir2, 
+					int orientation,int cutoff_length)
+{
+	int previous_edge1, previous_edge2;
+	F_EDGES *node;
+	ListHead *pListHead;
+	register int walk = 0, nextvert,numverts,counter;
+	BOOL flag;
+	
+	/*	Get the largest band that will include this face, starting
+		from orientation. Save the values of the largest band
+		(either north and south together, or east and west together)
+		in the direction variables.
+	*/
+	/* Find the edge that we are currently on */
+     if (orientation != 3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation);
+                previous_edge2 = *(temp2->pPolygon + orientation + 1);
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+		
+     if (orientation == 0)
+     {
+			 if (*dir1 > *(temp2->walked + 1))
+				*dir1 = *(temp2->walked + 1);
+			 if (*dir2 > *(temp2->walked + 3))
+				*dir2 = *(temp2->walked + 3);
+	}
+	else if (orientation == 3)
+	{
+			if (*dir1 > *(temp2->walked + orientation - 3))
+			     *dir1 = *(temp2->walked + orientation - 3) ;
+			if (*dir2 > *(temp2->walked + orientation -1 ))
+				*dir2 = *(temp2->walked + orientation - 1);
+	}
+	else
+	{
+			if (*dir1 > *(temp2->walked + orientation - 1))
+				*dir1 = *(temp2->walked + orientation -1) ;
+			if (*dir2 > *(temp2->walked+ orientation + 1))
+				*dir2 = *(temp2->walked + orientation + 1);
+	}
+        
+     /*	if we know already that we can't extend the
+        	band from this face, we do not need to do the walk
+     */
+     if ((*dir1 != 0) && (*dir2 != 0))
+     {
+		/* Find the adjacent face to this edge */
+        	node = *(temp2->VertandId+orientation);                   
+        	if (face_id == node->edge[1])
+			nextvert = node->edge[2];
+        	else 
+			nextvert = node->edge[1];
+	}
+     else
+        	nextvert = -1; /* leave w/o walking */                                
+	
+	/* Keep walking in this direction until we cannot do so */
+     while ((nextvert != face_id) && (nextvert != -1))
+     {
+            walk++;
+            pListHead = PolFaces[nextvert];
+            temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+            numverts = temp2->nPolSize;
+            if ((numverts != 4)	|| (walk > cutoff_length))
+                   nextvert = -1;
+            else
+            {
+	  		  /* Find edge that is not adjacent to the previous one */
+                 counter = 0;
+                 flag = TRUE;
+                 while ((counter < 3) && (flag))
+                 {
+                           if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                     counter++;
+                           else
+                                flag = FALSE;
+                 }
+                 /* Get the IDs of the next edge */
+                 if (counter < 3)
+                 {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon + counter + 1);
+                 }
+                 else
+                 {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon);
+                 }
+                
+			  /* 	find out how far we can extend in the 2 directions
+					along this new face in the walk
+			  */
+			  if (counter == 0)
+			  {
+					if (*dir1 > *(temp2->walked + 1))
+						*dir1 = *(temp2->walked + 1);
+					if (*dir2 > *(temp2->walked + 3))
+						*dir2 = *(temp2->walked + 3);
+			  }
+			  else if (counter == 3)
+			  {
+					if (*dir1 > *(temp2->walked + counter - 3))
+						*dir1 = *(temp2->walked + counter - 3) ;
+					if (*dir2 > *(temp2->walked + counter -1 ))
+						*dir2 = *(temp2->walked + counter -1);
+			  }
+			  else
+			  {
+					if (*dir1 > *(temp2->walked + counter - 1))
+						*dir1 = *(temp2->walked + counter -1) ;
+					if (*dir2 > *(temp2->walked + counter + 1))
+						*dir2 = *(temp2->walked + counter + 1);
+			  }
+        
+        	      /*	if we know already that we can't extend the
+        	     	band from this face, we do not need to do the walk
+        	      */
+	        	 if ((*dir1 == 0) || (*dir2 == 0))
+                	nextvert = -1;
+                if (nextvert != -1)
+                {
+                	node = *(temp2->VertandId + counter);
+                	if (node->edge[1] == nextvert)
+                        nextvert = node->edge[2];
+                	else
+                        nextvert = node->edge[1];
+                }
+
+           }
+        }
+}
+
+
+
+
+int Find_Max(PF_FACES temp2,int lastvert,int north,int left,
+			int *lastminup,int *lastminleft)
+{
+	int temp,walk,counter,minup,x,band_value;
+	int previous_edge1, previous_edge2;
+	F_EDGES	*node;
+	ListHead *pListHead;
+	BOOL flag;	
+	static int last_seen = 0;
+	register int t,smallest_so_far,nextvert,max=-1;
+	        
+     t= lastvert;
+     *lastminup = MAX_BAND;
+	*lastminleft = 1;
+
+     if (left == 3)
+	{
+          previous_edge1 = *(temp2->pPolygon + left);
+          previous_edge2 = *(temp2->pPolygon);
+	}
+                
+	else
+	{
+          previous_edge1 = *(temp2->pPolygon + left + 1);
+          previous_edge2 = *(temp2->pPolygon + left);
+	}
+
+	temp2->seen = last_seen;
+     walk = *(temp2->walked + left);
+
+     for (x=1;x<=(walk+1); x++)
+	{
+		/*   test to see if we have a true band
+		     that is, are they adjacent to each other
+		*/
+        
+         minup = *(temp2->walked + north) + 1;
+
+	    /*	if we are at the very first face, then we do not
+	    	     have to check the adjacent faces going up
+	    	     and our north distance is the distance of this face's
+			north direction. 
+	    */
+         if (x == 1) 
+	    {
+			*lastminup = minup;
+			minup = Test_Adj(temp2,x,north,*lastminup,lastvert,last_seen);
+			*lastminup = minup;
+               smallest_so_far = minup;	
+         }
+		
+	
+	    /* find the largest band that we can have */
+	    if (minup < (*lastminup))
+	    {
+			/*	see if we really can go up all the way 
+				temp should by less than our equal to minup
+				if it is less, then one of the faces was not
+				adjacent to those next to it and the band height
+				will be smaller
+			*/
+			temp = Test_Adj(temp2,x,north,minup,lastvert,last_seen);
+			if (temp > minup)
+			{
+				printf("There is an error in the test adj\n");
+				exit(0);
+			}
+			minup = temp;
+			band_value = x * minup;
+			if (minup < smallest_so_far)
+			{
+				if (band_value > max)
+               	{
+					smallest_so_far = minup;
+					*lastminup = minup;
+					*lastminleft = x;
+                         max = band_value;
+                    }
+				else
+					smallest_so_far = minup;
+			}
+			else
+			{
+				band_value = x * smallest_so_far;
+     	          if (band_value > max)
+                    {
+                	     *lastminup = smallest_so_far;
+                         *lastminleft = x;
+                         max = band_value;
+                    }
+			}
+		}
+		else
+		{
+			if (x != 1)
+               {
+                    temp = Test_Adj(temp2,x,north,smallest_so_far,lastvert,last_seen);
+			     if (temp > smallest_so_far)
+			     {
+				    printf("There is an error in the test adj\n");
+				    exit(0);
+			     }
+			    smallest_so_far = temp;
+               }
+               band_value = x * smallest_so_far; 
+			if (band_value > max)
+			{
+				*lastminup = smallest_so_far;
+				*lastminleft = x;
+				max = band_value;
+			}
+		}
+		if ( x != (walk + 1))
+		{
+			node = *(temp2->VertandId+left);
+			if (lastvert == node->edge[1])
+				nextvert = node->edge[2];
+			else
+				nextvert = node->edge[1];
+
+               lastvert = nextvert;
+               
+               if (nextvert == -1)
+                    return max;
+               
+               pListHead = PolFaces[nextvert];
+			temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
+			
+               /* if we have visited this face before, then there is an error */
+               if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
+				(*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
+				|| (temp2->nPolSize !=4) || (temp2->seen == last_seen))
+			{
+
+                    if (lastvert == node->edge[1])
+                         nextvert = node->edge[2];
+                    else
+                         nextvert = node->edge[1];
+                    if (nextvert == -1)
+                         return max;
+                    lastvert = nextvert;
+                    /*   Last attempt to get the face ... */
+                    pListHead = PolFaces[nextvert];
+     			temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
+                    if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
+				     (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
+				     || (temp2->nPolSize !=4) || (temp2->seen == last_seen))
+                         return max;    /*   The polygon was not saved with the edge, not
+                                             enough room. We will get the walk when we come
+                                             to that polygon later.
+                                        */
+			}
+			else
+			{
+				counter = 0;
+				flag = TRUE;
+				temp2->seen = last_seen;
+
+                    while ((counter < 3) && (flag))
+			     {
+
+                         if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                        ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                        counter++;
+				     else
+                                        flag = FALSE;
+                    }
+               }
+		
+               /* Get the IDs of the next edge */
+               left = counter;
+		     north = left+1;
+               if (left ==3)
+			     north = 0;	
+		     if (counter < 3)
+               {
+                        previous_edge1 = *(temp2->pPolygon + counter + 1);
+                        previous_edge2 = *(temp2->pPolygon + counter);
+               }
+               else
+               {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon);
+               }
+
+          } 
+
+}
+last_seen++;
+return max;
+}
+
+void Mark_Face(PF_FACES temp2, int color1, int color2,
+				int color3, FILE *output_file, BOOL end, int *edge1, int *edge2, 
+                    int *face_id, int norms, int texture)
+{
+     static int last_quad[4];
+     register int x,y,z=0;
+     int saved[2];
+     static int output1, output2,last_id;
+     BOOL cptexture;
+
+     /*   Are we done with the patch? If so return the last edge that
+          we will come out on, and that will be the edge that we will
+          start to extend upon.
+     */
+
+     cptexture = texture;
+     if (end)
+     {
+          *edge1 = output1;
+          *edge2 = output2;
+          *face_id = last_id;
+          return;
+     }
+
+     last_id = *face_id;
+	*(temp2->walked) = -1;
+	*(temp2->walked+1) = -1;
+	*(temp2->walked+2) = -1;
+	*(temp2->walked+3) = -1;
+	added_quad++;
+	temp2->nPolSize = 1;
+
+     if (patch == 0)
+     {
+          /*   At the first quad in the strip -- save it */
+          last_quad[0] = *(temp2->pPolygon);
+          last_quad[1] = *(temp2->pPolygon+1);
+          last_quad[2] = *(temp2->pPolygon+2);
+          last_quad[3] = *(temp2->pPolygon+3);
+          patch++;
+     }
+     else
+     {
+          /*   Now we have a triangle to output, find the edge in common */
+          for (x=0; x < 4 ;x++)
+          {
+              for (y=0; y< 4; y++)
+              {
+                   if (last_quad[x] == *(temp2->pPolygon+y))
+                   {
+                        saved[z++] = last_quad[x];               
+                        if (z > 2)
+                        {
+                             /*    This means that there was a non convex or
+                                   an overlapping polygon
+                             */
+                             z--;
+                             break;
+                        }
+                   }                             
+              }
+          }
+          
+          if (z != 2)
+          {
+               printf("Z is not 2 %d \n",patch);
+               printf("4 %d %d %d %d %d %d %d\n",*(temp2->pPolygon),
+				*(temp2->pPolygon+1),*(temp2->pPolygon+2),*(temp2->pPolygon+3),
+				color1,color2,color3);
+               printf("%d %d %d %d\n",last_quad[0],last_quad[1],last_quad[2],last_quad[3]);
+               exit(1);
+          }
+          
+          if (patch == 1)
+          {
+               /*   First one to output, there was no output edge */
+               patch++;
+               x = Adjacent(saved[0],saved[1],last_quad,4);
+               y = Adjacent(saved[1],saved[0],last_quad,4);
+               
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) || ((vt[saved[1]])==0)))
+                    cptexture = FALSE;
+
+               if ((!norms) && (!cptexture))
+               {
+                    fprintf(output_file,"\nt %d %d %d ",x+1,y+1,saved[1]+1);
+                    fprintf(output_file,"%d ",saved[0]+1);
+               }
+               else if ((norms) && (!cptexture))
+               {
+                    fprintf(output_file,"\nt %d//%d %d//%d %d//%d ",x+1,vn[x] +1,
+                                                                    y+1,vn[y] +1,
+                                                                    saved[1]+1,vn[saved[1]]+1);
+                    fprintf(output_file,"%d//%d ",saved[0]+1,vn[saved[0]]+1);
+               }
+               else if ((cptexture) && (!norms))
+               {
+                    fprintf(output_file,"\nt %d/%d %d/%d %d/%d ",x+1,vt[x] +1,
+                                                                    y+1,vt[y] +1,
+                                                                    saved[1]+1,vt[saved[1]]+1);
+                    fprintf(output_file,"%d//%d ",saved[0]+1,vt[saved[0]]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"\nt %d/%d/%d %d/%d/%d %d/%d/%d ",x+1,vt[x]+1,vn[x] +1,
+                                                                    y+1,vt[y]+1,vn[y] +1,
+                                                                    saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1);
+                    fprintf(output_file,"%d/%d/%d ",saved[0]+1,vt[saved[0]]+1,vn[saved[0]]+1);
+               }
+
+               x = Adjacent(saved[0],saved[1],temp2->pPolygon,4);
+               y = Adjacent(saved[1],saved[0],temp2->pPolygon,4);
+
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( (vt[x] == 0) || (vt[y]==0)))
+               {
+                    if (cptexture)
+                         fprintf(output_file,"\nq ");
+                    cptexture = FALSE;
+               }
+               if ((!norms) && (!cptexture))
+               {
+                    fprintf(output_file,"%d ",x+1);
+                    fprintf(output_file,"%d ",y+1);
+               }
+               else if ((norms) && (!cptexture))
+               {
+                    fprintf(output_file,"%d//%d ",x+1,vn[x]+1);
+                    fprintf(output_file,"%d//%d ",y+1,vn[y]+1);
+               }
+               else if ((cptexture) && (!norms))
+               {
+                    fprintf(output_file,"%d/%d ",x+1,vt[x]+1);
+                    fprintf(output_file,"%d/%d ",y+1,vt[y]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"%d/%d/%d ",x+1,vt[x]+1,vn[x]+1);
+                    fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1);
+               }
+
+               output1 = x;
+               output2 = y;
+          }
+          
+          else 
+          {
+               x = Adjacent(output2,output1,temp2->pPolygon,4);
+               y = Adjacent(output1,output2,temp2->pPolygon,4);
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) ))
+                    texture = FALSE;
+
+               if ((!norms) && (!texture))
+               {
+                    fprintf(output_file,"\nq %d ",x+1);
+                    fprintf(output_file,"%d ",y+1);
+               }
+               else if ((norms) && (!texture))
+               {
+                    fprintf(output_file,"\nq %d//%d ",x+1,vn[x]+1);
+                    fprintf(output_file,"%d//%d ",y+1,vn[y]+1);
+               }
+               else if ((texture) && (!norms))
+               {
+                    fprintf(output_file,"\nq %d/%d ",x+1,vt[x]+1);
+                    fprintf(output_file,"%d/%d ",y+1,vt[y]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"\nq %d/%d/%d ",x+1,vt[x]+1,vn[x]+1);
+                    fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1);
+               }
+               
+               output1 = x;
+               output2 = y;
+          }
+          
+          last_quad[0] = *(temp2->pPolygon);
+          last_quad[1] = *(temp2->pPolygon+1);
+          last_quad[2] = *(temp2->pPolygon+2);
+          last_quad[3] = *(temp2->pPolygon+3);
+     }
+}
+
+void Fast_Reset(int x)
+{
+	register int y,numverts;
+	register int front_walk, back_walk;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+     pListHead = PolFaces[x];
+	temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+	numverts = temp->nPolSize;
+     
+     front_walk = 0; 
+     back_walk = 0;          
+     resetting = TRUE;
+          
+     /* we are doing this only for quads */
+	if (numverts == 4)
+	{
+			/* 	for each face not seen yet, do North and South together
+				and East and West together
+			*/
+			for (y=0;y<2;y++)
+			{
+				/* Check if the opposite sides were seen already */
+	     		/* Find walk for the first edge */
+				front_walk = Calculate_Walks(x,y,temp);
+				/* Find walk in the opposite direction */
+				back_walk = Calculate_Walks(x,y+2,temp);
+				/* 	Now put into the data structure the numbers that
+		          	we have found
+				*/
+                    Assign_Walk(x,temp,front_walk,y,back_walk);
+				Assign_Walk(x,temp,back_walk,y+2,front_walk);
+			}
+	}
+     resetting = FALSE;
+}
+
+
+void Reset_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation,
+		int last_left,FILE *output_file,int color1,int color2,int color3,
+		BOOL start)
+{
+	register int walk = 0,count = 0;
+	int previous_edge1,previous_edge2;
+	int static last_seen = 1000;
+	F_EDGES *node;
+	ListHead *pListHead;
+	int f,t,nextvert,counter;
+     BOOL flag;
+
+ 
+     /*   Reset walks on faces, since we just found a patch */
+     if (orientation !=3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation+1);
+                previous_edge2 = *(temp2->pPolygon + orientation );
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+
+	/* only if we are going left, otherwise there will be -1 there */
+	/*Find the adjacent face to this edge */
+        
+     for (t = 0; t <=3 ; t++)
+     {
+             node = *(temp2->VertandId+t);
+              
+             if (face_id == node->edge[1])
+                f = node->edge[2];
+             else
+               f = node->edge[1];
+       
+             if (f != -1)
+                  Fast_Reset(f);
+        }
+
+        node = *(temp2->VertandId+orientation);
+        if (face_id == node->edge[1])
+             nextvert = node->edge[2];
+        else
+             nextvert = node->edge[1];
+
+	while ((last_left--) > 1)
+	{
+               
+          if (start)
+               Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE);		
+        
+          face_id = nextvert;
+          pListHead = PolFaces[nextvert];                
+          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+          if ((temp2->nPolSize != 4) && (temp2->nPolSize != 1))
+          {
+             /*   There is more than 2 polygons on the edge, and we could have
+                  gotten the wrong one
+             */
+             if (nextvert != node->edge[1])
+                  nextvert = node->edge[1];
+             else
+                  nextvert = node->edge[2];
+             pListHead = PolFaces[nextvert];          
+             temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+             node = *(temp2->VertandId+orientation);
+          }
+
+                
+         if (!start)
+         {
+             for (t = 0; t <=3 ; t++)
+             {
+                    node = *(temp2->VertandId+t);
+              
+                    if (face_id == node->edge[1])
+                         f = node->edge[2];
+                    else
+                         f = node->edge[1];
+          
+                    if (f != -1)
+                         Fast_Reset(f);
+             }
+        }
+
+
+        counter = 0;
+	   flag = TRUE;
+	   while ((counter < 3) && (flag))
+        {
+             if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                  ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                   counter++;
+             else
+                  flag = FALSE;
+        }
+
+        /* Get the IDs of the next edge */
+        if (counter < 3)
+        {
+             previous_edge1 = *(temp2->pPolygon + counter+1);
+             previous_edge2 = *(temp2->pPolygon + counter);
+        }
+        else
+        {
+             previous_edge1 = *(temp2->pPolygon + counter);
+             previous_edge2 = *(temp2->pPolygon);
+        }
+        orientation = counter;
+
+        node = *(temp2->VertandId + counter);
+	   if (node->edge[1] == nextvert)
+			nextvert = node->edge[2];
+	   else
+			nextvert = node->edge[1];
+
+        if (!reversed)
+        {
+               if (counter != 3)
+			     north = counter +1;
+		     else
+			     north = 0;
+        }
+        else
+        {
+               if (counter != 0)
+                    north = counter -1;
+               else
+                    north = 3;
+    
+        }
+     }
+if (start)
+	Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE);
+else if (nextvert != -1)       
+     Fast_Reset(nextvert);
+
+}
+
+
+int Peel_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation,
+		int last_left,FILE *output_file,int color1,int color2,int color3,
+		BOOL start, int *swaps_added, int norms, int texture)
+{
+	int end1,end2,last_id,s=0,walk = 0,count = 0;
+	int previous_edge1,previous_edge2;
+	int static last_seen = 1000;
+	F_EDGES *node;
+	ListHead *pListHead;
+	int nextvert,numverts,counter,dummy,tris=0;
+     BOOL flag;
+
+     /*   Peel the patch from the model.
+          We will try and extend off the end of each strip in the patch. We will return the
+          number of triangles completed by this extension only, and the number of swaps
+          in the extension only.
+     */	
+     patch = 0;
+     
+     if (orientation !=3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation+1);
+                previous_edge2 = *(temp2->pPolygon + orientation );
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+
+
+     walk = *(temp2->walked + orientation);
+	
+     /* only if we are going left, otherwise there will be -1 there */
+	if ((start) && ((walk+1) < last_left))
+	{
+		printf("There is an error in the left %d %d\n",walk,last_left);
+		exit(0);
+	}
+	
+     /* Find the adjacent face to this edge */
+     node = *(temp2->VertandId+orientation);
+     if (face_id == node->edge[1])
+          nextvert = node->edge[2];
+     else
+          nextvert = node->edge[1];
+	temp2->seen = last_seen;
+
+
+	while ((last_left--) > 1)
+	{
+ 		if (start)
+             tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,
+                              color1,color2,color3,FALSE,swaps_added,norms,texture);		    
+          else
+             Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);
+		
+
+          pListHead = PolFaces[nextvert];      
+          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+          numverts = temp2->nPolSize;
+	
+          if ((numverts != 4) || (temp2->seen == last_seen) 
+			||  (nextvert == -1))
+          {
+  	
+             /*   There is more than 2 polygons on the edge, and we could have
+                  gotten the wrong one
+             */
+             if (nextvert != node->edge[1])
+                  nextvert = node->edge[1];
+             else
+                  nextvert = node->edge[2];
+             pListHead = PolFaces[nextvert];
+             temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+             numverts = temp2->nPolSize;
+             if ((numverts != 4) || (temp2->seen == last_seen) )
+             {
+                  printf("Peel 2 %d\n",numverts);
+                  exit(1);
+             }
+        }
+
+        face_id = nextvert;
+        temp2->seen = last_seen;
+                
+        counter = 0;
+        flag = TRUE;
+	   while ((counter < 3) && (flag))
+        {
+             if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                  ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                   counter++;
+             else
+                  flag = FALSE;
+        }
+        /* Get the IDs of the next edge */
+        if (counter < 3)
+        {
+             previous_edge1 = *(temp2->pPolygon + counter+1);
+             previous_edge2 = *(temp2->pPolygon + counter);
+        }
+        else
+        {
+             previous_edge1 = *(temp2->pPolygon + counter);
+             previous_edge2 = *(temp2->pPolygon);
+        }
+        orientation = counter;
+		              
+	   node = *(temp2->VertandId + counter);
+	   if (node->edge[1] == nextvert)
+			nextvert = node->edge[2];
+	   else
+			nextvert = node->edge[1];
+
+	   if (!reversed)
+        {
+               if (counter != 3)
+			     north = counter +1;
+		     else
+			     north = 0;
+        }
+        else
+        {
+               if (counter != 0)
+                    north = counter -1;
+               else
+                    north = 3;
+        }
+}
+
+if (start)
+	tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,
+                        color1,color2,color3,FALSE,swaps_added,norms,texture);	
+else
+     Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);/* do the last face */
+
+last_seen++;
+
+/*    Get the edge that we came out on the last strip of the patch */
+Mark_Face(NULL,0,0,0,output_file,TRUE,&end1,&end2,&last_id,norms,texture);
+tris += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+*swaps_added = *swaps_added + s;
+return tris;
+}
+
+
+
+void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, 
+                int *cost, int *tri, int norms, int *vert_norms, int texture, int *vert_texture)
+{
+
+	register int x,y,max1,max2,numverts,face_id,flag,maximum = 25;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+	int color1 = 0, color2 = 100, color3 = 255;
+	int color = 0,larger,smaller;
+	int north_length1,last_north,left_length1,last_left,north_length2,left_length2;
+     int total_tri = 0, total_swaps = 0,last_id;
+     int end1, end2,s=0;
+     register int cutoff = 20;
+    
+     /*   Code that will find the patches. "Cutoff" will be
+          the cutoff of the area of the patches that we will be allowing. After
+          we reach this cutoff length, then we will run the local algorithm on the
+          remaining faces.
+     */
+
+	/* 	For each faces that is left find the largest possible band that we can
+		have with the remaining faces. Note that we will only be finding patches
+          consisting of quads.
+	*/
+
+vn = vert_norms;
+vt = vert_texture;
+y=1;
+*bands = 0;
+
+while ((maximum >= cutoff))
+{
+	y++;
+     maximum = -1;
+	for (x=0; x<numfaces; x++)
+	{ 
+			
+          /*   Used to produce the triangle strips */
+               
+          /* for each face, get the face */
+		pListHead = PolFaces[x];
+		temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		numverts = temp->nPolSize;
+		
+          /* we are doing this only for quads */
+		if (numverts == 4)
+		{
+			/*   We want a face that is has not been used yet,
+                    since we know that that face must be part of
+				a band. Then we will find the largest band that
+				the face may be contained in
+			*/
+			
+               /*  Doing the north and the left */
+			if ((*(temp->walked) != -1) && (*(temp->walked+3) != -1))
+				max1 = Find_Max(temp,x,0,3,&north_length1,&left_length1);
+			if ((*(temp->walked+1) != -1) && (*(temp->walked+2) != -1))
+				max2 = Find_Max(temp,x,2,1,&north_length2,&left_length2);
+			if ((max1 != (north_length1 * left_length1)) ||
+			    (max2 != (north_length2 * left_length2)))
+			{
+				printf("Max1 %d, %d %d	Max2 %d, %d %d\n",max1,north_length1,left_length1,max2,north_length2,left_length2);
+				exit(0);
+			}
+                
+                    
+               if ((max1 > max2) && (max1 > maximum))
+			{
+                    maximum = max1;
+                    face_id = x;
+                    flag = 1; 
+                    last_north = north_length1;
+                    last_left = left_length1;
+                    /* so we know we saved max1 */
+			}
+			else if ((max2 > maximum) )
+			{
+                    maximum = max2;
+                    face_id = x;
+                    flag = 2; 
+                    last_north = north_length2;
+                    last_left = left_length2;
+                    /* so we know we saved max2 */
+               }
+          }
+     }
+     if ((maximum < cutoff) && (*bands == 0))
+          return;
+     pListHead = PolFaces[face_id];
+     temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);	
+     /*   There are no patches that we found in this pass */
+     if (maximum == -1)
+          break;
+     /*printf("The maximum is  face %d area %d: lengths %d %d\n",face_id,maximum,last_north,last_left);*/
+
+     if (last_north > last_left)
+     {
+          larger = last_north;
+          smaller = last_left;
+     }
+     else
+     {
+          larger = last_left;
+          smaller = last_north;
+     }
+
+     length = larger;
+
+if (flag == 1)
+{
+	if (last_north > last_left) /*     go north sequentially */
+     {
+          total_tri += Peel_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+          Reset_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE);
+          total_swaps += s;
+     }
+    else
+    {
+         reversed = TRUE;
+         total_tri += Peel_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+         Reset_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE);
+         reversed = FALSE;
+         total_swaps += s;
+    }
+
+     
+    /*    Get the edge that we came out on the last strip of the patch */
+    Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
+    total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+    total_swaps += s;
+
+}
+else
+{
+     if (last_north > last_left)
+     {
+          total_tri += Peel_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture); 
+          Reset_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE); 
+          total_swaps += s;
+     }
+     else
+     {
+          reversed = TRUE;
+          total_tri += Peel_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+          Reset_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE);
+          reversed = FALSE;
+          total_swaps += s;
+     }
+
+     /*    Get the edge that we came out on on the patch */
+    Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
+    total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+    total_swaps += s;
+}
+
+    /*  Now compute the cost of transmitting this band, is equal to 
+        going across the larger portion sequentially,
+        and swapping 3 times per other dimension
+    */
+
+total_tri += (maximum * 2);
+*bands = *bands + smaller;
+
+}
+
+/*printf("We transmitted %d triangles,using %d swaps and %d strips\n",total_tri,
+        total_swaps, *bands);
+printf("COST %d\n",total_tri + total_swaps + *bands + *bands);*/
+*cost = total_tri + total_swaps + *bands + *bands;
+*tri = total_tri;
+added_quad = added_quad * 4;
+*swaps = total_swaps;
+}
+
+ 
+void Save_Rest(int *numfaces)
+{
+    /*  Put the polygons that are left into a data structure so that we can run the
+        stripping code on it.
+    */
+    register int x,y=0,numverts;
+    ListHead *pListHead;
+    PF_FACES temp=NULL;
+
+    for (x=0; x<*numfaces; x++)
+    { 
+			/* for each face, get the face */
+			pListHead = PolFaces[x];
+			temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+			numverts = temp->nPolSize;
+               /*  If we did not do the face before add it to data structure with new 
+                   face id number
+               */
+               if (numverts != 1)
+               {
+                   CopyFace(temp->pPolygon,numverts,y+1,temp->pNorms);
+                   y++;
+               }
+               /*   Used it, so remove it */
+               else
+                    RemoveList(pListHead,(PLISTINFO) temp);
+
+    }
+    *numfaces = y;
+}
+
+void Assign_Walk(int lastvert,PF_FACES temp2, int front_walk,int y,
+				int back_walk)
+{
+/*      Go back and do the walk again, but this time save the lengths inside
+        the data structure.
+        y was the starting edge number for the front_walk length
+        back_walk is the length of the walk along the opposite edge
+ */
+        int previous_edge1, previous_edge2;
+        register int walk = 0,nextvert,numverts,counter;
+        BOOL flag;
+        F_EDGES *node;
+        ListHead *pListHead;
+        register int total_walk, start_back_walk;
+        static int seen = 0;
+        static BOOL first = TRUE;         
+        int test;
+        BOOL f = TRUE, wrap = FALSE, set = FALSE;
+             test = lastvert;
+
+        /*     In the "Fast_Reset" resetting will be true */
+        if ((resetting) && (first))
+        {
+             seen = 0;
+             first = FALSE;
+        }
+
+        seen++;
+        total_walk = front_walk + back_walk;
+        start_back_walk = back_walk;
+        /*     Had a band who could be a cycle  */
+        if (front_walk == back_walk)
+             wrap = TRUE;
+             
+        /* Find the edge that we are currently on */
+        if (y != 3)
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon + y + 1);
+        }
+        else
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon);
+        }
+
+        /* Assign the lengths */
+	   if (y < 2) 
+	   {
+                *(temp2->walked+y) = front_walk--;
+         		 *(temp2->walked+y+2) = back_walk++;
+    	   }
+	   else
+	   {				
+               *(temp2->walked+y) = front_walk--;
+              	*(temp2->walked+y-2) = back_walk++;
+  	   }
+
+	   /*Find the adjacent face to this edge */
+        node = *(temp2->VertandId+y);                   
+
+        if (node->edge[2] != lastvert)
+          nextvert = node->edge[2];
+        else
+          nextvert = node->edge[1];
+                                       
+        temp2->seen3 = seen;
+        
+        /* Keep walking in this direction until we cannot do so */
+        while ((nextvert != lastvert) && (nextvert != -1) && (front_walk >= 0))
+        {
+		     walk++;
+               pListHead = PolFaces[nextvert];
+               
+               temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+               numverts = temp2->nPolSize;
+               if ((numverts != 4))
+               {
+                    nextvert = -1;
+                    /* Don't include this face in the walk */
+                    walk--;
+               }
+               else
+               {
+                    /* Find edge that is not adjacent to the previous one */
+                    counter = 0;
+                    flag = TRUE;
+                    while ((counter < 3) && (flag))
+                    {
+                         if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                               (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                              ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                               (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                              counter++;
+                         else
+                              flag = FALSE;
+                    }
+                    /* Get the IDs of the next edge */
+                    if (counter < 3)
+                    {
+                         previous_edge1 = *(temp2->pPolygon + counter);
+                         previous_edge2 = *(temp2->pPolygon + counter + 1);
+                    }
+                    else
+                    {
+                         previous_edge1 = *(temp2->pPolygon + counter);
+                         previous_edge2 = *(temp2->pPolygon);
+                    }
+               
+
+		          /*      Put in the walk lengths */
+		          if (counter < 2)
+		          {
+                        if (((*(temp2->walked + counter) >= 0)
+			          || (*(temp2->walked +counter + 2) >= 0)))
+			          {
+				          if ((resetting == FALSE) && ((temp2->seen3) != (seen-1)))
+				          {
+					          /*   If there are more than 2 polygons adjacent
+                                        to an edge then we can be trying to assign more than
+                                        once. We will save the smaller one
+                                   */
+                                   temp2->seen3 = seen;
+                                   if ( (*(temp2->walked+counter) <= front_walk) &&
+                                        (*(temp2->walked+counter+2) <= back_walk) )
+                                        return;
+                                   if (*(temp2->walked+counter) > front_walk)
+                                       *(temp2->walked+counter) = front_walk--;
+                                   else
+                                        front_walk--;
+                                   if (*(temp2->walked+counter+2) > back_walk)
+                                       *(temp2->walked+counter+2) = back_walk++;
+                                   else
+                                        back_walk++;
+				          }
+				          else if (resetting == FALSE)
+				          {
+					          /* if there was a cycle then all lengths are the same */
+					          walk--;
+					          back_walk--;
+					          front_walk++;
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                              else if (((temp2->seen3 == (seen-1))
+                                   && (wrap) && (walk == 1)) || (set))
+                              {
+					          /* if there was a cycle then all lengths are the same */
+					          set = TRUE;
+                                   walk--;
+					          back_walk--;
+					          front_walk++;
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                              else
+                              {
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                        } /* if was > 0 */	
+                        else
+                        {
+                             temp2->seen3 = seen;
+                             *(temp2->walked+counter) = front_walk--;
+                             *(temp2->walked+counter+2) = back_walk++;
+                        }
+                    }
+		
+               else
+               {
+                    if (((*(temp2->walked + counter) >= 0 )
+                        || (*(temp2->walked +counter - 2) >= 0)) )
+                    {
+                         if ((temp2->seen3 != (seen-1))  && (resetting == FALSE))
+                         {
+                              /*   If there are more than 2 polygons adjacent
+                                   to an edge then we can be trying to assign more than
+                                   once. We will save the smaller one
+                              */
+                              temp2->seen3 = seen;
+                              if ( (*(temp2->walked+counter) <= front_walk) &&
+                                   (*(temp2->walked+counter-2) <= back_walk) )
+                                   return;
+                              if (*(temp2->walked+counter) > front_walk)
+                                   *(temp2->walked+counter) = front_walk--;
+                              else
+                                   front_walk--;
+                              if (*(temp2->walked+counter-2) > back_walk)
+                                   *(temp2->walked+counter-2) = back_walk++;
+                              else
+                                   back_walk++;
+                        	}
+				     else if (resetting == FALSE)
+	     			{
+     					walk--;
+		     			back_walk--;
+			     		front_walk++;
+	                         temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+                         else if (((temp2->seen3 == (seen-1)) && (walk == 1) && (wrap))
+                              || (set))
+                         {
+					     /* if there was a cycle then all lengths are the same */
+					     set = TRUE;
+                              walk--;
+					     back_walk--;
+					     front_walk++;
+                              temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+                         else
+                         {
+                              temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+     			}
+                    else
+                    {
+                         temp2->seen3 = seen;
+                         *(temp2->walked+counter) = front_walk--;
+                         *(temp2->walked+counter-2) = back_walk++;
+                    }
+		                
+  		     } 
+		     if (nextvert != -1)
+		     {
+			     node = *(temp2->VertandId + counter);
+                	if (node->edge[1] == nextvert)
+                        	nextvert = node->edge[2];
+                	else
+                        	nextvert = node->edge[1];
+               }
+		
+     }
+}
+if ((EVEN(seen)) )
+     seen+=2;
+}
+
+void Save_Walks(int numfaces)
+{
+	int x,y,numverts;
+	int front_walk, back_walk;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	for (x=0; x<numfaces; x++)
+	{ 
+		/* for each face, get the face */
+		pListHead = PolFaces[x];
+		temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		numverts = temp->nPolSize;
+		front_walk = 0; 
+          back_walk = 0;
+
+          /* we are finding patches only for quads */
+		if (numverts == 4)
+		{
+			/* 	for each face not seen yet, do North and South together
+				and East and West together
+			*/
+			for (y=0;y<2;y++)
+			{
+				/*   Check if the opposite sides were seen already from another
+                         starting face, if they were then there is no need to do the walk again
+                    */
+
+				if 	( ((*(temp->walked+y) == -1) &&
+					(*(temp->walked+y+2) == -1) ))
+				{
+					/* Find walk for the first edge */
+					front_walk = Calculate_Walks(x,y,temp);
+					/* Find walk in the opposite direction */
+					back_walk = Calculate_Walks(x,y+2,temp);
+					/* 	Now put into the data structure the numbers that
+						we have found
+					*/
+                         Assign_Walk(x,temp,front_walk,y,back_walk);
+					Assign_Walk(x,temp,back_walk,y+2,front_walk);
+	     		}
+			}
+		}
+	}
+}
+
+
diff --git a/Stripe_u/options.c b/Stripe_u/options.c
new file mode 100644
index 000000000..7322d937c
--- /dev/null
+++ b/Stripe_u/options.c
@@ -0,0 +1,181 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: options.c
+     This file contains routines that are used to determine the options
+     that were specified by the user
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "options.h"
+#include "global.h"
+
+int power_10(int power)
+{
+	/*	Raise 10 to the power */
+	register int i,p;
+
+	p = 1;
+	for (i = 1; i <= power; ++i)
+		p = p * 10;
+	return p;
+}
+
+float power_negative(int power)
+{
+     /*   Raise 10 to the negative power */
+
+     register int i;
+     float p;
+     
+     p = (float)1;
+     for (i = 1; i<=power; i++)
+          p = p * (float).1;
+     return p;
+}
+
+float convert_array(int num[],int stack_size)
+{
+	/* Convert an array of characters to an integer */
+	
+	register int counter,c;
+	float temp =(float)0.0;
+
+	for (c=(stack_size-1), counter = 0; c>=0; c--, counter++)
+     {
+          if (num[c] == -1)
+          /*   We are at the decimal point, convert to decimal
+               less than 1
+          */
+          {
+               counter = -1;
+               temp = power_negative(stack_size - c - 1) * temp;
+          }
+          else 
+               temp += power_10(counter) * num[c];
+     }
+			
+	return(temp);
+}
+
+float get_options(int argc, char **argv, int *f, int *t, int *tr, int *group)
+{
+     char c;
+     int count = 0;
+     int buffer[MAX1];
+     int next = 0;
+     /*    tie variable */
+     enum tie_options tie = FIRST;
+     /*   triangulation variable */
+     enum triangulation_options triangulate = WHOLE;
+     /*   normal difference variable (in degrees) */
+     float norm_difference = (float)360.0;
+     /*   file-type variable */
+     enum file_options file_type = ASCII;
+
+     /*      User has the wrong number of options */
+	if ((argc > 5) || (argc < 2))
+	{
+		printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] file_name\n");
+		exit(0);
+	}
+	
+     /* Interpret the options specified */
+	while (--argc > 0 && (*++argv)[0] == '-')
+     {
+          /*   At the next option that was specified */
+          next = 1;
+          while (c = *++argv[0])
+			switch (c)
+		{
+				case 'f': 
+					/*      Use the first polygon we see. */
+                         tie = FIRST;
+					break;
+				
+				case 'r':
+					/*      Randomly choose the next polygon */
+                         tie = RANDOM;
+					break;
+
+				case 'a':
+					/*      Alternate direction in choosing the next polygon */
+                         tie = ALTERNATE;
+					break;
+
+				case 'l':
+					/*      Use lookahead to choose the next polygon */
+                         tie = LOOK;
+					break;
+
+				case 'q':
+					/*  Try to reduce swaps */
+                         tie = SEQUENTIAL;
+					break;
+
+				case 'p':
+					/*      Use partial triangulation of polygons */
+                         triangulate = PARTIAL;
+					break;
+
+				case 'w':
+					/*      Use whole triangulation of polygons */
+                         triangulate = WHOLE;
+					break;
+
+                    case 'b':
+                         /*      Input file is in binary */
+                         file_type = BINARY;
+                         break;
+
+                    case 'g':
+                         /*   Strips will be grouped according to the groups in 
+                              the data file. We will have to restrict strips to be
+                              in the grouping of the data file.
+                         */
+                         *group = 1;
+  		    
+                         /*	Get each the value of the integer */
+                         /*	We have an integer */
+                    default:
+                         if ((c >= '0') && (c <= '9'))
+                         {
+                              /*   More than one normal difference specified, use the last one */
+                              if (next == 1)
+                              {
+                                   count = 0;
+                                   next = 0;
+                              }
+                              buffer[count++] = ATOI(c);
+                         }
+                              /*   At the decimal point */
+                         else if (c == '.')
+                         {
+                              /*   More than one normal difference specified, use the last one */
+                              if (next == 1)
+                              {
+                                   count = 0;
+                                   next = 0;
+                              }
+                              buffer[count++] = -1;
+                         }
+                         else 
+                              break;
+		}
+     }
+     /*   Convert the buffer of characters to a floating pt integer */
+     if (count != 0) 
+          norm_difference = convert_array(buffer,count);
+     *f = file_type;
+     *t = tie;
+     *tr = triangulate;
+     return norm_difference;
+}
diff --git a/Stripe_u/options.h b/Stripe_u/options.h
new file mode 100644
index 000000000..055d33ea7
--- /dev/null
+++ b/Stripe_u/options.h
@@ -0,0 +1,17 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: options.h
+-----------------------------------------------------------------------*/
+
+float get_options();
+enum file_options {ASCII,BINARY};
+enum tie_options {FIRST, RANDOM, ALTERNATE, LOOK, SEQUENTIAL};
+enum triangulation_options {PARTIAL,WHOLE};
+     
diff --git a/Stripe_u/output.c b/Stripe_u/output.c
new file mode 100644
index 000000000..d6c30f613
--- /dev/null
+++ b/Stripe_u/output.c
@@ -0,0 +1,582 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: output.c
+     This file contains routines that are finding and outputting the
+     strips from the local algorithm
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "partial.h"
+#include "sturcts.h"
+#include "ties.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+#include "free.h"
+
+int *vn;
+int *vt;
+int norm;
+int text;
+
+int Finished(int *swap, FILE *output, BOOL global)
+{
+     /*   We have finished all the triangles, now is time to output to
+	     the data file. In the strips data structure, every three ids
+	     is  a triangle. Now we see whether we can swap, or make a new strip
+	     or continue the strip, and output the data accordingly to the
+	     data file. 
+     */
+     register int start_swap = 0;
+     int num,x,vertex1,vertex2;
+     ListHead *pListHead;
+     int id[2],other1,other2,index = 0,a,b,c;
+     P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6;
+     BOOL cptexture;
+     *swap =0;
+    
+     cptexture = text;
+     pListHead = strips[0];
+     if (pListHead == NULL)
+         return 0;
+
+     num = NumOnList(pListHead);
+     /*printf ("There are %d triangles in the extend\n",num/3);*/
+
+     /* Go through the list triangle by triangle */
+	temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
+	temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
+	temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
+	
+      /*   Next triangle for lookahead */
+     temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3);
+	  
+
+     /*    There is only one polygon in the strip */
+     if (temp4 == NULL)
+     {
+           /*   Data might be mixed and we do not have textures for some of the vertices */
+           if ((text) &&  (vt[temp3->face_id] == 0))
+                    cptexture = FALSE;
+           if ((norm) && (!cptexture))
+                fprintf(output,"%d//%d %d//%d %d//%d",temp3->face_id+1,vn[temp3->face_id]+1,
+                                temp2->face_id+1,vn[temp2->face_id]+1,
+                                temp1->face_id+1,vn[temp1->face_id]+1);
+           else if ((cptexture) && (!norm))
+                fprintf(output,"%d/%d %d/%d %d/%d",temp3->face_id+1,vt[temp3->face_id]+1,
+                        temp2->face_id+1,vt[temp2->face_id]+1,
+                        temp1->face_id+1,vt[temp1->face_id]+1);
+           else if ((cptexture)&& (norm))
+                fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d",temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1,
+                        temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1,
+                        temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1);
+           else 
+                fprintf(output,"%d %d %d",temp3->face_id+1,temp2->face_id+1,temp1->face_id+1);
+           Free_Strips();
+	      return 1;
+	  }
+	  
+	  /*    We have a real strip */
+	  temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4);
+	  temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5);
+	  
+	  if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL))
+	  {
+	       printf("There is an error in the output of the triangles\n");
+	       exit(0);
+	  }
+
+	  /*   Find the vertex in the first triangle that is not in the second */
+	  vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id,temp4->face_id,temp5->face_id,temp6->face_id,&other1,&other2);
+	  /*    Find the vertex in the second triangle that is not in the first */
+	  vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
+
+	  /* Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle */
+       temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6);
+	  temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7);
+	  temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8);
+       
+       if (temp1 != NULL)
+          other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a);
+	   
+	  id[index] = vertex1; index = !index;
+	  id[index] = other1; index = !index;
+	  id[index] = other2; index = !index;
+
+	  a = temp4->face_id; 
+	  b = temp5->face_id; 
+	  c = temp6->face_id;
+
+      /*    If we need to rearrange the first sequence because otherwise
+            there would have been a swap.
+      */
+
+      if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0))
+           cptexture = FALSE;
+      if ((norm) && (!cptexture))
+           fprintf(output,"%d//%d %d//%d %d//%d ",vertex1+1,vn[vertex1]+1,other1+1,vn[other1]+1,
+                                                  other2+1,vn[other2]+1);
+      else if ((cptexture) && (!norm))
+           fprintf(output,"%d/%d %d/%d %d/%d ",vertex1+1,vt[vertex1]+1,other1+1,vt[other1]+1,
+                                               other2+1,vt[other2]+1);
+      else if ((cptexture) && (norm))
+           fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d ",vertex1+1,vt[vertex1]+1,vn[vertex1]+1,
+                                                        other1+1,vt[other1]+1,vn[other1]+1,
+                                                        other2+1,vt[other2]+1,vn[other2]+1);
+      else
+           fprintf(output,"%d %d %d ",vertex1+1,other1+1,other2+1);
+
+
+	 for (x = 6; x < num ; x = x+3)
+	  {
+
+	      /*    Get the next triangle */
+	      temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x);
+	      temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+1);
+	      temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+2);
+
+           /*    Error checking */
+	      if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c)))
+	      {
+		     /*   If we used partial we might have a break in the middle of a strip */
+		     fprintf(output,"\nt ");
+	          /*   Find the vertex in the first triangle that is not in the second */
+	          vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
+	          /*    Find the vertex in the second triangle that is not in the first */
+	          vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
+	   
+	          id[index] = vertex1; index = !index;
+	          id[index] = other1; index = !index;
+	          id[index] = other2; index = !index;
+	      }
+
+	      if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL))
+	      {
+		  printf("There is an error in the triangle list \n");
+		  exit(0);
+	      }
+         
+           if ((id[0] == id[1]) || (id[0] == vertex2))
+                continue;
+
+           if ((member(id[index],temp1->face_id,temp2->face_id,temp3->face_id)))
+           {
+                if ((text) && ( vt[id[index]]==0))
+                     cptexture = FALSE;
+                if ((!norm) && (!cptexture))
+                     fprintf(output,"%d ",id[index]+1);
+                else if ((norm) && (!cptexture))
+                     fprintf(output,"%d//%d ",id[index]+1,vn[id[index]]+1);
+                else if ((!norm) && (cptexture))
+                     fprintf(output,"%d/%d ",id[index]+1,vt[id[index]]+1);
+                else
+                     fprintf(output,"%d/%d/%d ",id[index]+1,vt[id[index]]+1,vn[id[index]]+1);
+                index = !index;
+                *swap = *swap + 1;
+           }
+           
+           if ((text) && ( vt[vertex2]==0))
+                cptexture = FALSE;
+	      if ((!norm) && (!cptexture))
+                fprintf(output,"\nq %d ",vertex2+1);
+           else if ((norm) && (!cptexture))
+                fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1);
+           else if ((!norm) && (cptexture))
+                fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1);
+           else
+                fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
+
+	      id[index] = vertex2; index = !index;
+
+	      /*    Get the next vertex not in common */
+	      vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
+	      a = temp1->face_id;
+	      b = temp2->face_id;
+	      c = temp3->face_id;
+	  }
+	  /*    Do the last vertex */
+       if ((text) && (vt[vertex2]==0))
+       {
+            if (cptexture)
+                 fprintf(output,"\nq ");
+            cptexture = FALSE;
+       }
+       if ((!norm) && (!cptexture))
+            fprintf(output,"%d ",vertex2+1);
+       else if ((norm) && (!cptexture))
+            fprintf(output,"%d//%d ",vertex2+1,vn[vertex2]+1);
+       else if ((!norm) && (cptexture))
+            fprintf(output,"%d/%d ",vertex2+1,vt[vertex2]+1);
+       else
+            fprintf(output,"%d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
+
+	  
+	 Free_Strips();
+      return (num/3);	      
+}
+
+void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, int color2, int color3,BOOL end)
+{
+     /*   We will save everything into a list, rather than output at once,
+	     as was done in the old routine. This way for future modifications
+	     we can change the strips later on if we want to.
+     */
+
+    int temp1,temp2,temp3;
+    
+    /*  Make sure we do not have an error */
+    /*    There are degeneracies in some of the files */
+	if ( (id1 == id2) || (id1 == id3) || (id2 == id3))
+	{
+		printf("Degenerate triangle %d %d %d\n",id1,id2,id3);
+		exit(0);
+	}
+     else
+     {
+          Last_Edge(&temp1,&temp2,&temp3,0);
+	     Add_Id_Strips(id1,end);
+	     Add_Id_Strips(id2,end);
+	     Add_Id_Strips(id3,end);
+	     Last_Edge(&id1,&id2,&id3,1);
+     }
+}
+
+
+int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket,
+					ListHead *pListHead, BOOL first, int *swaps,
+                         FILE *bands,int color1,int color2,int color3,BOOL global, BOOL end)
+{
+	ListHead *pListFace;
+	PF_FACES face;
+	P_ADJACENCIES pfNode;
+	static BOOL begin = TRUE;
+	int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
+	P_ADJACENCIES lpListInfo; 
+     int ties=0;
+     int  tie = SEQUENTIAL;
+     
+     /* We have a polygon to output, the id is face id, and the number
+	   of adjacent polygons to it is bucket. This routine extends the patches from
+        either end to make longer triangle strips.
+	*/
+                
+                   
+     /*  Now get the edge */
+     Last_Edge(&e1,&e2,&e3,0);
+    
+     /*  Get the polygon with id face_id */
+	pListFace  = PolFaces[face_id];
+	face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     /*  We can't go any more */
+     if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global))) /* if global, then we are still doing patches */
+     {
+        /*     Remove it from the list so we do not have to waste
+               time visiting it in the future, or winding up in an infinite loop
+               if it is the first on that we are looking at for a possible strip
+        */
+        if (face->nPolSize == 1)
+             RemoveList(pListHead,(PLISTINFO) temp);
+        if (first)
+             return 0;
+        else
+             return (Finished(swaps,bands,global));
+    }
+
+    if (face->nPolSize == 3)
+    {
+		/*      It is already a triangle */
+		if (bucket == 0)
+		{
+			/*      It is not adjacent to anything so we do not have to
+	 			   worry about the order of the sides or updating adjacencies
+			*/
+			    
+	          next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
+		                              e1,e2,e3,&other1,&other2);  
+			face->nPolSize = 1;
+                       
+               /* If this is the first triangle in the strip */
+               if ((e2 == 0) && (e3 ==0))
+               {
+                    e2 = other1;
+                    e3 = other2;
+               }
+
+               Output_Tri(e2,e3,next_face_id,bands,color1,color2,color3,end);
+               RemoveList(pListHead,(PLISTINFO) temp);
+               return (Finished(swaps,bands,global));
+          }
+		
+        
+          /*  It is a triangle with adjacencies. This means that we
+		    have to:
+				1. Update the adjacencies in the list, because we are
+					using this polygon and it will be deleted.
+				2. Get the next polygon.
+		*/
+		else
+		{
+			/*   Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current triangle.
+			*/
+            
+               next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+               {
+                       Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
+                                  color2,color3,end);
+                       face->nPolSize = 1;
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       return (Finished(swaps,bands,global));
+               }
+		  
+               old_face = next_face_id;
+		     /*      Find the other vertex to transmit in the triangle */
+		     e3 = Return_Other(face->pPolygon,e1,e2);
+	          Last_Edge(&other1,&other2,&other3,0);
+	    
+	          if ((other2 != 0) && (other3 != 0))
+	          {
+	              /*   See which vertex in the output edge is not in the input edge */
+	              if ((e1 != other2) && (e1 != other3))
+		            e3 = e1;
+	              else if ((e2 != other2) && (e2 != other3))
+		             e3 = e2;
+	              else
+	              {
+		            printf("There is an error in the tri with adj\n");
+		            exit(0);
+	              }
+
+	              /*   See which vertex of the input edge is not in the output edge */
+	              if ((other2 != e1) && (other2 != e2))
+	              {
+		            other1 = other2;
+		            other2 = other3;
+	              }
+	              else if ((other3 != e1) && (other3 != e2))
+		            other1 = other3;
+	              else
+	              {
+		            printf("There is an error in getting the tri with adj\n");
+		            exit(0);
+	              }
+		      
+	          }
+               else
+               {
+                  /*     We are the first triangle in the strip and the starting edge
+                         has not been set yet
+                  */
+                  /*  Maybe we deleted something in a patch and could not find an adj polygon */
+                  if (next_face_id == -1)
+                  {
+                       Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
+                                  color2,color3,end);
+                       face->nPolSize = 1;
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       return (Finished(swaps,bands,global));
+                  }
+
+                  other1 = e3;
+                  e3 = e2;
+                  other2 = e1;
+               }
+	   
+	          /*   At this point the adjacencies have been updated  and we
+				have the next polygon id 
+	          */
+
+               Output_Tri(other1,other2,e3,bands,color1,color2,color3,end);
+               face->nPolSize = 1;
+		     RemoveList(pListHead,(PLISTINFO) temp);
+		     begin = FALSE;
+	          
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+                    return (Finished(swaps,bands,global));
+        
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+		     {
+			     printf("We deleted the next face 4%d\n",next_face_id);
+			     exit(0);
+	          }
+
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				(int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+			{
+				printf("There is an error finding the next polygon3 %d\n",next_face_id);
+				exit(0);
+			}
+			return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
+					             pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
+
+		}
+	}
+
+	else
+	{
+		/*   It is not a triangle, we have to triangulate it .
+			Since it is not adjacent to anything we can triangulate it
+			blindly
+		*/
+		if (bucket == 0)
+		{
+		          /*   It is the first polygon in the strip, therefore there is no
+                         input edge to start with.
+                    */
+                    if ((e2 == 0) && (e3 ==0))
+                       Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
+			                          TRUE,1,color1,color2,color3);
+
+                    else
+                       Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
+			                          FALSE,1,color1,color2,color3);
+
+			     RemoveList(pListHead,(PLISTINFO) temp);
+			               
+                    /*      We will be at the beginning of the next strip. */
+                    face->nPolSize = 1;
+                    return (Finished(swaps,bands,global));
+		}
+
+
+		else
+		{
+			
+             
+               /*  WHOLE triangulation */
+	          /*  It is not a triangle and has adjacencies. 
+				This means that we have to:
+				1. Triangulate this polygon, not blindly because
+					we have an edge that we want to come out on, that
+					is the edge that is adjacent to a polygon with the
+					least number of adjacencies. Also we must come in
+					on the last seen edge.
+				2. Update the adjacencies in the list, because we are
+					using this polygon .
+				3. Get the next polygon.
+			*/
+			/*      Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current polygon.
+			*/
+				
+               next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
+	    
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+               {
+ 
+                    /*   If we are at the first polygon in the strip and there is no input
+                         edge, then begin is TRUE
+                    */
+                    if ((e2 == 0) && (e3 == 0))
+                         Blind_Triangulate(face->nPolSize,face->pPolygon,
+			                            bands,TRUE,1,color1,color2,color3);
+
+                    else
+                         Blind_Triangulate(face->nPolSize,face->pPolygon,
+			                            bands,FALSE,1,color1,color2,color3);
+
+		          RemoveList(pListHead,(PLISTINFO) temp);
+		              
+    	               /*      We will be at the beginning of the next strip. */
+                    face->nPolSize = 1;
+                    return (Finished(swaps,bands,global));
+               }
+
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+	          {
+			    printf("We deleted the next face 6 %d %d\n",next_face_id,face_id);
+			    exit(0);
+		     }
+			
+			Non_Blind_Triangulate(face->nPolSize,face->pPolygon, 
+				                 bands,next_face_id,face_id,1,color1,color2,color3);
+				     
+               RemoveList(pListHead,(PLISTINFO) temp);
+               begin = FALSE;
+               face->nPolSize = 1;
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+					   (int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+		     {
+				printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
+				exit(0);
+			}
+			return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
+					             pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
+		}
+
+	}
+    Last_Edge(&e1,&e2,&e3,0);
+
+}       
+
+
+int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands,
+                int color1,int color2,int color3,int *vert_norm, int normals,
+                int *vert_texture, int texture)
+{
+    int dummy=0,next_bucket;
+    P_ADJACENCIES pfNode,lpListInfo;
+    ListHead *pListHead;
+
+    /*    Try to extend backwards off of the local strip that we just found */
+    
+    vn = vert_norm;
+    vt = vert_texture;
+    norm = normals;
+    text = texture;
+
+    *swaps = 0;
+    /*	Find the face that is adjacent to the edge and is not the
+		current face.
+    */
+    face_id = Find_Face(face_id, e1, e2,&next_bucket);
+    if (face_id == -1)
+          return 0;
+			
+    pListHead = array[next_bucket];
+    pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+    if ( pfNode )
+		pfNode->face_id = face_id;
+    lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+		       (int (*)(void *,void *)) (Compare)));
+    if (lpListInfo == NULL)
+    {
+		printf("There is an error finding the next polygon3 %d\n",face_id);
+		exit(0);
+    }
+    Last_Edge(&dummy,&e1,&e2,1);
+    
+    /*  Find a strip extending from the patch and return the cost */
+    return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps,bands,color1,color2,color3,TRUE,TRUE));
+}
+
+
diff --git a/Stripe_u/output.h b/Stripe_u/output.h
new file mode 100644
index 000000000..d9aed50a9
--- /dev/null
+++ b/Stripe_u/output.h
@@ -0,0 +1,26 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: output.h
+-----------------------------------------------------------------------*/
+
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_Tri();
+void Sgi_Test();
+int Polygon_Output();
+void Last_Edge();
+void Extend_Backwards();
+int Finished();
+int Extend_Face();
+void Fast_Reset();
+
+
diff --git a/Stripe_u/outputex.c b/Stripe_u/outputex.c
new file mode 100644
index 000000000..48d4da147
--- /dev/null
+++ b/Stripe_u/outputex.c
@@ -0,0 +1,518 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: outputex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "outputex.h"
+#include "triangulatex.h"
+#include "polverts.h"
+#include "ties.h"
+#include "partial.h"
+#include "sturctsex.h"
+#include "options.h"
+#include "output.h"
+#include "common.h"
+#include "util.h"
+
+
+void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, int flag,
+		int where)
+{
+     /*   We will save everything into a list, rather than output at once,
+	  as was done in the old routine. This way for future modifications
+	  we can change the strips later on if we want to.
+     */
+
+    int swap,temp1,temp2,temp3;
+    static int total=0;
+    static int tri=0;
+    static int strips = 0;
+    static int cost = 0;
+    
+    if (flag == -20)
+    {
+         cost = cost + where+total+tri+strips+strips;
+         printf("We will need to send %d vertices to the renderer\n",cost);
+         total = 0;
+         tri = 0;
+         strips = 0;
+         return ;
+    }
+
+
+    if (flag == -10)
+	 /*    We are finished, now is time to output the triangle list
+	 */
+    {
+          fprintf(output,"\nt ");
+          tri = tri + Finished(&swap,output,FALSE);
+          total = total + swap;
+          strips++;
+          /*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/
+    }
+       
+    else
+    {
+	 Last_Edge(&temp1,&temp2,&temp3,0);
+	 Add_Id_Strips(id1,where);
+	 Add_Id_Strips(id2,where);
+	 Add_Id_Strips(id3,where);
+	 Last_Edge(&id1,&id2,&id3,1);
+    }
+}
+
+		
+
+
+void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, 
+		      int tie, int triangulate, 
+		      int swaps,int *next_id)
+{
+    /*  We just made a strip, now we are going to see if we can extend
+	   backwards from the starting face, which had 2 or more adjacencies
+	   to start with.
+    */
+    int bucket,next_face,num,x,y,z,c,d=1,max,f;
+    ListHead *pListFace;
+    PF_FACES face;
+    P_ADJACENCIES temp;
+
+    /*  Get the first triangle that we have saved the the strip data 
+	   structure, so we can see if there are any polygons adjacent
+	   to this edge or a neighboring one
+    */
+    First_Edge(&x,&y,&z); 
+    
+    pListFace  = PolFaces[face_id];
+    face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+    num = face->nPolSize;
+
+    /*  Go through the edges to see if there is an adjacency
+	   with a vertex in common to the first triangle that was
+	   outputted in the strip. (maybe edge was deleted....)
+    */
+    for (c=0; c<num ; c++)
+    {
+	   
+	if ( (c != (num-1)) && 
+	     (( (*(face->pPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) ||
+		(*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x)))
+	{
+	    /*  Input edge is still there see if there is an adjacency */
+	    next_face = Find_Face(face_id, x, y, &bucket);
+	    if (next_face == -1)
+		/*  Could not find a face adjacent to the edge */
+	     	break;
+	    pListFace = array[bucket];
+	    max = NumOnList(pListFace);
+	    for (f=0;;f++)
+	    {
+			temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);	
+		     if (temp->face_id == next_face)
+		     {
+		          Last_Edge(&z,&y,&x,1);
+		          Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
+        			  		       output,strip,ties,tie,triangulate,swaps,next_id,0);
+		          return;
+		     }
+
+			if (temp == NULL)
+			{
+					printf("Error in the new buckets%d %d %d\n",bucket,max,0);
+					exit(0);
+			}
+	    }
+
+	}
+	else if ( (c == (num -1)) &&
+	   ( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) ||
+	      (*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x)))
+	{
+	     next_face = Find_Face(face_id,x,y,&bucket);
+	     if (next_face == -1)
+		/*  Could not find a face adjacent to the edge */
+		     break;
+		pListFace = array[bucket];
+		max = NumOnList(pListFace);
+		for (f=0;;f++)
+		{
+			temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);
+		     if (temp->face_id == next_face)
+		     {
+		          Last_Edge(&z,&y,&x,1);
+		          Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
+				   	            output,strip,ties,tie,triangulate,swaps,next_id,0);
+		          return;
+		     }
+
+			if (temp == NULL)
+			{
+					printf("Error in the new buckets%d %d %d\n",bucket,max,0);
+					exit(0);
+			}
+	    }
+	}
+    
+    }
+
+}
+
+void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
+					ListHead *pListHead, FILE *output, FILE *strips,
+					int *ties, int tie, 
+					int triangulate, int swaps,
+					int *next_id, int where)
+{
+	ListHead *pListFace;
+	PF_FACES face;
+	P_ADJACENCIES pfNode;
+	static BOOL begin = TRUE;
+	int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
+	P_ADJACENCIES lpListInfo; 
+
+	/*      We have a polygon to output, the id is face id, and the number
+		   of adjacent polygons to it is bucket.
+	*/
+
+     Last_Edge(&e1,&e2,&e3,0);
+    
+     /*  Get the polygon with id face_id */
+	pListFace  = PolFaces[face_id];
+	face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     if (face->nPolSize == 3)
+	{
+		/*      It is already a triangle */
+		if (bucket == 0)
+		{
+			/*      It is not adjacent to anything so we do not have to
+				   worry about the order of the sides or updating adjacencies
+			*/
+			    
+	          Last_Edge(&e1,&e2,&e3,0);
+	          next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
+		                              e1,e2,e3,&other1,&other2);
+	          /*  No input edge, at the start */
+	          if ((e2 ==0) && (e3 == 0))
+	          {
+		          e2 = other1;
+		          e3 = other2;
+	          }
+	    
+			Output_TriEx(e2,e3,next_face_id,strips,-1,begin,where);
+			RemoveList(pListHead,(PLISTINFO) temp);
+			/*      We will be at the beginning of the next strip. */
+			begin = TRUE;
+		}
+		/*      It is a triangle with adjacencies. This means that we
+			   have to:
+				1. Update the adjacencies in the list, because we are
+					using this polygon and it will be deleted.
+				2. Get the next polygon.
+		*/
+		else
+		{
+			/*   Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current triangle.
+			*/
+            
+               next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+			old_face = next_face_id;
+				        
+              /*  Break the tie,  if there was one */
+		    if (tie != FIRST)
+				old_face = Get_Next_Face(tie,face_id,triangulate);
+
+              if (next_face_id == -1)
+              {
+                    Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+	     		    triangulate,swaps,next_id,where);
+                    return;
+              }
+
+
+	        /*  We are using a different face */
+	        if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON))
+             {
+		        next_face_id = old_face;
+		        /*  Get the new output edge, since e1 and e2 are for the
+		            original next face that we got.
+		        */
+                  e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id,face->nPolSize,0,0);
+	        }
+			
+		   /*      Find the other vertex to transmit in the triangle */
+		   e3 = Return_Other(face->pPolygon,e1,e2);
+	        Last_Edge(&other1,&other2,&other3,0);
+	    
+	        if ((other1 != 0) && (other2 != 0))
+	        {
+	               /*   See which vertex in the output edge is not in the input edge */
+	               if ((e1 != other2) && (e1 != other3))
+		               e3 = e1;
+	               else if ((e2 != other2) && (e2 != other3))
+		               e3 = e2;
+	               /* can happen with > 2 polys on an edge  but won't form a good strip so stop
+                       the strip here
+                    */
+                    else
+	               {
+                         Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+         		                           triangulate,swaps,next_id,where);
+                         return;
+	       }
+
+	       /*   See which vertex of the input edge is not in the output edge */
+	       if ((other2 != e1) && (other2 != e2))
+	       {
+		          other1 = other2;
+		          other2 = other3;
+	       }
+	       else if ((other3 != e1) && (other3 != e2))
+		          other1 = other3;
+	       else
+	       {
+                 /* Degenerate triangle just return*/
+               Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
+			RemoveList(pListHead,(PLISTINFO) temp);
+			begin = FALSE;
+               return;
+	       }
+		      
+	   }
+	   
+	   /*   There was not an input edge, we are the first triangle in a strip */
+	   else 
+	   {
+	       /*   Find the correct order to transmit the triangle, what is
+		       the output edge that we want ?
+	       */
+	       other1 = e3;
+	       e3 = e2;
+	       other2 = e1;
+	   }
+	   
+	   /*   At this point the adjacencies have been updated  and we
+		   have the next polygon id 
+	   */
+        Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
+  	   RemoveList(pListHead,(PLISTINFO) temp);
+	   begin = FALSE;
+
+	   if (Done(next_face_id,59,&next_bucket) == NULL)
+		return;
+
+        pListHead = array[next_bucket];
+	   pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+	   if ( pfNode )
+	  	pfNode->face_id = next_face_id;
+	   lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				 (int (*)(void *,void *)) (Compare)));
+	   if (lpListInfo == NULL)
+	   {
+				printf("There is an error finding the next polygon3 %d\n",next_face_id);
+				exit(0);
+	   }
+	   Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+					pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+
+	}
+}
+
+	else
+	{
+		/*      It is not a triangle, we have to triangulate it .
+			   Since it is not adjacent to anything we can triangulate it
+			   blindly
+		*/
+		if (bucket == 0)
+		{
+			/*  Check to see if there is not an input edge */
+	          Last_Edge(&other1,&other2,&other3,0);
+	          if ((other1 == 0) && (other2 ==0))
+		          Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						          output,TRUE,where);
+	          else
+		          Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
+			                         output,FALSE,where);
+
+			RemoveList(pListHead,(PLISTINFO) temp);
+			/*      We will be at the beginning of the next strip. */
+			begin = TRUE;
+		}
+
+		 /*  If we have specified PARTIAL triangulation then
+			we will go to special routines that will break the
+			polygon and update the data structure. Else everything
+			below will simply triangulate the whole polygon 
+		*/
+		else if (triangulate == PARTIAL)
+		{
+	    
+	          /*  Return the face_id of the next polygon we will be using,
+			*/
+			next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties);
+
+		
+			/* Don't do it partially, because we can go inside and get
+		        less adjacencies, for a quad we can do the whole thing.
+	          */
+	          if ((face_id == next_face_id) && (face->nPolSize == 4)  && (swaps == ON))
+	          {
+                    next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+		          if (next_face_id == -1)
+		          {
+		               /*  There is no sequential face to go to, end the strip */
+		               Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+					                 triangulate,swaps,next_id,where);
+		               return;
+		          }
+               
+                    /* Break the tie,  if there was one */
+		          if (tie != FIRST)
+			          next_face_id = Get_Next_Face(tie,face_id,triangulate);
+		          Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						              output,next_face_id,face_id,where);
+			     RemoveList(pListHead,(PLISTINFO) temp);
+	          }
+	   
+	          /*   Was not a quad but we still do not want to do it partially for
+		          now, since we want to only do one triangle at a time
+	          */
+	          else if ((face_id == next_face_id) && (swaps == ON))
+	               Inside_Polygon(face->nPolSize,face->pPolygon,strips,output,
+		                         next_face_id,face_id,next_id,pListHead,temp,where);
+
+	          else
+	          {
+					 if ((tie != FIRST) && (swaps == ON))
+						 next_face_id = Get_Next_Face(tie,face_id,triangulate);
+					 Partial_Triangulate(face->nPolSize,face->pPolygon,strips,
+						                output,next_face_id,face_id,next_id,pListHead,temp,where);
+					/*    Check the next bucket again ,maybe it changed 
+						 We calculated one less, but that might not be the case
+					*/
+               }
+
+			if (Done(next_face_id,59,&next_bucket) == NULL)
+			{
+     			/*  Check to see if there is not an input edge */
+	               Last_Edge(&other1,&other2,&other3,0);
+	               if ((other1 == 0) && (other2 ==0))
+		               Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						               output,TRUE,where);
+	               else
+		               Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
+			                              output,FALSE,where);
+                    
+                    if (Done(face_id,59,&bucket) != NULL)
+                    {
+                         pListHead = array[bucket];
+			          pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			          if ( pfNode )
+				          pfNode->face_id = face_id;
+			          lpListInfo = (P_ADJACENCIES) (SearchList(array[bucket], pfNode,
+				                  (int (*)(void *,void *)) (Compare)));
+			          RemoveList(pListHead,(PLISTINFO)lpListInfo);
+                    }
+                    begin = TRUE;
+				return;
+			}
+			
+			begin = FALSE;
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				        (int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+			{
+				printf("There is an error finding the next polygon1 %d %d\n",next_face_id,next_bucket);
+				exit(0);
+			}
+			Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+				            pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+		}
+
+          
+		else
+		{
+			/*  WHOLE triangulation */
+	          /*  It is not a triangle and has adjacencies. 
+				This means that we have to:
+				1. TriangulateEx this polygon, not blindly because
+					we have an edge that we want to come out on, that
+					is the edge that is adjacent to a polygon with the
+					least number of adjacencies. Also we must come in
+					on the last seen edge.
+				2. Update the adjacencies in the list, because we are
+					using this polygon .
+				3. Get the next polygon.
+			*/
+			/*   Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current polygon.
+			*/
+				
+               next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+               {
+                    Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+			                      triangulate,swaps,next_id,where);
+                    /*    Because maybe there was more than 2 polygons on the edge */
+                    return;
+		     }
+
+		     /*      Break the tie,  if there was one */
+			else if (tie != FIRST)
+				next_face_id = Get_Next_Face(tie,face_id,triangulate);
+				
+			Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						         output,next_face_id,face_id,where);
+			RemoveList(pListHead,(PLISTINFO) temp);
+			begin = FALSE;
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+					   (int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+		     {
+					printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
+					exit(0);
+               }
+			Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+					       pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+		}
+
+	}
+    Last_Edge(&e1,&e2,&e3,0);
+
+}       
+
+
+
+	
+
+
+
+
diff --git a/Stripe_u/outputex.h b/Stripe_u/outputex.h
new file mode 100644
index 000000000..68cff0ca2
--- /dev/null
+++ b/Stripe_u/outputex.h
@@ -0,0 +1,23 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: outputex.h
+-----------------------------------------------------------------------*/
+
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_TriEx();
+void Sgi_Test();
+void Polygon_OutputEx();
+void Extend_BackwardsEx();
+void FinishedEx();
+
+
diff --git a/Stripe_u/partial.c b/Stripe_u/partial.c
new file mode 100644
index 000000000..9afb03c19
--- /dev/null
+++ b/Stripe_u/partial.c
@@ -0,0 +1,665 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: partial.c
+     This file contains routines that are used partial triangulation of polygons
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "outputex.h"
+#include "polvertsex.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "polverts.h"
+#include "common.h"
+#include "util.h"
+
+void P_Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,FILE *fp,int reversed,int face_id,
+					  int *next_id,ListHead *pListHead, 
+					  P_ADJACENCIES temp,
+                      int where)
+{
+    int vertex4,vertex5,dummy=60;
+	
+    /*	This routine will nonblindly triangulate a quad, meaning
+		that there is a definite input and a definite output
+		edge that we must adhere to. Reversed will tell the orientation
+		of the input edge. (Reversed is -1 is we do not have an input
+		edge, in other words we are at the beginning of a strip.)
+		Out_edge* is the output edge, and in_edge* is the input edge. 
+		Index are the edges of the polygon
+		and size is the size of the polygon. Begin is whether we are
+		at the start of a new strip.
+		Note that we will not necessarily triangulate the whole quad;
+		maybe we will do half and leave the other half (a triangle)
+		for later.
+	*/
+	
+
+    /*	If we do not have an input edge, then we can make our input
+		edge whatever we like, therefore it will be easier to come
+		out on the output edge.	In this case the whole quad is done.
+	*/
+	if (reversed == -1)
+	{
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+		Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+		RemoveList(pListHead,(PLISTINFO) temp);
+		return;
+	}
+	
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off, but cannot use the whole quad?
+	*/
+
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge. Save the other half for later.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+          Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,
+				face_id,&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		/*	Put the new face in the proper bucket of adjacencies 
+			There are 2 edges that need to be checked for the triangle
+			that was just outputted. For the output edge we definitely
+			will be decreasing the adjacency, but we must check for the
+			input edge.
+		*/
+
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge1,out_edge2,vertex4);
+		return;									  
+	}
+	else if (in_edge1 == out_edge1)
+	{
+		/*	We want to output the first triangle (whose output
+			edge is not the one that we want.
+			We have to find the vertex that we need, which is
+			the other vertex which we do not have.
+		*/						
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+		Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge2,out_edge2,vertex4);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge2,out_edge1,vertex4);
+          return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge1,out_edge1,vertex4);
+		return;
+	}
+
+	/*	The final case is where we want to come out the opposite
+		edge.
+	*/
+	else
+	{
+        if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
+                    ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
+		{
+			/*	We need to know the orientation of the input
+				edge, so we know which way to put the diagonal.
+                And also the output edge, so that we triangulate
+                correctly. Does not need partial.
+             */
+			Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
+			dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+			RemoveList(pListHead,(PLISTINFO) temp);
+		}
+		else
+		{
+			/*      Input and output orientation was reversed, so diagonal will
+					be reversed from above.
+			*/
+			Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
+			dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+			RemoveList(pListHead,(PLISTINFO) temp);
+		}
+		return;
+	}
+}
+
+void P_Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1,
+						   int in_edge2,int size,
+						  int *index,FILE *output,FILE *fp,
+						  int reversed,int face_id,int *next_id,
+						  ListHead *pListHead, P_ADJACENCIES temp2,
+                          int where)
+{
+	/*	We have a polygon greater than 4 sides, which we wish
+		to partially triangulate
+	*/
+	int next_bucket,vertex4,dummy = 60;
+	int *temp;
+	P_ADJACENCIES pfNode;
+
+		
+    /*	Since we are calling this recursively, we have to check whether		
+		we are down to the case of the quad.
+	*/
+	if (size == 4)
+	{
+		P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+							index,output,fp,reversed,face_id,next_id,
+							pListHead,temp2,where);
+		return;
+	}
+	
+	/*	We do not have a specified input edge, and therefore we
+		can make it anything we like, as long as we still come out 
+		the output edge that we want.
+	*/
+	if (reversed  == -1)
+	{
+		/*	Get the vertex for the last triangle, which is
+			the one coming out the output edge, before we do
+			any deletions to the list. We will be doing this
+			bottom up.
+		*/
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(out_edge2,index,size);
+		/*	We do not have to partially triangulate, since
+			we will do the whole thing, so use the whole routine
+		*/
+		Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
+						 vertex4,size-1,index,output,fp,reversed,face_id,
+						 next_id,pListHead,temp2,where);
+		memcpy(index,temp,sizeof(int)*size);
+		/*	Lastly do the triangle that comes out the output
+			edge.
+		*/
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		/*	We were able to do the whole polygon, now we
+			can delete the whole thing from our data structure.
+		*/
+		dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+		RemoveList(pListHead,(PLISTINFO) temp2);
+		return;
+	}	  
+
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off that comes out the correct output edge, 
+		but we cannot use the whole polygon?
+	*/
+	if (in_edge2 == out_edge1) 
+	{
+		Output_TriEx(in_edge1,out_edge1,out_edge2,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge2,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+
+	/*	Next case is where it is again consecutive, but the triangle
+		formed by the consecutive edges do not come out of the
+		correct output edge. (the input edge will be reversed in
+		the next triangle)
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge1,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+        Delete_From_ListEx(in_edge1,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge2,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+
+	/*	Else the edge is not consecutive, and it is sufficiently
+		far away, for us not to make a conclusion at this time.
+		So we can take off a triangle and recursively call this
+		function.
+	*/
+	else
+	{
+          if (!reversed)
+		{
+			vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+			Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+			
+			/*	Now delete the adjacencies by one for all the faces
+				that are adjacent to the triangle that we just outputted.
+			*/
+			Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+			Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+			
+			/*	Put the new face in the proper bucket of adjacencies */
+			next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+			next_bucket = Change_FaceEx(face_id,in_edge1,vertex4,pListHead,temp2,FALSE);
+			
+			/*	Create a new edgelist without the triangle that
+				was just outputted.
+			*/
+			Delete_From_ListEx(in_edge1,index,size);
+			/*	Update the face data structure, by deleting the old
+				face and putting in the polygon minus the triangle 
+				as the new face, here we will be decrementing the size
+				by one.
+			*/
+			New_Size_Face(face_id);
+
+			/*	Save the info for the new bucket, we will need it on
+				the next pass for the variables, pListHead and temp 
+			*/
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = face_id;
+			temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				(int (*)(void *,void *)) (Compare)));
+			if (temp2 == NULL)
+			{
+				printf("There is an error finding the next polygon10\n",next_bucket,face_id);
+				exit(0);
+			}
+
+			P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+						 vertex4,size-1,index,output,fp,!reversed,
+						 face_id,next_id,pListHead,temp2,where);
+		}
+		else
+		{
+			vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+			Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+
+			/*	Now delete the adjacencies by one for all the faces
+				that are adjacent to the triangle that we just outputted.
+			*/
+			Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+			Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+			
+			/*	Put the new face in the proper bucket of adjacencies */
+			next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+			next_bucket = Change_FaceEx(face_id,in_edge2,vertex4,pListHead,temp2,FALSE);
+			
+			/*	Create a new edgelist without the triangle that
+				was just outputted.
+			*/
+			Delete_From_ListEx(in_edge2,index,size);
+			
+			/*	Update the face data structure, by deleting the old
+				face and putting in the polygon minus the triangle 
+				as the new face, here we will be decrementing the size
+				by one.
+			*/
+			New_Size_Face(face_id);
+			
+			/*	Save the info for the new bucket, we will need it on
+				the next pass for the variables, pListHead and temp 
+			*/
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = face_id;
+			temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				(int (*)(void *,void *)) (Compare)));
+			if (temp2 == NULL)
+			{
+				printf("There is an error finding the next polygon11 %d %d\n",face_id,next_bucket);
+				exit(0);
+			}
+
+			P_Triangulate_Polygon(out_edge1,out_edge2,vertex4,
+						       in_edge1,size-1,index,output,fp,!reversed,
+						       face_id,next_id,pListHead,temp2,where);
+		}
+		return;
+	}
+}
+
+void P_Triangulate(int out_edge1,int out_edge2,int in_edge1,
+				 int in_edge2,int size,int *index,
+				 FILE *fp,FILE *output,int reversed,int face_id,
+				 int *next_id,ListHead *pListHead, 
+				 P_ADJACENCIES temp,int where)
+{
+		
+	if (size == 4)
+		P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			              index,fp,output,reversed,face_id,next_id,pListHead, temp,where);
+	else
+		P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			                 index,fp,output,reversed,face_id,next_id,pListHead,temp,where);
+}
+
+ void Partial_Triangulate(int size,int *index, FILE *fp,
+						 FILE *output,int next_face_id,int face_id,
+						 int *next_id,ListHead *pListHead,
+						 P_ADJACENCIES temp, int where)
+{
+	int id1,id2,id3;
+	int nedge1,nedge2;
+	int reversed;
+
+	/*	We have a polygon that has to be triangulated and we cannot
+		do it blindly, ie we will try to come out on the edge that
+		has the least number of adjacencies, But also we do not
+		want to triangulate the whole polygon now, so that means 
+		we will output the least number of triangles that we can
+		and then update the data structures, with the polygon
+		that is left after we are done.
+	*/
+	Last_Edge(&id1,&id2,&id3,0);
+	
+	/*	Find the edge that is adjacent to the new face ,
+		also return whether the orientation is reversed in the
+		face of the input edge, which is id2 and id3.
+	*/
+	reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+	
+	/*   Input edge and output edge can be the same if there are more than
+          one polygon on an edge 
+     */
+     if ( ((nedge1 == id2) && (nedge2 == id3)) ||
+          ((nedge1 == id3) && (nedge2 == id2)) )
+          /*   Set output edge arbitrarily but when come out of here the
+               next face will be on the old output edge (identical one)
+          */
+          nedge2 = Return_Other(index,id2,id3);
+
+          /*	Do the triangulation */	
+	P_Triangulate(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
+		         face_id,next_id,pListHead,temp,where);
+}
+
+ void Input_Edge(int face_id, int *index, int size, int in_edge1, int in_edge2, 
+                FILE *fp, FILE *output,ListHead *pListHead, P_ADJACENCIES temp2,
+                int where)
+ {
+     /* The polygon had an input edge, specified by input1 and input2 */
+    
+     int output1,next_bucket;
+     int vertex4, vertex5,dummy=60;
+
+     output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2);
+	vertex5 = AdjacentEx(in_edge2,in_edge1,index,size); 
+     vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+
+     if (vertex4 == output1)
+     {
+		Output_TriEx(in_edge2,in_edge1,output1,output,-1,-1,where);
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(in_edge2,output1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,in_edge2,output1,pListHead,temp2,FALSE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge2,index,size);
+
+    }	
+    else if (vertex5 == output1)
+    {
+          Output_TriEx(in_edge1,in_edge2,vertex5,output,-1,-1,where);
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,in_edge1,vertex5,pListHead,temp2,FALSE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge1,index,size);
+    }
+		
+    /*	Update the face data structure, by deleting the old
+		face and putting in the polygon minus the triangle 
+		as the new face, here we will be decrementing the size
+		by one.
+    */
+    New_Size_Face(face_id);
+    return;
+ }
+ 
+ void Inside_Polygon(int size,int *index,FILE *fp,FILE *output,
+                   int next_face_id,int face_id,int *next_id,
+                   ListHead *pListHead,P_ADJACENCIES temp, int where)
+ {
+     /* We know that we have a polygon that is greater than 4 sides, and
+        that it is better for us to go inside the polygon for the next
+        one, since inside will have less adjacencies than going outside.
+        So, we are not doing partial for a part of the polygon.
+      */
+    int id1,id2,id3;
+    int new1,new2;
+
+    Last_Edge(&id1,&id2,&id3,0);
+
+    /*  See if the input edge existed in the polygon, that will help us */
+	if (Exist(face_id,id2,id3))
+        Input_Edge(face_id,index,size,id2,id3,output,fp,pListHead,temp,where);
+    else
+    {
+        /*  Make one of the input edges 
+            We will choose it by trying to get an edge that has something
+            in common with the last triangle, or by getting the edge that
+            is adjacent to the least number of thigs, with preference given
+            to the first option
+        */
+               
+        Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id);
+        Input_Edge(face_id,index,size,new1,new2,output,fp,pListHead,temp,where);
+    }
+ }
+
+
diff --git a/Stripe_u/partial.h b/Stripe_u/partial.h
new file mode 100644
index 000000000..c9a9439c8
--- /dev/null
+++ b/Stripe_u/partial.h
@@ -0,0 +1,15 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: partial.h
+-----------------------------------------------------------------------*/
+
+void Partial_Triangulate();
+void Inside_Polygon();
+
diff --git a/Stripe_u/polverts.h b/Stripe_u/polverts.h
new file mode 100644
index 000000000..79ece86db
--- /dev/null
+++ b/Stripe_u/polverts.h
@@ -0,0 +1,87 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: polverts.h
+-----------------------------------------------------------------------*/
+
+#include "queue.h"
+#include <malloc.h>
+
+
+/*      external functions */
+void Find_Adjacencies();
+void Test_Adj_Struct();
+void Test_SGI_Struct();
+void Write_Edges();
+void Build_SGI_Table();
+void Save_Walks();
+void Find_Bands();
+void Save_Rest();
+void Assign_Walk();
+void Save_Walks();
+	
+typedef struct adjacencies
+{
+	Node ListNode;
+	int face_id;
+} ADJACENCIES,*P_ADJACENCIES;
+
+typedef struct FVerts
+{
+	Node ListNode;
+	int *pPolygon;
+	int nPolSize;
+	int nId;
+} F_VERTS, *PF_VERTS;
+
+/*Every time we need to use this, cast it ( ListInfo*)*/
+
+typedef struct FEdges
+{
+	Node ListNode;
+	int edge[3];
+}F_EDGES,*PF_EDGES;
+
+typedef struct FFaces
+{
+	Node ListNode;
+	int *pPolygon;
+	int *pNorms;
+    int     seen;
+    int seen2;
+    int seen3;
+	int nPolSize;
+	F_EDGES **VertandId;
+	int *marked;
+		int *walked;
+} F_FACES,*PF_FACES;
+	
+
+typedef struct Strips
+{
+	Node ListNode;
+	int face_id;
+} Strips,*P_STRIPS;
+
+
+     struct vert_added
+     {
+          int num;
+          int *normal;
+     };
+
+
+/*      Globals */
+ListHead **PolVerts;
+ListHead **PolFaces;
+ListHead **PolEdges;
+ListHead *array[60];
+int     id_array[60];
+ListHead *strips[1];
+ListHead *all_strips[100000]; /*  Assume max 100000 strips */
diff --git a/Stripe_u/polvertsex.h b/Stripe_u/polvertsex.h
new file mode 100644
index 000000000..8e05a7dd3
--- /dev/null
+++ b/Stripe_u/polvertsex.h
@@ -0,0 +1,34 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: polvertsex.h
+-----------------------------------------------------------------------*/
+
+#include "queue.h"
+#include <malloc.h>
+
+
+/*      external functions */
+void Start_Vert_Struct();
+void Start_Face_StructEx();
+void Start_Edge_StructEx();
+void AddNewNode();
+void AddNewFaceEx();      
+void Find_AdjacenciesEx();
+void Test_Adj_Struct();
+void Test_SGI_Struct();
+void Write_Edges();
+void End_Verts_Struct();
+void End_Face_StructEx();
+void End_Edge_StructEx();
+void Build_SGI_TableEx();
+void Add_AdjEdgeEx();
+
+
+
diff --git a/Stripe_u/queue.c b/Stripe_u/queue.c
new file mode 100644
index 000000000..29d5e9de0
--- /dev/null
+++ b/Stripe_u/queue.c
@@ -0,0 +1,226 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: queue.c
+     This file contains the routines used in the data structures lists, which
+     are queues.
+*/
+/*---------------------------------------------------------------------*/
+
+ #include "queue.h"
+ 
+
+
+/*----------------------------------------------------------------------------
+ * InitList:
+ */
+BOOL  InitList  (PLISTHEAD LHead)
+ 
+{
+     if (LHead == NULL) return(FALSE);
+
+     LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL;
+     LHead->NumList = 0;
+     return(TRUE);
+}
+
+/*----------------------------------------------------------------------------
+ * AddHead:
+ */
+BOOL  AddHead(PLISTHEAD LHead, PLISTINFO LInfo)
+{
+     if (LHead == NULL || LInfo == NULL)
+          return(FALSE);
+     if (EMPTYLIST(LHead))
+          LHead->LHeaders[LISTTAIL] = LInfo;
+     else LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void  *) LInfo;
+
+     LInfo->ListNode.Next = (void  *) LHead->LHeaders[LISTHEAD];
+     LHead->LHeaders[LISTHEAD] = LInfo;
+     LInfo->ListNode.Previous = NULL;
+     LHead->NumList++;
+     return(TRUE);
+}
+
+/*----------------------------------------------------------------------------
+ * AddTail
+ */
+BOOL  AddTail(PLISTHEAD LHead, PLISTINFO LInfo)
+{
+     if (LHead == NULL || LInfo == NULL)
+          return(FALSE);
+     if (EMPTYLIST(LHead))
+          LHead->LHeaders[LISTHEAD] = LInfo;
+     else LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo;
+
+     LInfo->ListNode.Previous = (void  *) LHead->LHeaders[LISTTAIL];
+     LHead->LHeaders[LISTTAIL] = LInfo;
+     LInfo->ListNode.Next = NULL;
+     LHead->NumList++;
+     return(TRUE);
+}
+
+
+BOOL  InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo )
+{
+PLISTINFO LAddNode;
+
+     if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) ) 
+          return( FALSE );
+
+     if ( nPos == 0 )
+          AddHead( LHead, LInfo );
+     else if ( nPos == NumOnList( LHead ) ) 
+          AddTail( LHead, LInfo );
+     else
+     {
+          if ( (LAddNode = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL )
+               return( FALSE );
+          
+          ((PLISTINFO)LAddNode->ListNode.Next)->ListNode.Previous = LInfo;
+          LInfo->ListNode.Next      = LAddNode->ListNode.Next;
+          LInfo->ListNode.Previous  = LAddNode;
+          LAddNode->ListNode.Next   = LInfo;
+          
+          LHead->NumList++;
+     }
+
+     return( TRUE );
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+ *  RemHead:
+ */
+PLISTINFO  RemHead(PLISTHEAD LHead)
+{
+     PLISTINFO t, t1;
+
+     if ( LHead == NULL || EMPTYLIST(LHead) )
+          return(NULL);
+
+     t = LHead->LHeaders[LISTHEAD];
+     LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next;
+
+     if (LHead->LHeaders[LISTHEAD] != NULL)
+     {
+          t1 = (PLISTINFO) t->ListNode.Next;
+          t1->ListNode.Previous = NULL;
+     }
+     else
+          LHead->LHeaders[LISTTAIL] = NULL;
+
+     LHead->NumList--;
+
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ *  RemTail:
+ */
+PLISTINFO  RemTail(PLISTHEAD   LHead)
+{
+     PLISTINFO   t, t1;
+
+     if ( LHead == NULL || EMPTYLIST(LHead) )
+          return(NULL);
+
+     t = LHead->LHeaders[LISTTAIL];
+     LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous;
+     if (LHead->LHeaders[LISTTAIL] != NULL)
+     {
+          t1 = (PLISTINFO) t->ListNode.Previous;
+          t1->ListNode.Next = NULL;
+     }
+     else
+          LHead->LHeaders[LISTHEAD] = NULL;
+
+     LHead->NumList--;
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ * PeekList:
+ */
+PLISTINFO  PeekList(PLISTHEAD LHead, int wch, int index )
+{
+     PLISTINFO  t;
+
+     if (LHead == NULL)
+          return(NULL);
+     if ( (t = LHead->LHeaders[wch]) == NULL )
+          return(NULL);
+
+     for (; t != NULL && index > 0; index-- )
+          t = (wch == LISTHEAD)  ? (PLISTINFO) t->ListNode.Next  :
+                                   (PLISTINFO) t->ListNode.Previous;
+     return(t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * RemoveList:
+ */
+PLISTINFO   RemoveList( PLISTHEAD LHead, PLISTINFO LInfo )
+{
+     PLISTINFO     t, t1;
+
+     t = LInfo;
+     if (LHead == NULL)
+          return(NULL);
+     if (LHead->LHeaders[LISTHEAD] == t)
+          t = (PLISTINFO) RemHead(LHead);
+     else if (LHead->LHeaders[LISTTAIL] == t)
+          t = (PLISTINFO) RemTail(LHead);
+     else
+     {
+          t1                    = (PLISTINFO) t->ListNode.Previous;
+          t1->ListNode.Next     = t->ListNode.Next;
+          t1                    = (PLISTINFO) t->ListNode.Next;
+          t1->ListNode.Previous = t->ListNode.Previous;
+          LHead->NumList--;
+     }
+
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ * SearchList:
+ *       Try to find a specific node in the queue whose key matches with
+ *  searching key. Return the pointer to that node if found, return NULL
+ *  otherwise
+ *
+ *  Input:
+ *    lpHashTbl       => a far pointer to the hash table
+ *    lpKey           => a far poniter to searching key
+ *    CompareCallBack => comparision function
+ *
+ *  Output: a far pointer to the node to be found
+ *
+ */
+PLISTINFO  SearchList(
+                        PLISTHEAD lpListHead,
+                        PVOID lpSKey,
+                        int (* CompareCallBack) ( PVOID, PVOID ) )
+{
+PLISTINFO lpListInfo;
+
+     lpListInfo = PeekList( lpListHead, LISTHEAD, 0);
+     while ( lpListInfo != NULL )
+     {
+          if ( CompareCallBack( lpListInfo, lpSKey ) )
+               break;
+          lpListInfo = GetNextNode( lpListInfo );
+     }
+
+     return( lpListInfo );
+}
+ 
diff --git a/Stripe_u/queue.h b/Stripe_u/queue.h
new file mode 100644
index 000000000..0bf926e0f
--- /dev/null
+++ b/Stripe_u/queue.h
@@ -0,0 +1,283 @@
+
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:queue.h
+-----------------------------------------------------------------------*/
+
+#ifndef QUEUE_INCLUDED
+#define QUEUE_INCLUDED
+
+/*        %%s  Node      */
+/*****************************************************************
+     This structure is used to store the List linkage information of a
+ListInfo structure.  It contains all the necessary information for the
+List functions to function properly.  This structure must be the first
+one defined in any block of memory to be linked with the List functions.
+for an example of the used of The Node structure look in the files
+ipd2dms.c and ipd2man.h
+******************************************************************/
+#include <stdio.h>
+#define FALSE 0
+#define TRUE  1
+typedef struct
+{
+     void  *Next;
+     void  *Previous;
+}
+     Node, * PNODE;
+
+/*****************************************************************
+     Next     :  is a pointer to the next structure in this List.
+     Previous :  is a pointer to the previous structure in this List.
+     priority :  this is the priority of this structure in the List.  The
+                 highest priority is 0.  This field is only used by the
+                 functions EnQue and DeQue.
+******************************************************************/
+/*        %%e       */
+
+
+/*        %%s  ListInfo      */
+
+/*****************************************************************
+      This is the general means of linking application defined information into
+Lists and queues.  All structures must begin with the Node Structure.  All
+other data in the structure is user definable.
+******************************************************************/
+
+typedef struct List
+{
+     Node     ListNode;       /*  link to the next Listinfo Structure  */
+     /*  user definable data  */
+}    ListInfo, *PLISTINFO;
+
+/*****************************************************************
+     ListNode  :  this is the required node structure for the List
+                  mainpulation functions.  This must be the first
+                  element of a user definable structure.
+
+     In order for an application to use the List routines, it must define
+a structure with all the needed information.  The first element in the
+user definable structure must be a Node structure.  The Node structure
+contains all the necessary information for the List routines to do their
+magic.  For an example of a user defined List structure see the file
+ipd2i.h.  The User definable structure can be passed to any List function
+that excepts a pointer to a ListInfo structure.
+
+example:
+
+typedef  mstruct
+{
+     Node   ListNode;
+     int    a,b,c,d,e,f,g;
+}
+     mystruct;
+
+     the user definable portion of the above structure is represented by
+the integers a,b,c,d,e,f,g.  When passing this structure to a List
+function a cast of (ListInfo *) must be made to satisify the "C" complier.
+******************************************************************/
+/*        %%e       */
+
+
+/*        %%s ListHead        */
+/*****************************************************************
+     ListHead is used as a header to a List.  LHeaders[0] points to the
+head of the List.  LHeaders[1] points the tail of the list.  When
+accessing these variables use the defines  LISTHEAD, LISTTAIL.
+******************************************************************/
+
+typedef struct LHead
+{
+     PLISTINFO  LHeaders[2];
+     int         NumList;
+}
+ListHead, *PLISTHEAD;
+
+/*****************************************************************
+     LHeaders   :  this is an array of two pointers to ListInfo structures.
+                   This information is used to point to the head and tail of
+                   a list.
+     NumList    :  this integer hold the number of structures linked into this
+                   list.
+
+ListHead #define:
+
+     LISTHEAD  :  when Peeking down a list this specifies you should
+                  start at the Head of the list and search downward.
+
+     LISTTAIL  :  when Peeking down a list this specifies you should
+                  start at the tail of the list and search foward.
+ ******************************************************************/
+
+#define  LISTHEAD  0
+
+#define  LISTTAIL  1
+/*        %%e       */ 
+
+typedef int BOOL;
+typedef void * PVOID;
+
+#define PEEKFROMHEAD( lh, ind )     ( PeekList( (lh), LISTHEAD, (ind) ) )
+#define PEEKFROMTAIL( lh, ind )     ( PeekList( (lh), LISTTAIL, (ind) ) )
+#define EMPTYLIST( lh )             ( ( (lh)->LHeaders[LISTHEAD] == NULL ) )
+
+/*   General utility routines   */
+/*        %%s QueRoutines          */
+BOOL    InitList      ( PLISTHEAD );
+
+/*****************************************************************
+     InitList :  Initialize a new list structure for use with the List
+                 routines
+
+     INPUTS   :  LHead : a pointer to a ListHead structure.
+     OUTPUT   :  a boolean value TRUE if no errors occured FALSE
+                 otherwise
+******************************************************************/
+
+
+PLISTINFO  PeekList      ( PLISTHEAD, int, int   );
+
+/*****************************************************************
+     PeekList :  This funciton peeks down a list for the N'th element
+                 from the HEAD or TAIL of the list
+
+     INPUTS   :  LHead    :  a pointer to a List head structure.
+                 from     :  can either search from the HEAD or TAIL
+                             of the list
+                 where    :  how many nodes from the begining should the
+                             List routines look.
+     OUTPUT   :  a pointer to a ListInfo structure identified by
+                 from/where or NULL if an error occurred.
+******************************************************************/
+
+
+PLISTINFO   RemoveList( PLISTHEAD LHead, PLISTINFO LInfo );
+
+
+/*****************************************************************
+     RemoveList: Remove a ListInfo structure from a List.
+
+     INPUTS    : LHead  :  a pointer to a ListHead structure.
+                 LInfo  :  a pointer to the ListInfo structure to remove
+                           from the list.
+     OUTPUT    : a pointer to the ListInfo structure that was removed or
+                 NULL if an error occurred.
+******************************************************************/
+
+BOOL  InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo );
+
+/*****************************************************************
+     InsertNode: add a node to a list after a given node
+     
+     INPUTS    : LHead : a pointer to a ListHead structure.
+                 nPos  : the position to insert the node into
+                 LInfo : a pointer to the new node to add to the list.
+     OUTPUT: a boolean value TRUE if all goes well false otherwise
+*****************************************************************/
+
+BOOL   AddHead       ( PLISTHEAD, PLISTINFO );
+
+/*****************************************************************
+     AddHead   : add a ListInfo structure to the HEAD of a list.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the list
+                          to add to.
+                 LInfo  : a pointer to the ListInfo structure to add to
+                          the list.
+     OUTPUT    : A boolean value TRUE if no errors occurred FALSE
+                 otherwise.
+******************************************************************/
+
+
+BOOL     AddTail       ( PLISTHEAD, PLISTINFO );
+
+/*****************************************************************
+     AddTail   : Add a ListInfo structure to the TAIL of a list.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to add to.
+                 LInfo  : a pointer to the ListInfo structure to add to
+                          the List.
+     OUTPUT    : a boolean value TRUE if no errors occurred FALSE
+                 otherwise.
+******************************************************************/
+
+
+PLISTINFO  RemTail       ( PLISTHEAD );
+
+/*****************************************************************
+     RemTail   : Remove a ListInfo structure from the TAIL of a List.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to remove from.
+     OUTPUT    : a pointer to the ListInfo structure that was removed
+                 or NULL if an error occurred.
+******************************************************************/
+
+
+PLISTINFO  RemHead       ( PLISTHEAD );
+
+/*****************************************************************
+     RemHead   : Remove a ListInfo structure from the Head of a List.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to remove from.
+     OUTPUT    : a pointer to the ListInfo structure that was removed or
+                 NULL if an error occurred.
+******************************************************************/
+
+PLISTINFO  SearchList(
+                        PLISTHEAD lpListHead,
+                        PVOID lpSKey,
+                        int ( * CompareCallBack) ( PVOID, PVOID ) );
+
+/*****************************************************************
+  SearchList:
+        Try to find a specific node in the queue whose key matches with
+   searching key. Return the pointer to that node if found, return NULL
+   otherwise
+
+   Input:
+     lpHashTbl       => a far pointer to the hash table
+     lpKey           => a far poniter to searching key
+     CompareCallBack => comparision function
+
+   Output: a far pointer to the node to be found
+
+ ******************************************************************/
+
+#define           NumOnList(lh) ( ((lh)->NumList)        )
+
+/*****************************************************************
+     NumOnList: Returns the number of Nodes linked to a ListHead
+                structure.  This number is maintained by the List
+                routines.
+******************************************************************/
+
+#define           GetNextNode(pli) ( ((pli)->ListNode.Next) )
+
+/********************************************************
+     GetNextNode: This macro returns the Next Structure in this list.
+                  This macro will return NULL if no more structures are
+                  in the List.
+*********************************************************/
+
+#define           GetPrevNode(pli) ( ((pli)->ListNode.Previous) )
+
+/********************************************************
+     GetPrevNode: This macro returns the Previous Structure in this list.
+                  This macro will reutrn NULL if no more structures are
+                  in the List.
+********************************************************/
+/*        %%e       */
+
+#endif
+
+
diff --git a/Stripe_u/sgi_triang.c b/Stripe_u/sgi_triang.c
new file mode 100644
index 000000000..40dff70f6
--- /dev/null
+++ b/Stripe_u/sgi_triang.c
@@ -0,0 +1,631 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sgi_triang.c
+     File contains the routines that do the whole triangulation
+     of polygons.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "output.h"
+#include "polverts.h"
+#include "sturcts.h"
+#include "common.h"
+#include "util.h"
+#include "init.h"
+
+int Adjacent(int id2,int id1, int *list, int size)
+{
+	/*	Return the vertex that is adjacent to id1,
+		but is not id2, in the list of integers.
+	*/
+
+	register int x=0;
+	
+	while (x < size)
+	{
+		if (*(list+x) == id1)
+		{
+			if ((x != (size -1)) && (x != 0))
+			{
+				if ( *(list+x+1) != id2)
+					return *(list+x+1);
+				else
+					return *(list+x-1);
+			}
+			else if (x == (size -1))
+			{
+				if (*(list) != id2)
+					return *(list);
+				else
+					return *(list+x-1);
+			}
+			else
+			{
+				if (*(list+size-1) != id2)
+					return *(list+size-1);
+				else
+					return *(list+x+1);
+			}
+		}
+		x++;
+	}
+	/*   if there are degeneracies */
+     return id1;
+}
+
+
+void Rearrange_Index(int *index, int size)
+{
+	/*	If we are in the middle of a strip we must find the
+		edge to start on, which is the last edge that we had
+		transmitted.
+	*/
+	int x,f,y,e1,e2,e3;
+ 	register int increment = 1;
+     int *temp;
+
+	/*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+	for (y = 0; y < size; y++)
+	{
+		if (*(index+y) == e2)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e3))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e3))
+				break;
+               else if ((y != 0) && (*(index+y-1) == e3))
+               {
+                    increment = -1;
+                    break;
+               }
+               else if ((y==0) && (*(index+size-1) == e3))
+               {
+                    increment = -1;
+                    break;
+               }
+		}
+		if (*(index+y) == e3)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e2))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e2))
+				break;
+            else if ((y != 0) && (*(index+y-1) == e2))
+            {
+                increment = -1;
+                break;
+            }
+            else if ((y==0) && (*(index+size-1) == e2))
+            {
+                increment = -1;
+                break;
+            }
+		}
+		/*	Edge is not here, we are at the beginning */
+		if ((y == (size-1)) && (increment != -1))
+			return;
+	}
+	
+	/*	Now put the list into a new list, starting with the
+		input edge. Increment tells us whether we have to go 
+		forward or backward.
+	*/
+	/*	Was in good position already */
+	if ((y == 0) && (increment == 1)) 
+		return;
+	
+     temp = (int *) malloc(sizeof(int) * size);
+     memcpy(temp,index,sizeof(int)*size);
+
+	if (increment == 1)
+	{
+		x=0;
+		for (f = y ; f< size; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = 0; f < y ; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+	else
+	{
+		x=0;
+		for (f = y ; f >= 0; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = (size - 1); f > y ; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+}
+
+void Delete_From_List(int id,int *list, int *size)
+{
+	/*	Delete the occurence of id in the list.
+		(list has size size)
+	*/
+
+	int *temp;
+	register int x,y=0;
+
+	temp = (int *) malloc(sizeof(int) * (*size));
+	for (x=0; x<(*size); x++)
+	{
+		if (*(list+x) != id)
+		{
+			*(temp+y) = *(list+x);
+			y++;
+		}
+	}
+	*(temp+y) = -1;
+     *size = *size - (*size - y - 1);
+	memcpy(list,temp,sizeof(int)*(*size));
+}
+
+
+void Build_SGI_Table(int num_verts,int num_faces)
+{
+	/*      Build a table that has the polygons sorted by the
+	        number of adjacent polygons.
+	*/
+	int x,y,size,tally=0;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	/* For each face....*/
+	for (x=0;x < num_faces;x++)
+	{
+		pListHead = PolFaces[x];
+		temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+		/*   Check each edge of the face and tally the number of adjacent
+			polygons to this face. 
+		*/                      
+		if ( temp != NULL )
+		{
+			/*      Size of the polygon */
+			size = temp->nPolSize;
+			if (size != 1)
+               {
+                    for (y = 0; y< size; y++)
+			     {
+				     if (y != (size-1))
+					     tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1));
+				     else
+					     tally += Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)));
+                    }
+			
+			     /*   Tally is the number of polygons that is adjacent to
+				     the current polygon. 
+			     */
+			     /*      Now put the face in the proper bucket depending on tally. */
+			     Add_Sgi_Adj(tally,x);
+			     temp = NULL;
+			     tally=0;
+               }
+		}
+	}
+}
+
+
+void Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,int reversed,int face_id,
+                      int where,int color1,int color2,int color3)
+{
+	int vertex4,vertex5;
+	
+	/*	This routine will nonblindly triangulate a quad, meaning
+		that there is a definite input and a definite output
+		edge that we must adhere to. Reversed will tell the orientation
+		of the input edge. (Reversed is -1 is we do not have an input
+		edge, in other words we are at the beginning of a strip.)
+		Out_edge* is the output edge, and in_edge* is the input edge. 
+		Index are the edges of the polygon
+		and size is the size of the polygon. Begin is whether we are
+		at the start of a new strip.
+	*/
+	
+	/*	If we do not have an input edge, then we can make our input
+		edge whatever we like, therefore it will be easier to come
+		out on the output edge.
+	*/
+	if (reversed == -1)
+	{
+		vertex4 = Adjacent(out_edge1,out_edge2,index,size);
+		vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+		Output_Tri(vertex5,vertex4,out_edge1,output,color1,color2,color3,where);
+		Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where);
+		return;
+	}
+	
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off, but cannot use the whole quad?
+	*/
+
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge last. First output the triangle that comes out
+			the wrong edge.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+          Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+          Output_Tri(vertex4,in_edge2,out_edge2,output,color1,color2,color3,where);
+		return;
+	}
+	/*	The next case is where it is impossible to come out the
+		edge that we want. So we will have to start a new strip to
+		come out on that edge. We will output the one triangle
+		that we can, and then start the new strip with the triangle
+		that comes out on the edge that we want to come out on.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	We want to output the first triangle (whose output
+			edge is not the one that we want.
+			We have to find the vertex that we need, which is
+			the other vertex which we do not have.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
+		Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+		Output_Tri(vertex4,in_edge1,out_edge2,output,color1,color2,color3,where);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+		Output_Tri(vertex4,in_edge1,out_edge1,output,color1,color2,color3,where);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+		Output_Tri(vertex4,in_edge2,out_edge1,output,color1,color2,color3,where);
+		return;
+	}
+
+	/*	The final case is where we want to come out the opposite
+		edge.
+	*/
+	else
+	{
+            if( ((!reversed) && (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) ||
+                    ((reversed) && (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size)))))
+			{
+			/*	We need to know the orientation of the input
+				edge, so we know which way to put the diagonal.
+                And also the output edge, so that we triangulate
+                correctly.
+             */
+			Output_Tri(in_edge1,in_edge2,out_edge2,output,color1,color2,color3,where);
+			Output_Tri(in_edge2,out_edge2,out_edge1,output,color1,color2,color3,where);
+		}
+		else
+		{
+			/*      Input and output orientation was reversed, so diagonal will
+					be reversed from above.
+			*/
+			Output_Tri(in_edge1,in_edge2,out_edge1,output,color1,color2,color3,where);
+			Output_Tri(in_edge2,out_edge1,out_edge2,output,color1,color2,color3,where);
+		}
+		return;
+	}
+}
+
+void Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1,
+						 int in_edge2,int size,int *index,
+						 FILE *output,int reversed,int face_id,
+                         int where,int color1,int color2,int color3)
+{
+	/*	We have a polygon that we need to nonblindly triangulate.
+		We will recursively try to triangulate it, until we are left
+		with a polygon of size 4, which can use the quad routine
+		from above. We will be taking off a triangle at a time
+		and outputting it. We will have 3 cases similar to the
+		cases for the quad above. The inputs to this routine
+		are the same as for the quad routine.
+	*/
+
+	int vertex4;
+	int *temp;
+
+		
+	/*	Since we are calling this recursively, we have to check whether
+		we are down to the case of the quad.
+	*/
+	
+    if (size == 4)
+	{
+		Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+							index,output,reversed,face_id,where,color1,color2,color3);
+		return;
+	}
+
+    
+	
+	/*	We do not have a specified input edge, and therefore we
+		can make it anything we like, as long as we still come out 
+		the output edge that we want.
+	*/
+	if (reversed  == -1)
+	{
+		/*	Get the vertex for the last triangle, which is
+			the one coming out the output edge, before we do
+			any deletions to the list. We will be doing this
+			bottom up.
+		*/
+		vertex4 = Adjacent(out_edge1,out_edge2,index,size);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(out_edge2,index,&size);
+		Triangulate_Polygon(out_edge1,vertex4,in_edge2,
+						 vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		/*	Lastly do the triangle that comes out the output
+			edge.
+		*/
+		Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where,where);
+		return;
+	}
+
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off that comes out the correct output edge, 
+		but we cannot use the whole polygon?
+	*/
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge last. First recursively do the rest of the
+			polygon.
+		*/
+		/*	Do the rest of the polygon without the triangle. 
+			We will be doing a fan triangulation.
+		*/
+		/*	Get the vertex adjacent to in_edge1, but is not
+			in_edge2.
+		*/
+		vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+          Delete_From_List(in_edge1,index,&size);
+		Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+						vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Next case is where it is again consecutive, but the triangle
+		formed by the consecutive edges do not come out of the
+		correct output edge. For this case, we can not do much to
+		keep it sequential. Try and do the fan.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = Adjacent(in_edge1,in_edge2,index,size);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where,where);
+		/*	Since that triangle goes out of the polygon (the
+			output edge of it), we can make our new input edge
+			anything we like, so we will try to make it good for
+			the strip. (This will be like starting a new strip,
+			all so that we can go out the correct output edge.)
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(in_edge2,index,&size);
+		Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
+						vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = Adjacent(in_edge1,in_edge2,index,size);
+		Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(in_edge2,index,&size);
+          Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
+						vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(in_edge1,index,&size);
+          Triangulate_Polygon(out_edge1,out_edge2,vertex4,
+						in_edge2,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Else the edge is not consecutive, and it is sufficiently
+		far away, for us not to make a conclusion at this time.
+		So we can take off a triangle and recursively call this
+		function.
+	*/
+	else
+	{
+			vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+			Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where,where);
+			temp = (int *) malloc(sizeof(int) * size);
+			memcpy(temp,index,sizeof(int)*size);
+			Delete_From_List(in_edge1,index,&size);
+               Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+						     vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
+			memcpy(index,temp,sizeof(int)*size);
+		     return;
+	}
+}
+
+void Triangulate(int out_edge1,int out_edge2,int in_edge1,
+				 int in_edge2,int size,int *index,
+				 FILE *output,int reversed,int face_id, int where,
+                     int color1, int color2,int color3)
+{
+	/*	We have the info we need to triangulate a polygon */
+
+	if (size == 4)
+		Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			            index,output,reversed,face_id,where,color1,color2,color3);
+	else
+		Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			               index,output,reversed,face_id,where,color1,color2,color3);
+}
+
+void Non_Blind_Triangulate(int size,int *index,
+					  FILE *output,int next_face_id,int face_id,int where,
+                           int color1,int color2,int color3)
+{
+	int id1,id2,id3;
+	int nedge1,nedge2;
+	int reversed;
+	/*	We have a polygon that has to be triangulated and we cannot
+		do it blindly, ie we will try to come out on the edge that
+		has the least number of adjacencies
+	*/
+
+	Last_Edge(&id1,&id2,&id3,0);
+	/*	Find the edge that is adjacent to the new face ,
+		also return whether the orientation is reversed in the
+		face of the input edge, which is id2 and id3.
+	*/
+	if (next_face_id == -1)
+     {
+        printf("The face is -1 and the size is %d\n",size);
+        exit(0);
+     }
+    
+     reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+	/*	Do the triangulation */
+	
+	/*	If reversed is -1, the input edge is not in the polygon, therefore we can have the
+		input edge to be anything we like, since we are at the beginning
+		of a strip
+	*/
+	Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed,
+		       face_id, where,color1,color2,color3);
+}
+
+
+
+void Blind_Triangulate(int size, int *index, FILE *output,
+				   BOOL begin, int where ,int color1,int color2,
+                       int color3)
+{
+	/*	save sides in temp array, we need it so we know
+		about swaps.
+	*/
+	int mode, decreasing,increasing,e1,e2,e3;
+	int x = 0;
+	BOOL flag = FALSE;
+
+	/*	Rearrange the index list so that the input edge is first
+	*/
+	if (!begin)
+		Rearrange_Index(index,size);
+	
+	/*	We are given a polygon of more than 3 sides
+		and want to triangulate it. We will output the
+		triangles to the output file.
+	*/
+	
+    /*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+     if (( (!begin) && (*(index) == e2) ) || (begin))
+     {
+	    Output_Tri(*(index+0),*(index+1),*(index+size-1),output,color1,color2,color3,where,where);
+        /*	If we have a quad, (chances are yes), then we know that
+	   	     we can just add one diagonal and be done. (divide the
+		     quad into 2 triangles.
+        */
+        if (size == 4)
+        {
+		    Output_Tri(*(index+1),*(index+size-1),*(index+2),output,color1,color2,color3,where,where);
+              return;
+        }
+        increasing = 1;
+        mode = 1;
+
+    }
+    else if (!begin)
+    {
+        Output_Tri(*(index+1),*(index+0),*(index+size-1),output,color1,color2,color3,where,where);
+        if (size == 4)
+        {
+            Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where,where);
+            return;
+        }
+        Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where,where);
+        increasing = 2;
+        mode = 0;
+    }
+    if (size != 4)
+    {
+		/*	We do not have a quad, we have something bigger. */
+		decreasing = size - 1;		
+		do
+		{
+			/*	Will be alternating diagonals, so we will be increasing
+				and decreasing around the polygon.
+			*/
+			if (mode)
+			{
+				Output_Tri(*(index+increasing),*(index+decreasing),*(index+increasing+1),output,color1,color2,color3,where,where);
+				increasing++;
+			}
+			else
+			{
+				Output_Tri(*(index+decreasing),*(index+increasing),*(index+decreasing-1),output,color1,color2,color3,where,where);
+                    decreasing--;
+               }
+			mode = !mode;
+		} while ((decreasing - increasing) >= 2);
+
+	}
+}
+
+
+
+
diff --git a/Stripe_u/sgi_triangex.c b/Stripe_u/sgi_triangex.c
new file mode 100644
index 000000000..afa2fd7db
--- /dev/null
+++ b/Stripe_u/sgi_triangex.c
@@ -0,0 +1,584 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sgi_triangex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "outputex.h"
+#include "polverts.h"
+#include "sturctsex.h"
+#include "common.h"
+#include "util.h"
+
+
+int AdjacentEx(int id2,int id1, int *list, int size)
+{
+	/*	Return the vertex that is adjacent to id1,
+		but is not id2, in the list of integers.
+	*/
+
+	register int x=0;
+	
+	while (x < size)
+	{
+		if (*(list+x) == id1)
+		{
+			if ((x != (size -1)) && (x != 0))
+			{
+				if ( *(list+x+1) != id2)
+					return *(list+x+1);
+				else
+					return *(list+x-1);
+			}
+			else if (x == (size -1))
+			{
+				if (*(list) != id2)
+					return *(list);
+				else
+					return *(list+x-1);
+			}
+			else
+			{
+				if (*(list+size-1) != id2)
+					return *(list+size-1);
+				else
+					return *(list+x+1);
+			}
+		}
+		x++;
+	}
+	printf("Error in the list\n");
+	exit(0);
+}
+
+
+void Delete_From_ListEx(int id,int *list, int size)
+{
+	/*	Delete the occurence of id in the list.
+		(list has size size)
+	*/
+
+	int *temp;
+	register int x,y=0;
+
+	temp = (int *) malloc(sizeof(int) * size);
+	for (x=0; x<size; x++)
+	{
+		if (*(list+x) != id)
+		{
+			*(temp+y) = *(list+x);
+			y++;
+		}
+	}
+	if(y != (size-1))
+	{
+		printf("There is an error in the delete\n");
+		exit(0);
+	}
+	*(temp+size-1) = -1;
+	memcpy(list,temp,sizeof(int)*size);
+
+}
+
+
+void Triangulate_QuadEx(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,FILE *fp,int reversed,int face_id,
+                      int where)
+{
+	int vertex4,vertex5;
+	
+	/*	This routine will nonblindly triangulate a quad, meaning
+		that there is a definite input and a definite output
+		edge that we must adhere to. Reversed will tell the orientation
+		of the input edge. (Reversed is -1 is we do not have an input
+		edge, in other words we are at the beginning of a strip.)
+		Out_edge* is the output edge, and in_edge* is the input edge. 
+		Index are the edges of the polygon
+		and size is the size of the polygon. Begin is whether we are
+		at the start of a new strip.
+	*/
+	
+	/*	If we do not have an input edge, then we can make our input
+		edge whatever we like, therefore it will be easier to come
+		out on the output edge.
+	*/
+	if (reversed == -1)
+	{
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+		Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		return;
+	}
+	
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*   Are they consecutive so that we form a triangle to
+		peel off, but cannot use the whole quad?
+	*/
+
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge last. First output the triangle that comes out
+			the wrong edge.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+          Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+          Output_TriEx(vertex4,in_edge2,out_edge2,output,-1,-1,where);
+		return;
+	}
+	/*	The next case is where it is impossible to come out the
+		edge that we want. So we will have to start a new strip to
+		come out on that edge. We will output the one triangle
+		that we can, and then start the new strip with the triangle
+		that comes out on the edge that we want to come out on.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	We want to output the first triangle (whose output
+			edge is not the one that we want.
+			We have to find the vertex that we need, which is
+			the other vertex which we do not have.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
+		Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+		Output_TriEx(vertex4,in_edge1,out_edge2,output,-1,-1,where);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+		Output_TriEx(vertex4,in_edge1,out_edge1,output,-1,-1,where);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+		Output_TriEx(vertex4,in_edge2,out_edge1,output,-1,-1,where);
+		return;
+	}
+
+	/*	The final case is where we want to come out the opposite edge.*/
+	else
+	{
+           if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
+                    ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
+		 {
+			/*	We need to know the orientation of the input
+				edge, so we know which way to put the diagonal.
+                    And also the output edge, so that we triangulate correctly.
+               */
+			Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
+		 }
+		else
+		{
+			/*   Input and output orientation was reversed, so diagonal will
+				be reversed from above.
+			*/
+			Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
+		}
+		return;
+	}
+}
+
+void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,FILE *fp,int reversed,int face_id,
+                           int where)
+{
+	/*	We have a polygon that we need to nonblindly triangulate.
+		We will recursively try to triangulate it, until we are left
+		with a polygon of size 4, which can use the quad routine
+		from above. We will be taking off a triangle at a time
+		and outputting it. We will have 3 cases similar to the
+		cases for the quad above. The inputs to this routine
+		are the same as for the quad routine.
+	*/
+
+	int vertex4;
+	int *temp;
+
+		
+	/*	Since we are calling this recursively, we have to check whether
+		we are down to the case of the quad.
+	*/
+	
+    if (size == 4)
+	{
+		Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+					    index,output,fp,reversed,face_id,where);
+		return;
+	}
+
+    
+	
+	/*	We do not have a specified input edge, and therefore we
+		can make it anything we like, as long as we still come out 
+		the output edge that we want.
+	*/
+	if (reversed  == -1)
+	{
+		/*	Get the vertex for the last triangle, which is
+			the one coming out the output edge, before we do
+			any deletions to the list. We will be doing this
+			bottom up.
+		*/
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(out_edge2,index,size);
+		Triangulate_PolygonEx(out_edge1,vertex4,in_edge2,
+					   	  vertex4,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		/*	Lastly do the triangle that comes out the output
+			edge.
+		*/
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		return;
+	}
+
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off that comes out the correct output edge, 
+		but we cannot use the whole polygon?
+	*/
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge last. First recursively do the rest of the
+			polygon.
+		*/
+		/*	Do the rest of the polygon without the triangle. 
+			We will be doing a fan triangulation.
+		*/
+		/*	Get the vertex adjacent to in_edge1, but is not
+			in_edge2.
+		*/
+		vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+		Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+          Delete_From_ListEx(in_edge1,index,size);
+		Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
+						  vertex4,size-1,index,output,fp,!reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Next case is where it is again consecutive, but the triangle
+		formed by the consecutive edges do not come out of the
+		correct output edge. For this case, we can not do much to
+		keep it sequential. Try and do the fan.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+		Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+		/*	Since that triangle goes out of the polygon (the
+			output edge of it), we can make our new input edge
+			anything we like, so we will try to make it good for
+			the strip. (This will be like starting a new strip,
+			all so that we can go out the correct output edge.)
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(in_edge2,index,size);
+		Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
+						  vertex4,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+		Output_TriEx(in_edge2,in_edge1,vertex4,fp,-1,-1,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(in_edge2,index,size);
+          Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
+		      		       vertex4,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+		Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(in_edge1,index,size);
+          Triangulate_PolygonEx(out_edge1,out_edge2,vertex4,
+						  in_edge2,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Else the edge is not consecutive, and it is sufficiently
+		far away, for us not to make a conclusion at this time.
+		So we can take off a triangle and recursively call this
+		function.
+	*/
+	else
+	{
+			vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+			Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+			temp = (int *) malloc(sizeof(int) * size);
+			memcpy(temp,index,sizeof(int)*size);
+			Delete_From_ListEx(in_edge1,index,size);
+               Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
+						       vertex4,size-1,index,output,fp,!reversed,face_id,where);
+			memcpy(index,temp,sizeof(int)*size);
+		     return;
+	}
+}
+
+void TriangulateEx(int out_edge1,int out_edge2,int in_edge1,
+				 int in_edge2,int size,int *index,
+				 FILE *fp,FILE *output,int reversed,int face_id, int where)
+{
+	/*	We have the info we need to triangulate a polygon */
+
+	if (size == 4)
+		Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			              index,fp,output,reversed,face_id,where);
+	else
+		Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			                 index,fp,output,reversed,face_id,where);
+}
+
+void Non_Blind_TriangulateEx(int size,int *index, FILE *fp,
+						 FILE *output,int next_face_id,int face_id,int where)
+{
+	int id1,id2,id3;
+	int nedge1,nedge2;
+	int reversed;
+	/*	We have a polygon that has to be triangulated and we cannot
+		do it blindly, ie we will try to come out on the edge that
+		has the least number of adjacencies
+	*/
+
+	Last_Edge(&id1,&id2,&id3,0);
+	/*	Find the edge that is adjacent to the new face ,
+		also return whether the orientation is reversed in the
+		face of the input edge, which is id2 and id3.
+	*/
+	if (next_face_id == -1)
+    {
+        printf("The face is -1 and the size is %d\n",size);
+        exit(0);
+    }
+    
+    reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+	/*	Do the triangulation */
+	
+	/*	If reversed is -1, the input edge is not in the polygon, therefore we can have the
+		input edge to be anything we like, since we are at the beginning
+		of a strip
+	*/
+	TriangulateEx(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
+		         face_id, where);
+}
+
+void Rearrange_IndexEx(int *index, int size)
+{
+	/*	If we are in the middle of a strip we must find the
+		edge to start on, which is the last edge that we had
+		transmitted.
+	*/
+	int x,f,y,e1,e2,e3;
+	int increment = 1;
+     int *temp;
+
+	/*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+	for (y = 0; y < size; y++)
+	{
+		if (*(index+y) == e2)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e3))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e3))
+				break;
+               else if ((y != 0) && (*(index+y-1) == e3))
+               {
+                   increment = -1;
+                   break;
+               }
+               else if ((y==0) && (*(index+size-1) == e3))
+               {
+                   increment = -1;
+                   break;
+               }
+		}
+		if (*(index+y) == e3)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e2))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e2))
+				break;
+               else if ((y != 0) && (*(index+y-1) == e2))
+               {
+                   increment = -1;
+                   break;
+               }
+               else if ((y==0) && (*(index+size-1) == e2))
+               {
+                   increment = -1;
+                   break;
+               }
+		}
+		/*	Edge is not here, we are at the beginning */
+		if ((y == (size-1)) && (increment != -1))
+			return;
+	}
+	
+	/*	Now put the list into a new list, starting with the
+		input edge. Increment tells us whether we have to go 
+		forward or backward.
+	*/
+	/*	Was in good position already */
+	if ((y == 0) && (increment == 1)) 
+		return;
+	
+	            
+    temp = (int *) malloc(sizeof(int) * size);
+    memcpy(temp,index,sizeof(int)*size);
+
+	if (increment == 1)
+	{
+		x=0;
+		for (f = y ; f< size; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = 0; f < y ; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+	else
+	{
+		x=0;
+		for (f = y ; f >= 0; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = (size - 1); f > y ; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+}
+
+void Blind_TriangulateEx(int size, int *index, FILE *fp,
+						 FILE *output, BOOL begin, int where )
+{
+	/*	save sides in temp array, we need it so we know
+		about swaps.
+	*/
+	int mode, decreasing,increasing,e1,e2,e3;
+	int x = 0;
+	BOOL flag = FALSE;
+
+	/*	Rearrange the index list so that the input edge is first
+	*/
+	if (!begin)
+		Rearrange_IndexEx(index,size);
+	
+	/*	We are given a polygon of more than 3 sides
+		and want to triangulate it. We will output the
+		triangles to the output file.
+	*/
+	
+    /*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+     if (( (!begin) && (*(index) == e2) ) || (begin))
+     {
+	    Output_TriEx(*(index+0),*(index+1),*(index+size-1),fp,-1,-1,where);
+        /*	If we have a quad, (chances are yes), then we know that
+		we can just add one diagonal and be done. (divide the
+		quad into 2 triangles.
+        */
+        if (size == 4)
+        {
+		    Output_TriEx(*(index+1),*(index+size-1),*(index+2),fp,-1,-1,where);
+              return;
+        }
+        increasing = 1;
+        mode = 1;
+
+    }
+    else if (!begin)
+    {
+        Output_TriEx(*(index+1),*(index+0),*(index+size-1),fp,-1,-1,where);
+        if (size == 4)
+        {
+            Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
+            return;
+        }
+        Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
+        increasing = 2;
+        mode = 0;
+    }
+	if (size != 4)
+	{
+		/*	We do not have a quad, we have something bigger. */
+		decreasing = size - 1;
+		
+		do
+		{
+			/*	Will be alternating diagonals, so we will be increasing
+				and decreasing around the polygon.
+			*/
+			if (mode)
+			{
+				Output_TriEx(*(index+increasing),*(index+decreasing),*(index+increasing+1),fp,-1,-1,where);
+				increasing++;
+			}
+			else
+			{
+				Output_TriEx(*(index+decreasing),*(index+increasing),*(index+decreasing-1),fp,-1,-1,where);
+                    decreasing--;
+               }
+			mode = !mode;
+		} while ((decreasing - increasing) >= 2);
+
+	}
+}
+
+
diff --git a/Stripe_u/struct.c b/Stripe_u/struct.c
new file mode 100644
index 000000000..f822b1da7
--- /dev/null
+++ b/Stripe_u/struct.c
@@ -0,0 +1,549 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: struct.c
+     Contains routines that update structures, and micellaneous routines.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "polverts.h"
+#include "ties.h"
+#include "output.h"
+#include "triangulate.h"
+#include "sturcts.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+int out1 = -1;
+int out2 = -1;
+
+int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
+	        int size, int id1, int id2)
+{
+	/*	Put the edge that is adjacent to face_id into edge1
+		and edge2. For each edge see if it is adjacent to
+		face_id. Id1 and id2 is the input edge, so see if 
+		the orientation is reversed, and save it in reversed.
+	*/
+	register int x;
+	int reversed = -1;
+	BOOL set = FALSE;
+    
+     for (x=0; x< size; x++)
+	{
+		if (x == (size-1))
+		{
+			if ((*(index) == id1) && (*(index+size-1)==id2))
+			{
+				if (set)
+                         return 1;
+				reversed = 1;
+			}
+			else if ((*(index) == id2) && (*(index+size-1)==id1))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+				
+			if (Look_Up(*(index),*(index+size-1),face_id))
+			{
+				if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) &&
+                       ( (out2 == *(index)) || (out2 == *(index+size-1)) ))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				else if (out1 == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				if ((reversed != -1) && (set))  
+					return reversed;
+			}
+		}		
+		else
+		{
+			if ((*(index+x) == id1) && (*(index+x+1)==id2))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+			else if ((*(index+x) == id2) && (*(index+x+1)==id1))
+			{
+				if (set)
+					return 1;
+				reversed = 1;
+			}
+
+			if (Look_Up(*(index+x),*(index+x+1),face_id))
+			{
+				if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) &&
+                         ((out2 == *(index+x)) || (out2 == *(index+x+1))))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                         *edge2 = *(index+x+1);
+                    }
+				else if (out1 == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+				     *edge2 = *(index+x + 1);
+                    }
+				if ((reversed != -1) && (set))
+                         return reversed;
+			}
+		}
+	}			
+	if ((x == size) && (reversed != -1))
+	{
+		/*	Could not find the output edge */
+		printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2);
+		exit(0);
+	}
+	return reversed;
+}
+
+
+void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
+				 int *e2,int temp1,int temp2,int *ties)
+{
+	/*	We have a face id that needs to be decremented.
+		We have to determine where it is in the structure,
+		so that we can decrement it.
+	*/
+	/*	The number of adjacencies may have changed, so to locate
+		it may be a little tricky. However we know that the number
+		of adjacencies is less than or equal to the original number
+		of adjacencies,
+	*/
+	int y,size,tally=0;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+	PLISTINFO lpListInfo;
+	static int each_poly = 0;
+	BOOL there = FALSE;
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+	{
+		/*	Size of the polygon */
+        size = temp->nPolSize;
+        /*  We did it already */
+        if (size == 1)
+            return;
+        for (y = 0; y< size; y++)
+	   {
+			/*	If we are doing partial triangulation, we must check
+				to see whether the edge is still there in the polygon,
+				since we might have done a portion of the polygon
+				and saved the rest for later.
+			*/
+            if (y != (size-1))
+	  	  {
+				if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1)))
+					|| ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+		  }
+		  else
+		  {
+				if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1)))
+					|| ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+		  }
+	 }
+		
+      if (!there)
+		/*	Original edge was already used, we cannot use this polygon */
+			return;
+		
+	/*	We have a starting point to start our search to locate
+		this polygon. 
+	*/
+
+	/*	Check to see if this polygon was done */
+	lpListInfo = Done(face_id,59,&y);
+
+	if (lpListInfo == NULL)
+		return;
+
+     /*  Was not done, but there is an error in the adjacency calculations */
+     if (y == 0)
+     {
+            printf("There is an error in finding the adjacencies\n");
+            exit(0);
+     }
+
+     /*	Now put the face in the proper bucket depending on tally. */
+	/*	First add it to the new bucket, then remove it from the old */
+	Add_Sgi_Adj(y-1,face_id);
+	RemoveList(array[y],lpListInfo);
+        
+     /*	Save it if it was the smallest seen so far since then
+		it will be the next face 
+		Here we will have different options depending on
+		what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+	*/
+	/*	At a new strip */
+	if (*next_bucket == 60)
+		*ties = *ties + each_poly;
+	/*	Have a tie */
+	if (*next_bucket == (y-1))
+	{
+		Add_Ties(face_id);
+		each_poly++;
+	}
+	/*	At a new minimum */
+	if (*next_bucket > (y-1))
+	{
+		*next_bucket = y-1;
+		*min_face = face_id;
+		*e1 = temp1;
+		*e2 = temp2;
+		each_poly = 0;
+		Clear_Ties();
+		Add_Ties(face_id);
+	}
+     }
+}
+
+
+void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, 
+			 int current_face,int *e1,int *e2,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Delete one adjacency from it. Save the min
+		adjacency seen so far.
+	*/
+	register int count=0;
+	PF_EDGES temp = NULL;
+	ListHead *pListHead;
+	int next_face;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+	/*	It could be a new edge that we created. So we can
+		exit, since there is not a face adjacent to it.
+	*/
+		return;
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	Was a new edge that was created and therefore
+				does not have anything adjacent to it
+			*/
+			return;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return;
+
+	/*	Was adjacent to something */
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Now we need to decrement this faces' adjacencies.
+	*/
+	Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
+}
+
+
+int Change_Face(int face_id,int in1,int in2,
+				 ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check)
+{
+	/*	We are doing a partial triangulation and we need to
+		put the new face of triangle into the correct bucket
+	*/
+	int input_adj,y;
+	
+	/*	Find the old number of adjacencies to this face,
+		so we know where to delete it from
+	*/
+	y = Old_Adj(face_id);
+	
+	/*	Do we need to change the adjacency? Maybe the edge on the triangle
+		that was outputted was not adjacent to anything. We know if we
+		have to check by "check". We came out on the output edge
+		that we needed, then we know that the adjacencies will decrease
+		by exactly one.
+	*/
+	if (!no_check)
+	{
+		input_adj = Number_Adj(in1,in2,face_id);
+		/*	If there weren't any then don't do anything */
+		if (input_adj == 0)
+			return y;
+	}
+
+	RemoveList(pListHead,(PLISTINFO)temp);
+	/*	Before we had a quad with y adjacencies. The in edge
+		did not have an adjacency, since it was just deleted,
+		since we came in on it. The outedge must have an adjacency
+		otherwise we would have a bucket 0, and would not be in this
+		routine. Therefore the new adjacency must be y-1
+	*/
+    
+    Add_Sgi_Adj(y-1,face_id);
+    return (y-1);
+}
+
+int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
+					   int *ties)
+{
+	/*	Give the face with id face_id, we want to decrement
+		all the faces that are adjacent to it, since we will
+		be deleting face_id from the data structure.
+		We will return the face that has the least number
+		of adjacencies.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face = -1;
+	
+     *next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+		else
+			Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+	}
+	return (min_face);
+}
+
+
+void Find_Adj_Tally(int id1, int id2,int *next_bucket,int *min_face, 
+				int current_face,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Save the min adjacency seen so far.
+	*/
+	int size,each_poly=0,y,tally=0,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	int next_face;
+	BOOL there = FALSE;
+
+    
+    /*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	This was a new edge that was created, so it is
+		adjacent to nothing.
+	*/
+		return;
+
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	This was a new edge that we created */
+			return;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return;
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Find how many faces it is adjacent to.
+	*/
+	pListHead = PolFaces[next_face];
+	temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent 
+		polygons to this face. This will be the original number of
+		polygons adjacent to this polygon, we must then see if this
+		number has been decremented
+	*/	      		
+	if ( temp2 != NULL )
+	{
+		/*	Size of the polygon */
+		size = temp2->nPolSize;
+		/*  We did it already */
+          if (size == 1)
+            return;
+          for (y = 0; y< size; y++)
+		{
+			/*	Make sure that the edge is still in the
+				polygon and was not deleted, because if the edge was
+				deleted, then we used it already.
+			*/
+			if (y != (size-1))
+			{
+				if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+					|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{		
+				if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+		if (!there)
+			/*	Edge already used and deleted from the polygon*/
+			return;
+		
+		/*	See if the face was already deleted, and where
+			it is if it was not
+		*/
+		if (Done(next_face,size,&y) == NULL)
+			return;
+		
+		/*	Save it if it was the smallest seen so far since then
+			it will be the next face 
+			Here we will have different options depending on
+			what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+		*/
+		
+		/*	At a new strip */
+		if (*next_bucket == 60)
+			*ties = *ties + each_poly;
+		/*	Have a tie */
+		if (*next_bucket == (y-1))
+		{
+			Add_Ties(next_face);
+			each_poly++;
+		}
+		/*	At a new minimum */
+		if (*next_bucket > (y-1))
+		{
+			*next_bucket = y-1;
+			*min_face = next_face;
+			each_poly = 0;
+			Clear_Ties();
+			Add_Ties(next_face);
+		}
+	}
+}
+
+
+int Min_Face_Adj(int face_id, int *next_bucket, int *ties)
+{
+	/*	Used for the Partial triangulation to find the next
+		face. It will return the minimum adjacency face id
+		found at this face.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face,test_face;
+	
+	*next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Find_Adj_Tally(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,ties);
+		else
+			Find_Adj_Tally(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,ties);
+	}
+	/*    Maybe we can do better by triangulating the face, because
+          by triangulating the face we will go to a polygon of lesser
+          adjacencies
+    */
+    if (size == 4)
+    {
+         /*    Checking for a quad whether to do the whole polygon will
+               result in better performance because the triangles in the polygon
+               have less adjacencies
+         */
+         Check_In_Quad(face_id,&test_face);
+         if (*next_bucket > test_face)
+              /*    We can do better by going through the polygon */
+              min_face = face_id;
+    }
+
+    /*  We have a polygon with greater than 4 sides, check to see if going
+        inside is better than going outside the polygon for the output edge.
+    */
+    else
+    {
+        Check_In_Polygon(face_id,&test_face,size);
+        if (*next_bucket > test_face)
+            /*  We can do better by going through the polygon */
+            min_face = face_id;
+    }
+    
+    return (min_face);
+}
+
+
+
diff --git a/Stripe_u/struct.h b/Stripe_u/struct.h
new file mode 100644
index 000000000..6eb036cb4
--- /dev/null
+++ b/Stripe_u/struct.h
@@ -0,0 +1,6 @@
+
+struct vert_struct {
+	VRDATA	x, y, z;	/* point coordinates */
+};
+
+
diff --git a/Stripe_u/structex.c b/Stripe_u/structex.c
new file mode 100644
index 000000000..06adba7b5
--- /dev/null
+++ b/Stripe_u/structex.c
@@ -0,0 +1,553 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: structex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "polverts.h"
+#include "ties.h"
+#include "outputex.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+int out1Ex = -1;
+int out2Ex = -1;
+
+int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
+			int size, int id1, int id2)
+{
+	/*	Put the edge that is adjacent to face_id into edge1
+		and edge2. For each edge see if it is adjacent to
+		face_id. Id1 and id2 is the input edge, so see if 
+		the orientation is reversed, and save it in reversed.
+	*/
+	int x;
+	int reversed = -1;
+	BOOL set = FALSE;
+
+     for (x=0; x< size; x++)
+	{
+		if (x == (size-1))
+		{
+			if ((*(index) == id1) && (*(index+size-1)==id2))
+			{
+				if (set)
+                         return 1;
+				reversed = 1;
+			}
+			else if ((*(index) == id2) && (*(index+size-1)==id1))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+				
+			if (Look_Up(*(index),*(index+size-1),face_id))
+			{
+				if ( (out1Ex != -1) && ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) &&
+                       ( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) ))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				else if (out1Ex == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				if ((reversed != -1) && (set))  
+					return reversed;
+			}
+		}		
+		else
+		{
+			if ((*(index+x) == id1) && (*(index+x+1)==id2))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+			else if ((*(index+x) == id2) && (*(index+x+1)==id1))
+			{
+				if (set)
+					return 1;
+				reversed = 1;
+			}
+
+			if (Look_Up(*(index+x),*(index+x+1),face_id))
+			{
+				if ( (out1Ex != -1) && ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) &&
+                        ((out2Ex == *(index+x)) || (out2Ex == *(index+x+1))))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                         *edge2 = *(index+x+1);
+                    }
+				else if (out1Ex == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+				     *edge2 = *(index+x + 1);
+                    }
+				if ((reversed != -1) && (set))
+                         return reversed;
+			}
+		}
+	}			
+	if ((x == size) && (reversed != -1))
+	{
+		/*	Could not find the output edge */
+		printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex);
+		exit(0);
+	}
+	return reversed;
+}
+
+
+void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
+			    int *e2,int temp1,int temp2,int *ties)
+{
+	/*	We have a face id that needs to be decremented.
+		We have to determine where it is in the structure,
+		so that we can decrement it.
+	*/
+	/*	The number of adjacencies may have changed, so to locate
+		it may be a little tricky. However we know that the number
+		of adjacencies is less than or equal to the original number
+		of adjacencies,
+	*/
+	int y,size,tally=0;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+	PLISTINFO lpListInfo;
+	static int each_poly = 0;
+	BOOL there = FALSE;
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+	{
+		/*	Size of the polygon */
+        size = temp->nPolSize;
+        for (y = 0; y< size; y++)
+		{
+			/*	If we are doing partial triangulation, we must check
+				to see whether the edge is still there in the polygon,
+				since we might have done a portion of the polygon
+				and saved the rest for later.
+			*/
+               if (y != (size-1))
+			{
+				if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1)))
+					|| ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{
+				if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1)))
+					|| ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+          if (!there)
+		/*	Original edge was already used, we cannot use this polygon */
+			return;
+		
+		/*	We have a starting point to start our search to locate
+			this polygon. 
+		*/
+
+		/*	Check to see if this polygon was done */
+		lpListInfo = Done(face_id,59,&y);
+
+		if (lpListInfo == NULL)
+			return;
+
+          /*  Was not done, but there is an error in the adjacency calculations */
+          /*     If more than one edge is adj to it then maybe it was not updated */
+          if (y == 0)
+            return;
+			
+		/*	Now put the face in the proper bucket depending on tally. */
+		/*	First add it to the new bucket, then remove it from the old */
+		Add_Sgi_Adj(y-1,face_id);
+		RemoveList(array[y],lpListInfo);
+        
+          /*	Save it if it was the smallest seen so far since then
+			it will be the next face 
+			Here we will have different options depending on
+			what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+		*/
+		/*	At a new strip */
+		if (*next_bucket == 60)
+			*ties = *ties + each_poly;
+		/*	Have a tie */
+		if (*next_bucket == (y-1))
+		{
+			Add_Ties(face_id);
+			each_poly++;
+		}
+		/*	At a new minimum */
+		if (*next_bucket > (y-1))
+		{
+			*next_bucket = y-1;
+			*min_face = face_id;
+			*e1 = temp1;
+			*e2 = temp2;
+			each_poly = 0;
+			Clear_Ties();
+			Add_Ties(face_id);
+		}
+	}
+}
+
+
+void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, 
+				int current_face,int *e1,int *e2,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Delete one adjacency from it. Save the min
+		adjacency seen so far.
+	*/
+	register int count=0;
+	PF_EDGES temp = NULL;
+	ListHead *pListHead;
+	int next_face;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+	/*	It could be a new edge that we created. So we can
+		exit, since there is not a face adjacent to it.
+	*/
+		return;
+     while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	Was a new edge that was created and therefore
+				does not have anything adjacent to it
+			*/
+			return;
+    }
+	/*	Was not adjacent to anything else except itself */
+    if (temp->edge[2] == -1)
+		return;
+
+    /*	Was adjacent to something */
+    else
+    {
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Now we need to decrement this faces' adjacencies.
+	*/
+	Update_FaceEx(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
+}
+
+int Change_FaceEx(int face_id,int in1,int in2,
+				 ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check)
+{
+	/*	We are doing a partial triangulation and we need to
+		put the new face of triangle into the correct bucket
+	*/
+	int input_adj,y;
+     P_ADJACENCIES pfNode,lpListInfo;
+	
+     /*	Find the old number of adjacencies to this face,
+		so we know where to delete it from
+	*/
+	y = Old_Adj(face_id);
+	pListHead = array[y];
+
+     pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+	if ( pfNode )
+		pfNode->face_id = face_id;
+	lpListInfo = (P_ADJACENCIES) (SearchList(array[y], pfNode,
+                  (int (*)(void *,void *)) (Compare)));
+	if (lpListInfo == NULL)
+	{
+		printf("There is an error finding the next polygon3 %d\n",face_id);
+		exit(0);
+	}
+
+     /*	Do we need to change the adjacency? Maybe the edge on the triangle
+		that was outputted was not adjacent to anything. We know if we
+		have to check by "check". We came out on the output edge
+		that we needed, then we know that the adjacencies will decrease
+		by exactly one.
+	*/
+	if (!no_check)
+	{
+		input_adj = Number_Adj(in1,in2,face_id);
+		/*	If there weren't any then don't do anything */
+		if (input_adj == 0)
+			return y;
+	}
+     
+	RemoveList(pListHead,(PLISTINFO)/*(temp*/lpListInfo);
+	/*	Before we had a quad with y adjacencies. The in edge
+		did not have an adjacency, since it was just deleted,
+		since we came in on it. The outedge must have an adjacency
+		otherwise we would have a bucket 0, and would not be in this
+		routine. Therefore the new adjacency must be y-1
+	*/
+    
+    Add_Sgi_Adj(y-1,face_id);
+    return (y-1);
+}
+
+int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2,
+					int *ties)
+{
+	/*	Give the face with id face_id, we want to decrement
+		all the faces that are adjacent to it, since we will
+		be deleting face_id from the data structure.
+		We will return the face that has the least number
+		of adjacencies.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face = -1;
+	
+     *next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Delete_AdjEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+		else
+			Delete_AdjEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+	}
+	return (min_face);
+}
+
+
+
+void Find_Adj_TallyEx(int id1, int id2,int *next_bucket,int *min_face, 
+			       int current_face,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Save the min adjacency seen so far.
+	*/
+	int size,each_poly=0,y,tally=0,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	int next_face;
+	BOOL there = FALSE;
+
+    
+    /*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	This was a new edge that was created, so it is
+		adjacent to nothing.
+	*/
+		return;
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	This was a new edge that we created */
+			return;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return;
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Find how many faces it is adjacent to.
+	*/
+	pListHead = PolFaces[next_face];
+	temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent 
+		polygons to this face. This will be the original number of
+		polygons adjacent to this polygon, we must then see if this
+		number has been decremented
+	*/	      		
+	if ( temp2 != NULL )
+	{
+		/*	Size of the polygon */
+		size = temp2->nPolSize;
+		for (y = 0; y< size; y++)
+		{
+			/*	Make sure that the edge is still in the
+				polygon and was not deleted, because if the edge was
+				deleted, then we used it already.
+			*/
+			if (y != (size-1))
+			{
+				if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+					|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{		
+				if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+		if (!there)
+			/*	Edge already used and deleted from the polygon*/
+			return;
+		
+		/*	See if the face was already deleted, and where
+			it is if it was not
+		*/
+		if (Done(next_face,size,&y) == NULL)
+			return;
+		
+		/*	Save it if it was the smallest seen so far since then
+			it will be the next face 
+			Here we will have different options depending on
+			what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+		*/
+					
+		/*	At a new strip */
+		if (*next_bucket == 60)
+			*ties = *ties + each_poly;
+		/*	Have a tie */
+		if (*next_bucket == (y-1))
+		{
+			Add_Ties(next_face);
+			each_poly++;
+		}
+		/*	At a new minimum */
+		if (*next_bucket > (y-1))
+		{
+			*next_bucket = y-1;
+			*min_face = next_face;
+			each_poly = 0;
+			Clear_Ties();
+			Add_Ties(next_face);
+		}
+	}
+}
+
+
+int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties)
+{
+	/*	Used for the Partial triangulation to find the next
+		face. It will return the minimum adjacency face id
+		found at this face.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face,test_face;
+	
+	*next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Find_Adj_TallyEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,ties);
+		else
+			Find_Adj_TallyEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,ties);
+	}
+	/*    Maybe we can do better by triangulating the face, because
+          by triangulating the face we will go to a polygon of lesser
+          adjacencies
+    */
+    if (size == 4)
+    {
+         /*    Checking for a quad whether to do the whole polygon will
+               result in better performance because the triangles in the polygon
+               have less adjacencies
+         */
+         Check_In_Quad(face_id,&test_face);
+         if (*next_bucket > test_face)
+              /*    We can do better by going through the polygon */
+              min_face = face_id;
+    }
+
+    /*  We have a polygon with greater than 4 sides, check to see if going
+        inside is better than going outside the polygon for the output edge.
+    */
+    else
+    {
+        Check_In_Polygon(face_id,&test_face,size);
+        if (*next_bucket > test_face)
+            /*  We can do better by going through the polygon */
+            min_face = face_id;
+    }
+    
+    return (min_face);
+}
+
+
diff --git a/Stripe_u/sturcts.h b/Stripe_u/sturcts.h
new file mode 100644
index 000000000..07a2bbf97
--- /dev/null
+++ b/Stripe_u/sturcts.h
@@ -0,0 +1,31 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sturcts.h
+-----------------------------------------------------------------------*/
+
+#define EVEN(x) (((x) & 1) == 0)
+
+BOOL Get_Edge();
+void add_vert_id();
+void Update_Face();
+int Min_Adj();
+int Min_Face_Adj();
+int Change_Face();
+void Delete_Adj();
+int Update_Adjacencies();
+int Get_Output_Edge();
+int Find_Face();
+
+
+
+
+
+
+
diff --git a/Stripe_u/sturctsex.h b/Stripe_u/sturctsex.h
new file mode 100644
index 000000000..550228306
--- /dev/null
+++ b/Stripe_u/sturctsex.h
@@ -0,0 +1,28 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:sturctsex.h
+-----------------------------------------------------------------------*/
+
+#define EVEN(x) (((x) & 1) == 0)
+
+BOOL Get_EdgeEx();
+void add_vert_idEx();
+void Update_FaceEx();
+int Min_Face_AdjEx();
+int Change_FaceEx();
+void Delete_AdjEx();
+int Number_AdjEx();
+int Update_AdjacenciesEx();
+
+
+
+
+
+
diff --git a/Stripe_u/ties.c b/Stripe_u/ties.c
new file mode 100644
index 000000000..e1a64545c
--- /dev/null
+++ b/Stripe_u/ties.c
@@ -0,0 +1,304 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*	STRIPE: ties.c
+     This file will contain all the routines used to determine the next face if there
+	is a tie
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "ties.h"
+#include "sturctsex.h"
+#include "triangulatex.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+#define MAX_TIE 60
+int ties_array[60];
+int last = 0;
+
+void Clear_Ties()
+{
+	/*	Clear the buffer, because we do not have the tie
+		any more that we had before */
+	last = 0;
+}
+
+void Add_Ties(int id)
+{
+	/*	We have a tie to add to the buffer */
+	ties_array[last++] = id;
+}
+
+int Alternate_Tie()
+{
+	/*	Alternate in what we choose to break the tie 
+		We are just alternating between the first and
+		second thing that we found
+	*/
+	static int x = 0;
+	register int t;
+	
+	t = ties_array[x];
+	x++;
+	if (x == 2)
+		x = 0;
+	return t;
+}
+
+int Random_Tie()
+{
+	/*	Randomly choose the next face with which
+		to break the tie
+	*/
+	register int num;
+
+	num = rand();
+	while (num >= last)
+		num = num/20;
+	return (ties_array[num]);
+}
+
+int Look_Ahead(int id)
+{
+	/*	Look ahead at this face and save the minimum
+		adjacency of all the faces that are adjacent to
+		this face.
+	*/
+	return Min_Adj(id);
+}
+
+int Random_Look(int id[],int count)
+{
+	/*	We had a tie within a tie in the lookahead, 
+		break it randomly 
+	*/
+	register int num;
+
+	num = rand();
+	while (num >= count)
+		num = num/20;
+	return (id[num]);
+}
+
+
+int Look_Ahead_Tie()
+{
+	/*	Look ahead and find the face to go to that
+		will give the least number of adjacencies
+	*/
+	int id[60],t,x,f=0,min = 60;
+
+	for (x = 0; x < last; x++)
+	{
+		t = Look_Ahead(ties_array[x]);
+		/*	We have a tie */
+		if (t == min)
+			id[f++] = ties_array[x];
+		if (t < min)
+		{
+			f = 0;
+			min = t;
+			id[f++] = ties_array[x];
+		}
+	}
+	/*	No tie within the tie */
+	if ( f == 1)
+		return id[0];
+	/*	Or ties, but we are at the end of strips */
+	if (min == 0)
+		return id[0];
+	return (Random_Look(id,f));
+}
+
+
+int Sequential_Tri(int *index)
+{
+    /*  We have a triangle and need to break the ties at it.
+        We will choose the edge that is sequential. There
+        is definitely one since we know we have a triangle
+        and that there is a tie and there are only 2 edges
+        for the tie.
+    */
+    int reversed, e1,e2,e3,output1,output2,output3,output4;
+
+    /*  e2 and e3 are the input edge to the triangle */
+    Last_Edge(&e1,&e2,&e3,0);
+    
+    if ((e2 == 0) && (e3 == 0))
+        /*  Starting the strip, don't need to do this */
+        return ties_array[0];
+
+    /*  For the 2 ties find the edge adjacent to face id */
+    reversed = Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
+    reversed = Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0);
+
+    if ((output1 == e3) || (output2 == e3))
+        return ties_array[0];
+    if ((output3 == e3) || (output4 == e3))
+        return ties_array[1];
+    printf("There is an error trying to break sequential triangle \n");
+}
+
+int Sequential_Quad(int *index,	int triangulate)
+{
+    /*  We have a quad that need to break its ties, we will try
+        and choose a side that is sequential, otherwise use lookahead
+    */
+    int reversed,output1,output2,x,e1,e2,e3;
+
+    /*  e2 and e3 are the input edge to the quad */
+    Last_Edge(&e1,&e2,&e3,0);
+
+    /*  No input edge */
+    if ((e2 == 0) && (e3 == 0))
+        return ties_array[0];
+
+	/*  Go through the ties and see if there is a sequential one */
+    for (x = 0; x < last; x++)
+	{
+        reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0);
+        /*  Partial and whole triangulation will have different requirements */
+        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
+            return ties_array[x];
+        if (((output1 != e3) && (output1 != e2) &&
+                (output2 != e3) && (output2 != e2)))
+            return ties_array[x];
+    }
+    /*  There was not a tie that was sequential */
+	return Look_Ahead_Tie();
+}
+
+void Whole_Output(int in1,int in2, int *index, int size, int *out1, int *out2)
+{
+    /*  Used to sequentially break ties in the whole triangulation for polygons
+        greater than 4 sides. We will find the output edge that is good
+        for sequential triangulation.
+    */
+
+    int half;
+    
+    /*  Put the input edge first in the list */
+    Rearrange_IndexEx(index,size);
+
+    if (!(EVEN(size)))
+    {
+        if (*(index) == in1)
+            half = size/2 ;
+        else
+            half = size/2 +1;
+    }
+    else
+        half = size/2;
+
+    *out1 = *(index+half);
+    *out2 = *(index+half+1);
+}
+
+int Sequential_Poly(int size, int *index, int triangulate)
+{
+    /*  We have a polygon of greater than 4 sides and wish to break the
+        tie in the most sequential manner.
+    */
+
+    int x,reversed,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4;
+    
+    /*  e2 and e3 are the input edge to the quad */
+    Last_Edge(&e1,&e2,&e3,0);
+
+    /*  If we are using whole, find the output edge that is sequential */
+    if (triangulate == WHOLE)
+        Whole_Output(e2,e3,index,size,&output3,&output4);
+
+    /*  No input edge */
+    if ((e2 == 0) && (e3 == 0))
+        return ties_array[0];
+    
+    for (x = 0; x < last ; x++)
+    {
+        reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0);
+        /*  Partial that can be removed in just one triangle */
+        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
+            saved1 = ties_array[x];
+        /*  Partial removed in more than one triangle */
+        if ((output1 != e3) && (output1 != e2) && (output2 != e3) && (output2 != e2) &&
+            (triangulate == PARTIAL) && (saved2 != -1))
+            saved2 = ties_array[x];
+        /*  Whole is not so easy, since the whole polygon must be done. Given
+            an input edge there is only one way to come out, approximately half
+            way around the polygon.
+        */
+        if (((output1 == output3) && (output2 == output4)) ||
+            ((output1 == output4) && (output2 == output3)) &&
+            (triangulate == WHOLE))
+            return ties_array[x];
+    }
+    
+    if (saved1 != -1)
+        return saved1;
+    if (saved2 != -1)
+        return saved2;
+    
+    /*  There was not a tie that was sequential */
+    return Look_Ahead_Tie();
+}
+
+int Sequential_Tie(int face_id,int triangulate)
+{
+    /*  Break the tie by choosing the face that will
+        not give us a swap and is sequential. If there
+        is not one, then do the lookahead to break the
+        tie.
+    */
+    /*  Separate into 3 cases for simplicity, if the current
+        polygon has 3 sides, 4 sides or if the sides were 
+        greater. We can do the smaller cases faster, so that
+        is why I separated the cases.
+    */
+
+     ListHead *pListFace;
+	PF_FACES face;
+
+    /*	Get the polygon with id face_id */
+	pListFace  = PolFaces[face_id];
+	face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     if (face->nPolSize == 3)
+        return(Sequential_Tri(face->pPolygon));
+     if (face->nPolSize == 4)
+        return(Sequential_Quad(face->pPolygon,triangulate));
+     else
+        return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate));
+
+}
+
+int Get_Next_Face(int t, int face_id, int triangulate)
+{
+	/*	Get the next face depending on what
+		the user specified
+	*/
+	
+	/*	Did not have a tie, don't do anything */
+	if (last == 1)
+		return(ties_array[0]);
+	if (t == RANDOM)
+		return Random_Tie();
+	if (t == ALTERNATE)
+		return Alternate_Tie();
+	if (t == LOOK)
+		return Look_Ahead_Tie();
+     if (t == SEQUENTIAL)
+        return Sequential_Tie(face_id,triangulate);
+
+	printf("Illegal option specified for ties, using first \n");
+     return (ties_array[0]);
+}
diff --git a/Stripe_u/ties.h b/Stripe_u/ties.h
new file mode 100644
index 000000000..97e051765
--- /dev/null
+++ b/Stripe_u/ties.h
@@ -0,0 +1,15 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: ties.h
+-----------------------------------------------------------------------*/
+
+void Clear_Ties();
+void Add_Ties();
+int Get_Next_Face();
diff --git a/Stripe_u/triangulate.h b/Stripe_u/triangulate.h
new file mode 100644
index 000000000..de612119f
--- /dev/null
+++ b/Stripe_u/triangulate.h
@@ -0,0 +1,23 @@
+
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: triangulate.h
+-----------------------------------------------------------------------*/
+
+void Blind_Triangulate();
+void Non_Blind_Triangulate();
+int Adjacent();
+void Delete_From_List();
+void Triangulate_Polygon();
+void Rearrange_Index();
+void Find_Local_Strips();
+
+
+
diff --git a/Stripe_u/triangulatex.h b/Stripe_u/triangulatex.h
new file mode 100644
index 000000000..1710f0182
--- /dev/null
+++ b/Stripe_u/triangulatex.h
@@ -0,0 +1,23 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: triangulatex.h
+-----------------------------------------------------------------------*/
+
+enum swap_type
+{ ON, OFF};
+
+void SGI_StripEx();
+void Blind_TriangulateEx();
+void Non_Blind_TriangulateEx();
+int AdjacentEx();
+void Delete_From_ListEx();
+void Triangulate_PolygonEx();
+void Rearrange_IndexEx();
+void Find_StripsEx();
diff --git a/Stripe_u/util.c b/Stripe_u/util.c
new file mode 100644
index 000000000..f17fe5f7c
--- /dev/null
+++ b/Stripe_u/util.c
@@ -0,0 +1,272 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: util.c
+     This file contains routines that are used for various functions
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+#include "polverts.h"
+
+void switch_lower (int *x, int *y)
+{
+	register int temp;
+	
+	/*	Put lower value in x */
+	if (*y < *x)
+	{
+		temp = *x;
+		*x = *y;
+		*y = temp;
+	}
+}
+
+BOOL member(int x , int id1, int id2, int id3)
+{
+    /*  Is x in the triangle specified by id1,id2,id3 */
+    if ((x != id1) && (x != id2) && (x != id3))
+	return FALSE;
+    return TRUE;
+}
+
+
+int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2)
+{
+	/*	This will only return whether 2 adjacency nodes
+		are equivalent.								  
+	*/
+	if (node1->face_id == node2->face_id)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+
+BOOL Exist(int face_id, int id1, int id2)
+{
+	/*	Does the edge specified by id1 and id2 exist in this
+		face currently? Maybe we deleted in partial triangulation
+	*/
+	ListHead *pListHead;
+	PF_FACES temp;
+	register int x,size;
+	BOOL a=FALSE,b =FALSE; 
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	size = temp->nPolSize;
+	for (x=0; x<size; x++)
+	{
+		if (*(temp->pPolygon+x) == id1)
+			a = TRUE;
+		if (*(temp->pPolygon+x) == id2)
+			b = TRUE;
+		if (a && b)
+			return TRUE;
+	}
+	return FALSE;
+}
+
+int Get_Next_Id(int *index,int e3, int size)
+{
+    /*  Return the id following e3 in the list of vertices */
+
+    register int x;
+
+    for (x = 0; x< size; x++)
+    {
+        if ((*(index+x) == e3) && (x != (size-1)))
+            return *(index+x+1);
+        else if (*(index+x) == e3)
+            return *(index);
+    }
+    printf("There is an error in the next id\n");
+    exit(0);
+}
+
+int Different (int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y)
+{
+    /*    Find the vertex in the first 3 numbers that does not exist in 
+	     the last three numbers
+    */
+    if ((id1 != id4) && (id1 != id5) && (id1 != id6))
+    {
+	*x = id2;
+	*y = id3;
+	return id1;
+    }
+    if ((id2 != id4) && (id2 != id5) && (id2 != id6))
+    {
+	*x = id1;
+	*y = id3;
+	return id2;
+    }
+    if ((id3 != id4) && (id3 != id5) && (id3 != id6))
+    {
+	*x = id1;
+	*y = id2;
+	return id3;
+    }
+    
+    /*  Because there are degeneracies in the data, this might occur */
+    *x = id5;
+    *y = id6;
+    return id4;
+}
+
+int Return_Other(int *index,int e1,int e2)
+{
+	/*   We have a triangle and want to know the third vertex of it */
+	register int x;
+
+	for (x=0;x<3;x++)
+	{
+		if ((*(index+x) != e1) && (*(index+x) != e2))
+			return *(index+x);
+	}
+     /*   If there is a degenerate triangle return arbitrary */
+     return e1;
+}
+
+int Get_Other_Vertex(int id1,int id2,int id3,int *index)
+{
+	/*	We have a list index of 4 numbers and we wish to
+          return the number that is not id1,id2 or id3
+	*/
+	register int x;
+
+	for (x=0; x<4; x++)
+	{
+		if ((*(index+x) != id1) && (*(index+x) != id2) &&
+			(*(index+x) != id3))
+			return *(index+x);
+	}
+	/*   If there is some sort of degeneracy this might occur,
+          return arbitrary 
+     */
+     if (x==4)
+          return id1;
+}
+
+
+PLISTINFO Done(int face_id, int size, int *bucket)
+{
+	/*	Check to see whether the polygon with face_id was used
+		already, return NULL if it was, otherwise return a pointer to the face.
+	*/
+	P_ADJACENCIES pfNode;
+	register int y;
+	PLISTINFO lpListInfo;
+	
+	pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+	if ( pfNode )
+		pfNode->face_id = face_id;
+		
+	for (y=size; ; y--)
+	{
+		lpListInfo = SearchList(array[y], pfNode,
+			(int (*)(void *,void *)) (Compare));
+		if (lpListInfo != NULL)
+		{
+			*bucket = y;
+			return lpListInfo;
+		}
+		if (y == 0)
+		/*	This adjacent face was done already */
+			return lpListInfo;
+	}
+	free (pfNode);
+}
+
+void Output_Edge(int *index,int e2,int e3,int *output1,int *output2)
+{
+    /*  Given a quad and an input edge return the other 2 vertices of the
+        quad.
+    */
+    
+    *output1 = -1;
+    *output2 = -1;
+
+    if ((*(index) != e2) && (*(index) != e3))
+        *output1 = *(index);
+
+    if ((*(index+1) != e2) && (*(index+1) != e3))
+    {
+        if (*output1 == -1)
+            *output1 = *(index+1);
+        else
+        {
+            *output2 = *(index+1);
+            return;
+        }
+    }
+
+    if ((*(index+2) != e2) && (*(index+2) != e3))
+    {
+        if (*output1 == -1)
+            *output1 = *(index+2);
+        else
+        {
+            *output2 = *(index+2);
+            return;
+        }
+    }
+
+    *output2 = *(index+3);
+}
+
+
+void First_Edge(int *id1,int *id2, int *id3)
+{
+    /*  Get the first triangle in the strip we just found, we will use this to
+	   try to extend backwards in the strip
+    */
+
+    ListHead *pListHead;
+    register int num;
+    P_STRIPS temp1,temp2,temp3;
+	 
+    pListHead = strips[0];
+    num = NumOnList(pListHead);
+     
+    /*    Did not have a strip */
+    if (num < 3)
+         return;
+	  
+    temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
+    temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
+    temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
+    *id1 = temp1->face_id;
+    *id2 = temp2->face_id;
+    *id3 = temp3->face_id;
+ 
+}
+
+void Last_Edge(int *id1, int *id2, int *id3, BOOL save)
+{
+	/*   We need the last edge that we had  */
+	static int v1, v2, v3;
+
+	if (save)
+	{
+		v1 = *id1;
+		v2 = *id2;
+		v3 = *id3;
+	}
+	else
+	{
+		*id1 = v1;
+		*id2 = v2;
+		*id3 = v3;
+	}
+}
+
+
diff --git a/Stripe_u/util.h b/Stripe_u/util.h
new file mode 100644
index 000000000..2b43a4d35
--- /dev/null
+++ b/Stripe_u/util.h
@@ -0,0 +1,24 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: util.h
+-----------------------------------------------------------------------*/
+
+void switch_lower ();
+int Compare ();
+BOOL Exist();
+int Get_Next_Id();
+int Different();
+int Return_Other();
+int Get_Other_Vertex();
+PLISTINFO Done();
+void Output_Edge();
+void Last_Edge();
+void First_Edge();
+BOOL member();

From cd7233754fa98f5b507aead5e100374df0a29ac8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 14 Apr 1998 02:25:54 +0000
Subject: [PATCH 056/283] Code reorganizations.  Added a Lib/ directory for
 more general libraries.

---
 AssemTris/Makefile.am |  7 +++++--
 AssemTris/Makefile.in | 14 ++++++++------
 AssemTris/assemtris.c |  9 ++++++---
 FixNode/Makefile.am   | 14 +++++++++++---
 FixNode/Makefile.in   | 25 ++++++++++++++++---------
 FixNode/fixnode.cxx   |  9 ++++++---
 FixNode/main.cxx      |  5 ++++-
 FixObj/MAT3vec.c      |  2 +-
 FixObj/Makefile.am    |  5 ++++-
 FixObj/Makefile.in    | 11 +++++++----
 SplitTris/MAT3vec.c   |  2 +-
 SplitTris/Makefile.am |  7 +++++--
 SplitTris/Makefile.in | 16 +++++++++-------
 SplitTris/polar.c     | 10 +++++++---
 SplitTris/splittris.c |  9 ++++++---
 Stripe_u/Makefile.in  |  4 ++--
 Tools/Makefile.am     |  1 -
 Tools/Makefile.in     |  3 +--
 Tri2obj/MAT3vec.c     |  2 +-
 Tri2obj/Makefile.am   |  7 +++++--
 Tri2obj/Makefile.in   | 16 +++++++++-------
 Tri2obj/polar.c       | 10 +++++++---
 Tri2obj/tri2obj.c     |  9 ++++++---
 Triangle/Makefile.in  |  4 ++--
 24 files changed, 129 insertions(+), 72 deletions(-)

diff --git a/AssemTris/Makefile.am b/AssemTris/Makefile.am
index aed518219..190b0ec5a 100644
--- a/AssemTris/Makefile.am
+++ b/AssemTris/Makefile.am
@@ -29,13 +29,16 @@ bin_PROGRAMS = assemtris
 assemtris_SOURCES = assemtris.c assemtris.h
 
 assemtris_LDADD = \
-	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/04/14 02:25:59  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
 # Revision 1.1  1998/04/08 22:54:57  curt
 # Adopted Gnu automake/autoconf system.
 #
diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index 1bcc681b3..f40608c87 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -101,14 +101,14 @@ bin_PROGRAMS = assemtris
 assemtris_SOURCES = assemtris.c assemtris.h
 
 assemtris_LDADD = \
-	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 PROGRAMS =  $(bin_PROGRAMS)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
@@ -117,8 +117,7 @@ X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 assemtris_OBJECTS =  assemtris.o
-assemtris_DEPENDENCIES =  \
-$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+assemtris_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
 assemtris_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -341,10 +340,13 @@ clean-generic maintainer-clean-generic clean mostlyclean distclean \
 maintainer-clean
 
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/04/14 02:26:00  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
 # Revision 1.1  1998/04/08 22:54:57  curt
 # Adopted Gnu automake/autoconf system.
 #
diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index 835dc756e..572990386 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -36,7 +36,7 @@
 // #include <Math/fg_geodesy.h>
 // #include <Math/mat3.h>
 // #include <Math/polar.h>
-#include <Scenery/Bucket/bucketutils.h>
+#include <Bucket/bucketutils.h>
 
 
 int nodecount = 0;
@@ -454,9 +454,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.6  1998/04/08 22:54:58  curt
-/* Adopted Gnu automake/autoconf system.
+/* Revision 1.7  1998/04/14 02:26:00  curt
+/* Code reorganizations.  Added a Lib/ directory for more general libraries.
 /*
+ * Revision 1.6  1998/04/08 22:54:58  curt
+ * Adopted Gnu automake/autoconf system.
+ *
  * Revision 1.5  1998/03/03 16:00:52  curt
  * More c++ compile tweaks.
  *
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index 4445f8400..fa6b8ef2d 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -32,14 +32,22 @@ fixnode_SOURCES = \
 	triload.cxx triload.hxx
 
 fixnode_LDADD = \
-	$(top_builddir)/Tools/DEM/libDEM.la \
-        $(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/DEM/libDEM.la \
+        $(top_builddir)/Lib/Bucket/libBucket.la
 
-INCLUDES += -I.. -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+
+# We can't build this with "-O2" (optimization) since this causes a seg fault
+# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
+# setting it to "-g"
+CXXFLAGS = -g
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/04/14 02:26:02  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
 # Revision 1.1  1998/04/08 23:05:54  curt
 # Adopted Gnu automake/autoconf system.
 #
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index 091d3835a..828ad939a 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -104,15 +104,20 @@ fixnode_SOURCES = \
 	triload.cxx triload.hxx
 
 fixnode_LDADD = \
-	$(top_builddir)/Tools/DEM/libDEM.la \
-        $(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/DEM/libDEM.la \
+        $(top_builddir)/Lib/Bucket/libBucket.la
+
+# We can't build this with "-O2" (optimization) since this causes a seg fault
+# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
+# setting it to "-g"
+CXXFLAGS = -g
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 PROGRAMS =  $(bin_PROGRAMS)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
@@ -121,10 +126,9 @@ X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 fixnode_OBJECTS =  fixnode.o main.o triload.o
-fixnode_DEPENDENCIES =  $(top_builddir)/Tools/DEM/libDEM.la \
-$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+fixnode_DEPENDENCIES =  $(top_builddir)/Lib/DEM/libDEM.la \
+$(top_builddir)/Lib/Bucket/libBucket.la
 fixnode_LDFLAGS = 
-CXXFLAGS = @CXXFLAGS@
 CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
 CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
@@ -361,11 +365,14 @@ clean-generic maintainer-clean-generic clean mostlyclean distclean \
 maintainer-clean
 
 
-INCLUDES += -I.. -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.1  1998/04/08 23:05:55  curt
+# Revision 1.2  1998/04/14 02:26:03  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
+# Revision 1.1  1998/04/08 23:05:54  curt
 # Adopted Gnu automake/autoconf system.
 #
 # Revision 1.4  1998/04/06 21:09:44  curt
diff --git a/FixNode/fixnode.cxx b/FixNode/fixnode.cxx
index 8acf685a7..b4408fbe6 100644
--- a/FixNode/fixnode.cxx
+++ b/FixNode/fixnode.cxx
@@ -53,7 +53,7 @@ void fixnodes( char *filename, fgDEM dem,
 	       nodes[i][1], nodes[i][2]); */
 
 	nodes[i][2] = 
-	    dem.interpolate_altitude(dem_data, nodes[i][0], nodes[i][1]);
+	    dem.interpolate_altitude(nodes[i][0], nodes[i][1]);
 
 	/* printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
 	       nodes[i][1], nodes[i][2]); */
@@ -80,9 +80,12 @@ void fixnodes( char *filename, fgDEM dem,
 
 
 /* $Log$
-/* Revision 1.1  1998/04/08 23:05:56  curt
-/* Adopted Gnu automake/autoconf system.
+/* Revision 1.2  1998/04/14 02:26:03  curt
+/* Code reorganizations.  Added a Lib/ directory for more general libraries.
 /*
+ * Revision 1.1  1998/04/08 23:05:56  curt
+ * Adopted Gnu automake/autoconf system.
+ *
  * Revision 1.5  1998/03/19 02:50:19  curt
  * Updated to support -lDEM class.
  *
diff --git a/FixNode/main.cxx b/FixNode/main.cxx
index 840ee23ae..8130ab8d4 100644
--- a/FixNode/main.cxx
+++ b/FixNode/main.cxx
@@ -93,7 +93,7 @@ int main(int argc, char **argv) {
 
     // load the corresponding dem file so we can interpolate elev values
     dem.open(demfile);
-    dem.parse(dem_data);
+    dem.parse();
     dem.close();
 
     // process all the *.1.node files in the specified directory
@@ -104,6 +104,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.2  1998/04/14 02:26:04  curt
+// Code reorganizations.  Added a Lib/ directory for more general libraries.
+//
 // Revision 1.1  1998/04/08 23:05:57  curt
 // Adopted Gnu automake/autoconf system.
 //
diff --git a/FixObj/MAT3vec.c b/FixObj/MAT3vec.c
index 24f2939af..a971ebe10 100644
--- a/FixObj/MAT3vec.c
+++ b/FixObj/MAT3vec.c
@@ -19,7 +19,7 @@
  * The two vectors involved may be the same.
  */
 
-#include <Math/mat3.h>
+#include "mat3.h"
 
 #ifndef TRUE
 #  define TRUE 1
diff --git a/FixObj/Makefile.am b/FixObj/Makefile.am
index 3e33b5d82..4be395bd8 100644
--- a/FixObj/Makefile.am
+++ b/FixObj/Makefile.am
@@ -30,11 +30,14 @@ fixobj_SOURCES = main.c mat3.h obj.c obj.h MAT3vec.c
 
 fixobj_LDADD =
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir)
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/04/14 02:26:05  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
 # Revision 1.1  1998/04/08 23:19:35  curt
 # Adopted Gnu automake/autoconf system.
 #
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index 6c2a3683e..21f91603d 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -102,12 +102,12 @@ fixobj_SOURCES = main.c mat3.h obj.c obj.h MAT3vec.c
 
 fixobj_LDADD =
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 PROGRAMS =  $(bin_PROGRAMS)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
@@ -339,11 +339,14 @@ clean-generic maintainer-clean-generic clean mostlyclean distclean \
 maintainer-clean
 
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir)
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.1  1998/04/08 23:19:36  curt
+# Revision 1.2  1998/04/14 02:26:05  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
+# Revision 1.1  1998/04/08 23:19:35  curt
 # Adopted Gnu automake/autoconf system.
 #
 # Revision 1.2  1998/01/21 02:55:53  curt
diff --git a/SplitTris/MAT3vec.c b/SplitTris/MAT3vec.c
index 24f2939af..a971ebe10 100644
--- a/SplitTris/MAT3vec.c
+++ b/SplitTris/MAT3vec.c
@@ -19,7 +19,7 @@
  * The two vectors involved may be the same.
  */
 
-#include <Math/mat3.h>
+#include "mat3.h"
 
 #ifndef TRUE
 #  define TRUE 1
diff --git a/SplitTris/Makefile.am b/SplitTris/Makefile.am
index ca10cc328..aeac1186e 100644
--- a/SplitTris/Makefile.am
+++ b/SplitTris/Makefile.am
@@ -34,13 +34,16 @@ splittris_SOURCES = \
 	splittris.c splittris.h
 
 splittris_LDADD = \
-	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/04/14 02:26:06  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
 # Revision 1.1  1998/04/08 23:21:10  curt
 # Adopted Gnu automake/autoconf system.
 #
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index 7eab72fae..b72e5c752 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -106,14 +106,14 @@ splittris_SOURCES = \
 	splittris.c splittris.h
 
 splittris_LDADD = \
-	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 PROGRAMS =  $(bin_PROGRAMS)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
@@ -122,8 +122,7 @@ X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 splittris_OBJECTS =  MAT3vec.o fg_geodesy.o polar.o splittris.o
-splittris_DEPENDENCIES =  \
-$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+splittris_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
 splittris_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -347,11 +346,14 @@ clean-generic maintainer-clean-generic clean mostlyclean distclean \
 maintainer-clean
 
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.1  1998/04/08 23:21:11  curt
+# Revision 1.2  1998/04/14 02:26:07  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
+# Revision 1.1  1998/04/08 23:21:10  curt
 # Adopted Gnu automake/autoconf system.
 #
 # Revision 1.3  1998/01/21 02:55:55  curt
diff --git a/SplitTris/polar.c b/SplitTris/polar.c
index c304f183b..e67881971 100644
--- a/SplitTris/polar.c
+++ b/SplitTris/polar.c
@@ -27,9 +27,10 @@
 #include <math.h>
 #include <stdio.h>
 
-#include <Math/polar.h>
 #include <Include/fg_constants.h>
 
+#include "polar.h"
+
 
 /* we can save these values between calls for efficiency */
 static double st, ct, sp, cp;
@@ -101,9 +102,12 @@ struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p) {
 
 
 /* $Log$
-/* Revision 1.1  1998/04/08 23:21:12  curt
-/* Adopted Gnu automake/autoconf system.
+/* Revision 1.2  1998/04/14 02:26:07  curt
+/* Code reorganizations.  Added a Lib/ directory for more general libraries.
 /*
+ * Revision 1.1  1998/04/08 23:21:12  curt
+ * Adopted Gnu automake/autoconf system.
+ *
  * Revision 1.5  1998/01/27 00:48:00  curt
  * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
  * system and commandline/config file processing code.
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index 38b87b227..e346285e4 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -36,7 +36,7 @@
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
-#include <Scenery/Bucket/bucketutils.h>
+#include <Bucket/bucketutils.h>
 
 #include "fg_geodesy.h"
 #include "mat3.h"
@@ -612,9 +612,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.7  1998/04/08 23:21:13  curt
-/* Adopted Gnu automake/autoconf system.
+/* Revision 1.8  1998/04/14 02:26:08  curt
+/* Code reorganizations.  Added a Lib/ directory for more general libraries.
 /*
+ * Revision 1.7  1998/04/08 23:21:13  curt
+ * Adopted Gnu automake/autoconf system.
+ *
  * Revision 1.6  1998/03/03 15:36:13  curt
  * Tweaks for compiling with g++
  *
diff --git a/Stripe_u/Makefile.in b/Stripe_u/Makefile.in
index f012c211e..db9d8599e 100644
--- a/Stripe_u/Makefile.in
+++ b/Stripe_u/Makefile.in
@@ -100,12 +100,12 @@ strips_SOURCES = \
 	triangulate.h triangulatex.h \
 	util.c util.h
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 PROGRAMS =  $(bin_PROGRAMS)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index e8ab79034..f2a48ea4b 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -2,7 +2,6 @@ EXTRA_DIST = process-dem.pl
 
 SUBDIRS = \
 	AssemTris \
-	DEM \
 	Dem2node \
 	FixNode \
 	FixObj \
diff --git a/Tools/Makefile.in b/Tools/Makefile.in
index 03dc3845e..65188d202 100644
--- a/Tools/Makefile.in
+++ b/Tools/Makefile.in
@@ -75,7 +75,6 @@ EXTRA_DIST = process-dem.pl
 
 SUBDIRS = \
 	AssemTris \
-	DEM \
 	Dem2node \
 	FixNode \
 	FixObj \
@@ -86,7 +85,7 @@ SUBDIRS = \
 
 bin_SCRIPTS = process-dem.pl
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../Simulator/Include/config.h
+CONFIG_HEADER = ../Include/config.h
 CONFIG_CLEAN_FILES = 
 SCRIPTS =  $(bin_SCRIPTS)
 
diff --git a/Tri2obj/MAT3vec.c b/Tri2obj/MAT3vec.c
index 24f2939af..a971ebe10 100644
--- a/Tri2obj/MAT3vec.c
+++ b/Tri2obj/MAT3vec.c
@@ -19,7 +19,7 @@
  * The two vectors involved may be the same.
  */
 
-#include <Math/mat3.h>
+#include "mat3.h"
 
 #ifndef TRUE
 #  define TRUE 1
diff --git a/Tri2obj/Makefile.am b/Tri2obj/Makefile.am
index 4b3cba1f1..13bece460 100644
--- a/Tri2obj/Makefile.am
+++ b/Tri2obj/Makefile.am
@@ -34,13 +34,16 @@ tri2obj_SOURCES = \
 	polar.c polar.h
 
 tri2obj_LDADD = \
-	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/04/14 02:26:09  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
 # Revision 1.1  1998/04/08 23:22:13  curt
 # Adopted Gnu automake/autoconf system.
 #
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index 7bac2edd1..e344583f9 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -106,14 +106,14 @@ tri2obj_SOURCES = \
 	polar.c polar.h
 
 tri2obj_LDADD = \
-	$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 PROGRAMS =  $(bin_PROGRAMS)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
@@ -122,8 +122,7 @@ X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 tri2obj_OBJECTS =  tri2obj.o MAT3vec.o fg_geodesy.o polar.o
-tri2obj_DEPENDENCIES =  \
-$(top_builddir)/Simulator/Scenery/Bucket/libBucket.la
+tri2obj_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
 tri2obj_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -347,11 +346,14 @@ clean-generic maintainer-clean-generic clean mostlyclean distclean \
 maintainer-clean
 
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.1  1998/04/08 23:22:14  curt
+# Revision 1.2  1998/04/14 02:26:10  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
+# Revision 1.1  1998/04/08 23:22:13  curt
 # Adopted Gnu automake/autoconf system.
 #
 # Revision 1.2  1998/01/21 02:55:46  curt
diff --git a/Tri2obj/polar.c b/Tri2obj/polar.c
index fae264766..665efec33 100644
--- a/Tri2obj/polar.c
+++ b/Tri2obj/polar.c
@@ -27,9 +27,10 @@
 #include <math.h>
 #include <stdio.h>
 
-#include <Math/polar.h>
 #include <Include/fg_constants.h>
 
+#include "polar.h"
+
 
 /* we can save these values between calls for efficiency */
 static double st, ct, sp, cp;
@@ -101,9 +102,12 @@ struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p) {
 
 
 /* $Log$
-/* Revision 1.1  1998/04/08 23:22:16  curt
-/* Adopted Gnu automake/autoconf system.
+/* Revision 1.2  1998/04/14 02:26:10  curt
+/* Code reorganizations.  Added a Lib/ directory for more general libraries.
 /*
+ * Revision 1.1  1998/04/08 23:22:16  curt
+ * Adopted Gnu automake/autoconf system.
+ *
  * Revision 1.5  1998/01/27 00:48:00  curt
  * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
  * system and commandline/config file processing code.
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index fb0f8ddb2..482906b37 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -34,7 +34,7 @@
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
-#include <Scenery/Bucket/bucketutils.h>
+#include <Bucket/bucketutils.h>
 
 #include "fg_geodesy.h"
 #include "mat3.h"
@@ -640,9 +640,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.12  1998/04/08 23:22:18  curt
-/* Adopted Gnu automake/autoconf system.
+/* Revision 1.13  1998/04/14 02:26:11  curt
+/* Code reorganizations.  Added a Lib/ directory for more general libraries.
 /*
+ * Revision 1.12  1998/04/08 23:22:18  curt
+ * Adopted Gnu automake/autoconf system.
+ *
  * Revision 1.11  1998/03/03 16:01:00  curt
  * More c++ compile tweaks.
  *
diff --git a/Triangle/Makefile.in b/Triangle/Makefile.in
index eed70e754..e5a0a2ccf 100644
--- a/Triangle/Makefile.in
+++ b/Triangle/Makefile.in
@@ -86,12 +86,12 @@ bin_PROGRAMS = triangle # showme
 
 triangle_SOURCES = triangle.c triangle.h
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 PROGRAMS =  $(bin_PROGRAMS)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@

From 1f7da4f54e024084c705efd93d945ca43c35d415 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 14 Apr 1998 02:43:27 +0000
Subject: [PATCH 057/283] Used "new" to auto-allocate large DEM parsing arrays
 in class constructor.

---
 DEM/dem.cxx | 50 ++++++++++++++++++++++----------------------------
 DEM/dem.hxx | 35 ++++++++++++++++-------------------
 2 files changed, 38 insertions(+), 47 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 77a7c5c81..b328c39e8 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -45,6 +45,8 @@
 
 fgDEM::fgDEM( void ) {
     // printf("class fgDEM CONstructor called.\n");
+    dem_data = new float[DEM_SIZE_1][DEM_SIZE_1];
+    output_data = new float[DEM_SIZE_1][DEM_SIZE_1];
 }
 
 
@@ -315,8 +317,7 @@ void fgDEM::read_a_record( void ) {
 
 
 // read and parse DEM "B" record
-void fgDEM::read_b_record(float dem_data[DEM_SIZE_1][DEM_SIZE_1])
-{
+void fgDEM::read_b_record( void ) {
     char token[80];
     int i;
 
@@ -353,7 +354,7 @@ void fgDEM::read_b_record(float dem_data[DEM_SIZE_1][DEM_SIZE_1])
 
 
 // parse dem file
-int fgDEM::parse( float dem_data[DEM_SIZE_1][DEM_SIZE_1] ) {
+int fgDEM::parse( void ) {
     int i;
 
     cur_row = 0;
@@ -361,7 +362,8 @@ int fgDEM::parse( float dem_data[DEM_SIZE_1][DEM_SIZE_1] ) {
     read_a_record();
 
     for ( i = 0; i < dem_num_profiles; i++ ) {
-	read_b_record( dem_data );
+	// printf("Ready to read next b record\n");
+	read_b_record();
 	cur_col++;
 
 	if ( cur_col % 100 == 0 ) {
@@ -377,9 +379,7 @@ int fgDEM::parse( float dem_data[DEM_SIZE_1][DEM_SIZE_1] ) {
 
 // return the current altitude based on mesh data.  We should rewrite
 // this to interpolate exact values, but for now this is good enough
-double fgDEM::interpolate_altitude( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
-				    double lon, double lat)
-{
+double fgDEM::interpolate_altitude( double lon, double lat ) {
     // we expect incoming (lon,lat) to be in arcsec for now
 
     double xlocal, ylocal, dx, dy, zA, zB, elev;
@@ -492,10 +492,7 @@ double fgDEM::interpolate_altitude( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
 
 
 // Use least squares to fit a simpler data set to dem data
-void fgDEM::fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
-		 float output_data[DEM_SIZE_1][DEM_SIZE_1], 
-		 char *fg_root, double error, struct fgBUCKET *p )
-{
+void fgDEM::fit( char *fg_root, double error, struct fgBUCKET *p ) {
     double x[DEM_SIZE_1], y[DEM_SIZE_1];
     double m, b, ave_error, max_error;
     double cury, lasty;
@@ -504,7 +501,7 @@ void fgDEM::fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
     // FILE *dem, *fit, *fit1;
 
     printf("Initializing output mesh structure\n");
-    outputmesh_init( output_data );
+    outputmesh_init();
 
     // determine dimensions
     colmin = p->x * ( (cols - 1) / 8);
@@ -514,10 +511,10 @@ void fgDEM::fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
     printf("Fitting region = %d,%d to %d,%d\n", colmin, rowmin, colmax, rowmax);
     
     // include the corners explicitly
-    outputmesh_set_pt(output_data, colmin, rowmin, dem_data[colmin][rowmin]);
-    outputmesh_set_pt(output_data, colmin, rowmax, dem_data[colmin][rowmax]);
-    outputmesh_set_pt(output_data, colmax, rowmax, dem_data[colmax][rowmax]);
-    outputmesh_set_pt(output_data, colmax, rowmin, dem_data[colmax][rowmin]);
+    outputmesh_set_pt(colmin, rowmin, dem_data[colmin][rowmin]);
+    outputmesh_set_pt(colmin, rowmax, dem_data[colmin][rowmax]);
+    outputmesh_set_pt(colmax, rowmax, dem_data[colmax][rowmax]);
+    outputmesh_set_pt(colmax, rowmin, dem_data[colmax][rowmin]);
 
     printf("Beginning best fit procedure\n");
 
@@ -598,7 +595,7 @@ void fgDEM::fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
 	    if ( start > colmin ) {
 		// skip this for the first line segment
 		cury = m * x[0] + b;
-		outputmesh_set_pt(output_data, start, row, (lasty + cury) / 2);
+		outputmesh_set_pt(start, row, (lasty + cury) / 2);
 		// fprintf(fit, "%.2f %.2f\n", x[0], (lasty + cury) / 2);
 	    }
 
@@ -625,12 +622,12 @@ void fgDEM::fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1],
 	// printf("Please hit return: "); gets(junk);
     }
 
-    outputmesh_output_nodes(output_data, fg_root, p);
+    outputmesh_output_nodes(fg_root, p);
 }
 
 
 // Initialize output mesh structure
-void fgDEM::outputmesh_init( float output_data[DEM_SIZE_1][DEM_SIZE_1] ) {
+void fgDEM::outputmesh_init( void ) {
     int i, j;
     
     for ( j = 0; j < DEM_SIZE_1; j++ ) {
@@ -642,26 +639,20 @@ void fgDEM::outputmesh_init( float output_data[DEM_SIZE_1][DEM_SIZE_1] ) {
 
 
 // Get the value of a mesh node
-double fgDEM::outputmesh_get_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
-				 int i, int j )
-{
+double fgDEM::outputmesh_get_pt( int i, int j ) {
     return ( output_data[i][j] );
 }
 
 
 // Set the value of a mesh node
-void fgDEM::outputmesh_set_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
-			       int i, int j, double value )
-{
+void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
     // printf("Setting data[%d][%d] = %.2f\n", i, j, value);
    output_data[i][j] = value;
 }
 
 
 // Write out a node file that can be used by the "triangle" program
-void fgDEM::outputmesh_output_nodes( float output_data[DEM_SIZE_1][DEM_SIZE_1],
-				     char *fg_root, struct fgBUCKET *p )
-{
+void fgDEM::outputmesh_output_nodes( char *fg_root, struct fgBUCKET *p ) {
     struct stat stat_buf;
     char base_path[256], dir[256], file[256];
 #ifdef WIN32
@@ -763,6 +754,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.2  1998/04/14 02:43:27  curt
+// Used "new" to auto-allocate large DEM parsing arrays in class constructor.
+//
 // Revision 1.1  1998/04/08 22:57:22  curt
 // Adopted Gnu automake/autoconf system.
 //
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index a3b5f215c..ae6ae2f79 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -30,7 +30,7 @@
 
 #include <stdio.h>
 
-#include <Scenery/Bucket/bucketutils.h>
+#include <Bucket/bucketutils.h>
 
 
 #define DEM_SIZE 1200
@@ -50,9 +50,9 @@ class fgDEM {
     // Distance between column and row data points (in arc seconds)
     double col_step, row_step;
     
-    // the actual mesh data allocated here
-    // float dem_data[DEM_SIZE_1][DEM_SIZE_1];
-    // float output_data[DEM_SIZE_1][DEM_SIZE_1];
+    // pointers to the actual mesh data allocated here
+    float (*dem_data)[DEM_SIZE_1];
+    float (*output_data)[DEM_SIZE_1];
 
     // Current "A" Record Information
     char dem_description[80], dem_quadrangle[80];
@@ -83,13 +83,13 @@ public:
     int close ( void );
 
     // parse a DEM file
-    int parse( float dem_data[DEM_SIZE_1][DEM_SIZE_1] );
+    int parse( void );
 
     // read and parse DEM "A" record
-    void read_a_record( );
+    void read_a_record( void );
 
     // read and parse DEM "B" record
-    void read_b_record( float dem_data[DEM_SIZE_1][DEM_SIZE_1] );
+    void read_b_record( void );
 
     // Informational methods
     double info_originx( void ) { return(originx); }
@@ -98,28 +98,22 @@ public:
     // return the current altitude based on mesh data.  We should
     // rewrite this to interpolate exact values, but for now this is
     // good enough
-    double interpolate_altitude( float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
-				 double lon, double lat);
+    double interpolate_altitude( double lon, double lat );
 
     // Use least squares to fit a simpler data set to dem data
-    void fit( float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
-	      float output_data[DEM_SIZE_1][DEM_SIZE_1], 
-	      char *fg_root, double error, struct fgBUCKET *p );
+    void fit( char *fg_root, double error, struct fgBUCKET *p );
 
     // Initialize output mesh structure
-    void outputmesh_init( float output_data[DEM_SIZE_1][DEM_SIZE_1] );
+    void outputmesh_init( void );
 
     // Get the value of a mesh node
-    double outputmesh_get_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
-			      int i, int j );
+    double outputmesh_get_pt( int i, int j );
 
     // Set the value of a mesh node
-    void outputmesh_set_pt( float output_data[DEM_SIZE_1][DEM_SIZE_1],
-			    int i, int j, double value );
+    void outputmesh_set_pt( int i, int j, double value );
 
     // Write out a node file that can be used by the "triangle" program
-    void outputmesh_output_nodes( float output_data[DEM_SIZE_1][DEM_SIZE_1],
-				  char *fg_root, struct fgBUCKET *p );
+    void outputmesh_output_nodes( char *fg_root, struct fgBUCKET *p );
 
     // Destructor
     ~fgDEM( void );
@@ -130,6 +124,9 @@ public:
 
 
 // $Log$
+// Revision 1.2  1998/04/14 02:43:28  curt
+// Used "new" to auto-allocate large DEM parsing arrays in class constructor.
+//
 // Revision 1.1  1998/04/08 22:57:23  curt
 // Adopted Gnu automake/autoconf system.
 //

From e4a1a341ccc4f315afe27cfe3195b915c31d2061 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 14 Apr 1998 02:43:57 +0000
Subject: [PATCH 058/283] Code reorganizations.  Added a Lib/ directory for
 more general libraries.

---
 DEM/Makefile.am |  7 ++++++-
 DEM/Makefile.in | 18 +++++++++++-------
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/DEM/Makefile.am b/DEM/Makefile.am
index d24cc6b35..aeb7ecf2c 100644
--- a/DEM/Makefile.am
+++ b/DEM/Makefile.am
@@ -4,5 +4,10 @@ lib_LTLIBRARIES = libDEM.la
 
 libDEM_la_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+
+# We can't build this with "-O2" (optimization) since this causes a seg fault
+# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
+# setting it to "-g"
+CXXFLAGS = -g
 
diff --git a/DEM/Makefile.in b/DEM/Makefile.in
index 81e385ab9..bd39aee3c 100644
--- a/DEM/Makefile.in
+++ b/DEM/Makefile.in
@@ -75,13 +75,18 @@ libdir  = ${exec_prefix}/lib
 lib_LTLIBRARIES = libDEM.la
 
 libDEM_la_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
+
+# We can't build this with "-O2" (optimization) since this causes a seg fault
+# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
+# setting it to "-g"
+CXXFLAGS = -g
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
 LTLIBRARIES =  $(lib_LTLIBRARIES)
 
 
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
@@ -92,7 +97,6 @@ X_PRE_LIBS = @X_PRE_LIBS@
 libDEM_la_LDFLAGS = 
 libDEM_la_LIBADD = 
 libDEM_la_OBJECTS =  dem.lo leastsqs.lo
-CXXFLAGS = @CXXFLAGS@
 CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
 CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
@@ -113,7 +117,7 @@ all: Makefile $(LTLIBRARIES)
 .SUFFIXES:
 .SUFFIXES: .S .c .cxx .lo .o .s
 $(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/DEM/Makefile
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Lib/DEM/Makefile
 
 Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
 	cd $(top_builddir) \
@@ -211,14 +215,14 @@ maintainer-clean-tags:
 
 distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
 
-subdir = Tools/DEM
+subdir = Lib/DEM
 
 distdir: $(DISTFILES)
 	here=`cd $(top_builddir) && pwd`; \
 	top_distdir=`cd $(top_distdir) && pwd`; \
 	distdir=`cd $(distdir) && pwd`; \
 	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/DEM/Makefile
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Lib/DEM/Makefile
 	@for file in $(DISTFILES); do \
 	  d=$(srcdir); \
 	  test -f $(distdir)/$$file \
@@ -328,7 +332,7 @@ installdirs mostlyclean-generic distclean-generic clean-generic \
 maintainer-clean-generic clean mostlyclean distclean maintainer-clean
 
 
-INCLUDES += -I../../Simulator
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.

From 7bc397dd6534cb9848acb6d1e9f6ef8956d9b72e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 18 Apr 1998 03:53:05 +0000
Subject: [PATCH 059/283] Added zlib support.

---
 DEM/dem.cxx | 47 ++++++++++++++++++++++++++++++++++-------------
 DEM/dem.hxx |  6 +++++-
 2 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index b328c39e8..821f23fc3 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -32,6 +32,8 @@
 #include <sys/stat.h> // stat()
 #include <unistd.h>   // stat()
 
+#include <zlib/zlib.h>
+
 #include "dem.hxx"
 #include "leastsqs.hxx"
 
@@ -100,10 +102,11 @@ int fgDEM::open ( char *file ) {
     // open input file (or read from stdin)
     if ( strcmp(file, "-") == 0 ) {
 	printf("Loading DEM data file: stdin\n");
-	fd = stdin;
+	// fd = stdin;
+	fd = gzdopen(STDIN_FILENO, "r");
     } else {
-	if ( (fd = fopen(file, "r")) == NULL ) {
-	    printf("Cannot open %s\n", file);
+	if ( (fd = gzopen(file, "r")) == NULL ) {
+	    printf("Cannot gzopen %s\n", file);
 	    return(0);
 	}
 	printf("Loading DEM data file: %s\n", file);
@@ -115,19 +118,31 @@ int fgDEM::open ( char *file ) {
 
 // close a DEM file
 int fgDEM::close ( void ) {
-    fclose(fd);
+    gzclose(fd);
 
     return(1);
 }
 
 
 // return next token from input stream
-static void next_token(FILE *fd, char *token) {
-    int result;
+static void next_token(gzFile *fd, char *token) {
+    int i, result;
+    char c;
 
-    result = fscanf(fd, "%s", token);
+    i = 0;
+    c = gzgetc(fd);
+    // skip past spaces
+    while ( (c != -1) && (c == ' ') ) {
+	c = gzgetc(fd);
+    }
+    while ( (c != -1) && (c != ' ') && (c != '\n') ){
+	token[i] = c;
+	i++;
+	c = gzgetc(fd);
+    }
+    token[i] = '\0';
 
-    if ( result == EOF ) {
+    if ( c == -1 ) {
 	strcpy(token, "__END_OF_FILE__");
 	printf("    Warning:  Reached end of file!\n");
     }
@@ -137,7 +152,7 @@ static void next_token(FILE *fd, char *token) {
 
 
 // return next integer from input stream
-static int next_int(FILE *fd) {
+static int next_int(gzFile *fd) {
     char token[80];
 
     next_token(fd, token);
@@ -146,7 +161,7 @@ static int next_int(FILE *fd) {
 
 
 // return next double from input stream
-static double next_double(FILE *fd) {
+static double next_double(gzFile *fd) {
     char token[80];
 
     next_token(fd, token);
@@ -155,12 +170,15 @@ static double next_double(FILE *fd) {
 
 
 // return next exponential num from input stream
-static int next_exp(FILE *fd) {
+static int next_exp(gzFile *fd) {
+    char token[80];
     double mantissa;
     int exp, acc;
     int i;
 
-    fscanf(fd, "%lfD%d", &mantissa, &exp);
+    next_token(fd, token);
+
+    sscanf(token, "%lfD%d", &mantissa, &exp);
 
     // printf("    Mantissa = %.4f  Exp = %d\n", mantissa, exp);
 
@@ -189,7 +207,7 @@ void fgDEM::read_a_record( void ) {
 
     // get the name field (144 characters)
     for ( i = 0; i < 144; i++ ) {
-	name[i] = fgetc(fd);
+	name[i] = gzgetc(fd);
     }
     name[i+1] = '\0';
 
@@ -754,6 +772,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.3  1998/04/18 03:53:05  curt
+// Added zlib support.
+//
 // Revision 1.2  1998/04/14 02:43:27  curt
 // Used "new" to auto-allocate large DEM parsing arrays in class constructor.
 //
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index ae6ae2f79..23f55b4aa 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -31,6 +31,7 @@
 #include <stdio.h>
 
 #include <Bucket/bucketutils.h>
+#include <zlib/zlib.h>
 
 
 #define DEM_SIZE 1200
@@ -39,7 +40,7 @@
 
 class fgDEM {
     // file pointer for input
-    FILE *fd;
+    gzFile *fd;
 
     // coordinates (in arc seconds) of south west corner
     double originx, originy;
@@ -124,6 +125,9 @@ public:
 
 
 // $Log$
+// Revision 1.3  1998/04/18 03:53:06  curt
+// Added zlib support.
+//
 // Revision 1.2  1998/04/14 02:43:28  curt
 // Used "new" to auto-allocate large DEM parsing arrays in class constructor.
 //

From e9faab034f4bc1bff99765f45f7c05ca21ff7f62 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 18 Apr 1998 03:57:53 +0000
Subject: [PATCH 060/283] Added zlib library support.

---
 Tools/process-dem.pl | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index a9454b0b8..c98be79a6 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -43,11 +43,7 @@ $do_fixobj =     1;
 # set the FG_ROOT environment variable if it hasn't already been set.
 if ( $ENV{FG_ROOT} eq "" ) {
     # look for a file called fgtop as a place marker
-    if ( -e "fgtop" ) {
-        $ENV{FG_ROOT} = ".";
-    } elsif ( -e "../fgtop" ) {
-        $ENV{FG_ROOT} = "..";
-    }
+    die "You must remember to set the FG_ROOT environment variable!\n";
 }
 
 
@@ -124,11 +120,7 @@ sub file_root {
 #     irregularly fitted vertices
 
 sub dem2node {
-    if ( $dem_file =~ m/.gz$/ ) {
-	$command = "gzip -dc $dem_file | Dem2node/dem2node $ENV{FG_ROOT} - $error";
-    } else {
-	$command = "Dem2node/dem2node $ENV{FG_ROOT} $dem_file $error";
-    }
+    $command = "Dem2node/dem2node $ENV{FG_ROOT} $dem_file $error";
     $command = fix_command($command);
     print "Running '$command'\n";
 
@@ -179,11 +171,7 @@ sub triangle_1 {
 #     fixed file.1.node
 
 sub fixnode {
-    if ( $dem_file =~ m/.gz$/ ) {
-	$command = "gzip -dc $dem_file | FixNode/fixnode - $subdir";
-    } else {
-	$command = "FixNode/fixnode $dem_file $subdir";
-    }
+    $command = "FixNode/fixnode $dem_file $subdir";
     $command = fix_command($command);
     print "Running '$command'\n";
     open(OUT, "$command |");
@@ -387,6 +375,9 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.16  1998/04/18 03:57:53  curt
+# Added zlib library support.
+#
 # Revision 1.15  1998/04/08 23:24:07  curt
 # Adopted Gnu automake/autoconf system.
 #

From 58dc64b85e0664d0d5551352a97fdaf0a4bf06a7 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 18 Apr 1998 03:58:32 +0000
Subject: [PATCH 061/283] Added DemRaw2ascii/ to process 30 arcsec Ascii DEM
 file formats.

---
 Tools/Makefile.am | 1 +
 Tools/Makefile.in | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index f2a48ea4b..2147c3a22 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	AssemTris \
 	Dem2node \
+	DemRaw2ascii \
 	FixNode \
 	FixObj \
 	SplitTris \
diff --git a/Tools/Makefile.in b/Tools/Makefile.in
index 65188d202..352c4f3de 100644
--- a/Tools/Makefile.in
+++ b/Tools/Makefile.in
@@ -76,6 +76,7 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	AssemTris \
 	Dem2node \
+	DemRaw2ascii \
 	FixNode \
 	FixObj \
 	SplitTris \

From 2c866a0b5cda9013f4198d8267cf8192daee08b1 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 18 Apr 1998 03:59:44 +0000
Subject: [PATCH 062/283] Incorporated into gnu automake/autoconf system.

---
 DemRaw2ascii/Makefile.am |  40 +++++
 DemRaw2ascii/Makefile.in | 352 +++++++++++++++++++++++++++++++++++++++
 DemRaw2ascii/rawdem.c    |  17 +-
 3 files changed, 403 insertions(+), 6 deletions(-)
 create mode 100644 DemRaw2ascii/Makefile.am
 create mode 100644 DemRaw2ascii/Makefile.in

diff --git a/DemRaw2ascii/Makefile.am b/DemRaw2ascii/Makefile.am
new file mode 100644
index 000000000..ab05c9034
--- /dev/null
+++ b/DemRaw2ascii/Makefile.am
@@ -0,0 +1,40 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started February 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+bin_PROGRAMS = raw2ascii
+
+raw2ascii_SOURCES = main.c rawdem.c
+
+raw2ascii_LDADD = 
+
+INCLUDES += 
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/18 03:59:44  curt
+# Incorporated into gnu automake/autoconf system.
+#
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
new file mode 100644
index 000000000..3e72c38fc
--- /dev/null
+++ b/DemRaw2ascii/Makefile.in
@@ -0,0 +1,352 @@
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started February 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = raw2ascii
+
+raw2ascii_SOURCES = main.c rawdem.c
+
+raw2ascii_LDADD = 
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+raw2ascii_OBJECTS =  main.o rawdem.o
+raw2ascii_DEPENDENCIES = 
+raw2ascii_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/main.P .deps/rawdem.P
+SOURCES = $(raw2ascii_SOURCES)
+OBJECTS = $(raw2ascii_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/DemRaw2ascii/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+raw2ascii: $(raw2ascii_OBJECTS) $(raw2ascii_DEPENDENCIES)
+	@rm -f raw2ascii
+	$(LINK) $(raw2ascii_LDFLAGS) $(raw2ascii_OBJECTS) $(raw2ascii_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/DemRaw2ascii
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/DemRaw2ascii/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+INCLUDES += 
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/04/18 03:59:45  curt
+# Incorporated into gnu automake/autoconf system.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/DemRaw2ascii/rawdem.c b/DemRaw2ascii/rawdem.c
index ae6679f09..bab0bb105 100644
--- a/DemRaw2ascii/rawdem.c
+++ b/DemRaw2ascii/rawdem.c
@@ -325,7 +325,8 @@ void rawDumpAsciiDEM( fgRAWDEM *raw, char *path, int ilon, int ilat ) {
 	/* row / column id of this profile */
 	fprintf(fd, "%6d%6d", 1, j + 1);
 
-	/* Number of columns and rows (elevations) in this profile */
+	/* Number of rows and columns (elevation points) in this
+           profile */
 	fprintf(fd, "%6d%6d", 3600 / raw->xdim + 1, 1);
 
 	/* Ground planimetric coordinates (arc-seconds) of the first
@@ -342,7 +343,8 @@ void rawDumpAsciiDEM( fgRAWDEM *raw, char *path, int ilon, int ilat ) {
 	fprintf(fd, "   %20.15E", 0.0);
 	fprintf(fd, "   %20.15E", 0.0);
 
-	/* One (usually) dimensional array (prof_num_cols,1) of elevations */
+	/* One (usually) dimensional array (1,prof_num_cols) of
+           elevations */
 	for ( i = 0; i <= 120; i++ ) {
 	    fprintf(fd, "%6.0f", raw->edge[j][i]);
 	}
@@ -440,11 +442,14 @@ void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path ) {
 
 
 /* $Log$
-/* Revision 1.4  1998/04/06 21:09:43  curt
-/* Additional win32 support.
-/* Fixed a bad bug in dem file parsing that was causing the output to be
-/* flipped about x = y.
+/* Revision 1.5  1998/04/18 03:59:46  curt
+/* Incorporated into gnu automake/autoconf system.
 /*
+ * Revision 1.4  1998/04/06 21:09:43  curt
+ * Additional win32 support.
+ * Fixed a bad bug in dem file parsing that was causing the output to be
+ * flipped about x = y.
+ *
  * Revision 1.3  1998/03/03 13:10:29  curt
  * Close to a working version.
  *

From db45671ad3b6ec7f9f1438c8649b674c62769306 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 18 Apr 1998 04:01:01 +0000
Subject: [PATCH 063/283] Now use libMath rather than having local copies of
 math routines.

---
 FixObj/MAT3vec.c       | 149 --------------------------
 FixObj/Makefile.am     |   9 +-
 FixObj/Makefile.in     |  15 +--
 FixObj/mat3.h          | 147 --------------------------
 FixObj/obj.c           |   9 +-
 SplitTris/MAT3vec.c    | 149 --------------------------
 SplitTris/Makefile.am  |  13 ++-
 SplitTris/Makefile.in  |  23 ++---
 SplitTris/fg_geodesy.c | 230 -----------------------------------------
 SplitTris/fg_geodesy.h | 163 -----------------------------
 SplitTris/mat3.h       | 147 --------------------------
 SplitTris/polar.c      | 128 -----------------------
 SplitTris/polar.h      |  93 -----------------
 SplitTris/splittris.c  |  13 ++-
 Tri2obj/MAT3vec.c      | 149 --------------------------
 Tri2obj/Makefile.am    |  13 ++-
 Tri2obj/Makefile.in    |  23 ++---
 Tri2obj/fg_geodesy.c   | 230 -----------------------------------------
 Tri2obj/fg_geodesy.h   | 163 -----------------------------
 Tri2obj/mat3.h         | 147 --------------------------
 Tri2obj/polar.c        | 128 -----------------------
 Tri2obj/polar.h        |  93 -----------------
 Tri2obj/tri2obj.c      |  13 ++-
 23 files changed, 71 insertions(+), 2176 deletions(-)
 delete mode 100644 FixObj/MAT3vec.c
 delete mode 100644 FixObj/mat3.h
 delete mode 100644 SplitTris/MAT3vec.c
 delete mode 100644 SplitTris/fg_geodesy.c
 delete mode 100644 SplitTris/fg_geodesy.h
 delete mode 100644 SplitTris/mat3.h
 delete mode 100644 SplitTris/polar.c
 delete mode 100644 SplitTris/polar.h
 delete mode 100644 Tri2obj/MAT3vec.c
 delete mode 100644 Tri2obj/fg_geodesy.c
 delete mode 100644 Tri2obj/fg_geodesy.h
 delete mode 100644 Tri2obj/mat3.h
 delete mode 100644 Tri2obj/polar.c
 delete mode 100644 Tri2obj/polar.h

diff --git a/FixObj/MAT3vec.c b/FixObj/MAT3vec.c
deleted file mode 100644
index a971ebe10..000000000
--- a/FixObj/MAT3vec.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
-
-/* --------------------------------------------------------------------------
- * This file contains routines that operate on matrices and vectors, or
- * vectors and vectors.
- * -------------------------------------------------------------------------*/
-
-/* #include "sphigslocal.h" */
-
-/* --------------------------  Static Routines	---------------------------- */
-
-/* -------------------------  Internal Routines  --------------------------- */
-
-/* --------------------------  Public Routines	---------------------------- */
-
-/*
- * Multiplies a vector by a matrix, setting the result vector.
- * It assumes all homogeneous coordinates are 1.
- * The two vectors involved may be the same.
- */
-
-#include "mat3.h"
-
-#ifndef TRUE
-#  define TRUE 1
-#endif
-
-#ifndef FALSE
-#  define FALSE 0
-#endif
-
-
-void
-MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
-{
-   MAT3vec		tempvec;
-   register double	*temp = tempvec;
-
-   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
-		vec[2] * mat[2][0] +	      mat[3][0];
-   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
-		vec[2] * mat[2][1] +	      mat[3][1];
-   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
-		vec[2] * mat[2][2] +	      mat[3][2];
-
-   MAT3_COPY_VEC(result_vec, temp);
-}
-
-/*
- * Multiplies a vector of size 4 by a matrix, setting the result vector.
- * The fourth element of the vector is the homogeneous coordinate, which
- * may or may not be 1.  If the "normalize" parameter is TRUE, then the
- * result vector will be normalized so that the homogeneous coordinate is 1.
- * The two vectors involved may be the same.
- * This returns zero if the vector was to be normalized, but couldn't be.
- */
-
-int
-MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
-{
-   MAT3hvec             tempvec;
-   double		norm_fac;
-   register double	*temp = tempvec;
-   register int 	ret = TRUE;
-
-   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
-		vec[2] * mat[2][0] + vec[3] * mat[3][0];
-   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
-		vec[2] * mat[2][1] + vec[3] * mat[3][1];
-   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
-		vec[2] * mat[2][2] + vec[3] * mat[3][2];
-   temp[3] =	vec[0] * mat[0][3] + vec[1] * mat[1][3] +
-		vec[2] * mat[2][3] + vec[3] * mat[3][3];
-
-   /* Normalize if asked for, possible, and necessary */
-   if (normalize) {
-      if (MAT3_IS_ZERO(temp[3])) {
-#ifndef THINK_C
-	 fprintf (stderr,
-		  "Can't normalize vector: homogeneous coordinate is 0");
-#endif
-	 ret = FALSE;
-      }
-      else {
-	 norm_fac = 1.0 / temp[3];
-	 MAT3_SCALE_VEC(result_vec, temp, norm_fac);
-	 result_vec[3] = 1.0;
-      }
-   }
-   else MAT3_COPY_HVEC(result_vec, temp);
-
-   return(ret);
-}
-
-/*
- * Sets the first vector to be the cross-product of the last two vectors.
- */
-
-void
-MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
-{
-   MAT3vec		tempvec;
-   register double	*temp = tempvec;
-
-   temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
-   temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
-   temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
-
-   MAT3_COPY_VEC(result_vec, temp);
-}
-
-/*
- * Finds a vector perpendicular to vec and stores it in result_vec.
- * Method:  take any vector (we use <0,1,0>) and subtract the
- * portion of it pointing in the vec direction.  This doesn't
- * work if vec IS <0,1,0> or is very near it.  So if this is
- * the case, use <0,0,1> instead.
- * If "is_unit" is TRUE, the given vector is assumed to be unit length.
- */
-
-#define SELECT	.7071	/* selection constant (roughly .5*sqrt(2) */
-
-void
-MAT3perp_vec(double *result_vec, double *vec, int is_unit)
-{
-   MAT3vec	norm;
-   double	dot;
-
-   MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
-
-   MAT3_COPY_VEC(norm, vec);
-
-   if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
-
-   /* See if vector is too close to <0,1,0>.  If so, use <0,0,1> */
-   if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
-      result_vec[1] = 0.0;
-      result_vec[2] = 1.0;
-      dot = MAT3_DOT_PRODUCT(norm, result_vec);
-   }
-
-   /* Subtract off non-perpendicular part */
-   result_vec[0] -= dot * norm[0];
-   result_vec[1] -= dot * norm[1];
-   result_vec[2] -= dot * norm[2];
-
-   /* Make result unit length */
-   MAT3_NORMALIZE_VEC(result_vec, dot);
-}
diff --git a/FixObj/Makefile.am b/FixObj/Makefile.am
index 4be395bd8..e041122ea 100644
--- a/FixObj/Makefile.am
+++ b/FixObj/Makefile.am
@@ -26,15 +26,18 @@
 
 bin_PROGRAMS = fixobj
 
-fixobj_SOURCES = main.c mat3.h obj.c obj.h MAT3vec.c
+fixobj_SOURCES = main.c obj.c obj.h
 
-fixobj_LDADD =
+fixobj_LDADD = $(top_builddir)/Lib/Math/libMath.la
 
-INCLUDES += -I$(top_builddir)
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/04/18 04:01:02  curt
+# Now use libMath rather than having local copies of math routines.
+#
 # Revision 1.2  1998/04/14 02:26:05  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index 21f91603d..de2c960d3 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -98,9 +98,9 @@ VERSION = @VERSION@
 
 bin_PROGRAMS = fixobj
 
-fixobj_SOURCES = main.c mat3.h obj.c obj.h MAT3vec.c
+fixobj_SOURCES = main.c obj.c obj.h
 
-fixobj_LDADD =
+fixobj_LDADD = $(top_builddir)/Lib/Math/libMath.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
@@ -115,8 +115,8 @@ X_CFLAGS = @X_CFLAGS@
 X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
-fixobj_OBJECTS =  main.o obj.o MAT3vec.o
-fixobj_DEPENDENCIES = 
+fixobj_OBJECTS =  main.o obj.o
+fixobj_DEPENDENCIES =  $(top_builddir)/Lib/Math/libMath.la
 fixobj_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -129,7 +129,7 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 TAR = tar
 GZIP = --best
-DEP_FILES =  .deps/MAT3vec.P .deps/main.P .deps/obj.P
+DEP_FILES =  .deps/main.P .deps/obj.P
 SOURCES = $(fixobj_SOURCES)
 OBJECTS = $(fixobj_OBJECTS)
 
@@ -339,10 +339,13 @@ clean-generic maintainer-clean-generic clean mostlyclean distclean \
 maintainer-clean
 
 
-INCLUDES += -I$(top_builddir)
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/04/18 04:01:02  curt
+# Now use libMath rather than having local copies of math routines.
+#
 # Revision 1.2  1998/04/14 02:26:05  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
diff --git a/FixObj/mat3.h b/FixObj/mat3.h
deleted file mode 100644
index 58c4b9e07..000000000
--- a/FixObj/mat3.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
-
-/* -------------------------------------------------------------------------
-		       Public MAT3 include file
-   ------------------------------------------------------------------------- */
-
-#ifndef MAT3_HAS_BEEN_INCLUDED
-#define MAT3_HAS_BEEN_INCLUDED
-
-/* -----------------------------  Constants  ------------------------------ */
-
-/*
- * Make sure the math library .h file is included, in case it wasn't.
- */
-
-#ifndef HUGE
-#include <math.h>
-#endif
-#include <stdio.h>
-
-
-#define MAT3_DET0	-1			/* Indicates singular mat */
-#define MAT3_EPSILON	1e-12			/* Close enough to zero   */
-#define MAT3_PI 	3.141592653589793	/* Pi			  */
-
-/* ------------------------------  Types  --------------------------------- */
-
-typedef double MAT3mat[4][4];		/* 4x4 matrix			 */
-typedef double MAT3vec[3];		/* Vector			 */
-typedef double MAT3hvec[4];             /* Vector with homogeneous coord */
-
-/* ------------------------------  Macros  -------------------------------- */
-
-/* Tests if a number is within EPSILON of zero */
-#define MAT3_IS_ZERO(N) 	((N) < MAT3_EPSILON && (N) > -MAT3_EPSILON)
-
-/* Sets a vector to the three given values */
-#define MAT3_SET_VEC(V,X,Y,Z)	((V)[0]=(X), (V)[1]=(Y), (V)[2]=(Z))
-
-/* Tests a vector for all components close to zero */
-#define MAT3_IS_ZERO_VEC(V)	(MAT3_IS_ZERO((V)[0]) && \
-				 MAT3_IS_ZERO((V)[1]) && \
-				 MAT3_IS_ZERO((V)[2]))
-
-/* Dot product of two vectors */
-#define MAT3_DOT_PRODUCT(V1,V2) \
-			((V1)[0]*(V2)[0] + (V1)[1]*(V2)[1] + (V1)[2]*(V2)[2])
-
-/* Copy one vector to other */
-#define MAT3_COPY_VEC(TO,FROM)	((TO)[0] = (FROM)[0], \
-				 (TO)[1] = (FROM)[1], \
-				 (TO)[2] = (FROM)[2])
-
-/* Normalize vector to unit length, using TEMP as temporary variable.
- * TEMP will be zero if vector has zero length */
-#define MAT3_NORMALIZE_VEC(V,TEMP) \
-	if ((TEMP = sqrt(MAT3_DOT_PRODUCT(V,V))) > MAT3_EPSILON) { \
-	   TEMP = 1.0 / TEMP; \
-	   MAT3_SCALE_VEC(V,V,TEMP); \
-	} else TEMP = 0.0
-
-/* Scale vector by given factor, storing result vector in RESULT_V */
-#define MAT3_SCALE_VEC(RESULT_V,V,SCALE) \
-	MAT3_SET_VEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), (V)[2]*(SCALE))
-
-/* Adds vectors V1 and V2, storing result in RESULT_V */
-#define MAT3_ADD_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
-			       (V1)[2]+(V2)[2])
-
-/* Subtracts vector V2 from V1, storing result in RESULT_V */
-#define MAT3_SUB_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
-			       (V1)[2]-(V2)[2])
-
-/* Multiplies vectors V1 and V2, storing result in RESULT_V */
-#define MAT3_MULT_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
-			       (V1)[2]*(V2)[2])
-
-/* Sets RESULT_V to the linear combination of V1 and V2, scaled by
- * SCALE1 and SCALE2, respectively */
-#define MAT3_LINEAR_COMB(RESULT_V,SCALE1,V1,SCALE2,V2) \
-	MAT3_SET_VEC(RESULT_V,	(SCALE1)*(V1)[0] + (SCALE2)*(V2)[0], \
-				(SCALE1)*(V1)[1] + (SCALE2)*(V2)[1], \
-				(SCALE1)*(V1)[2] + (SCALE2)*(V2)[2])
-
-/* Several of the vector macros are useful for homogeneous-coord vectors */
-#define MAT3_SET_HVEC(V,X,Y,Z,W) ((V)[0]=(X), (V)[1]=(Y), \
-				  (V)[2]=(Z), (V)[3]=(W))
-
-#define MAT3_COPY_HVEC(TO,FROM) ((TO)[0] = (FROM)[0], \
-				 (TO)[1] = (FROM)[1], \
-				 (TO)[2] = (FROM)[2], \
-				 (TO)[3] = (FROM)[3])
-
-#define MAT3_SCALE_HVEC(RESULT_V,V,SCALE) \
-	MAT3_SET_HVEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), \
-				(V)[2]*(SCALE), (V)[3]*(SCALE))
-
-#define MAT3_ADD_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
-				(V1)[2]+(V2)[2], (V1)[3]+(V2)[3])
-
-#define MAT3_SUB_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
-				(V1)[2]-(V2)[2], (V1)[3]-(V2)[3])
-
-#define MAT3_MULT_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
-				(V1)[2]*(V2)[2], (V1)[3]*(V2)[3])
-
-/* ------------------------------  Entries  ------------------------------- */
-
-
-/* In MAT3geom.c */
-void 		MAT3direction_matrix (MAT3mat result_mat, MAT3mat mat);
-int 		MAT3normal_matrix (MAT3mat result_mat, MAT3mat mat);
-void		MAT3rotate (MAT3mat result_mat, MAT3vec axis, double angle_in_radians);
-void		MAT3translate (MAT3mat result_mat, MAT3vec trans);
-void		MAT3scale (MAT3mat result_mat, MAT3vec scale);
-void		MAT3shear(MAT3mat result_mat, double xshear, double yshear);
-
-/* In MAT3mat.c */
-void		MAT3identity(MAT3mat);
-void		MAT3zero(MAT3mat);
-void		MAT3copy (MAT3mat to, MAT3mat from);
-void		MAT3mult (MAT3mat result, MAT3mat, MAT3mat);
-void		MAT3transpose (MAT3mat result, MAT3mat);
-int			MAT3invert (MAT3mat result, MAT3mat);
-void		MAT3print (MAT3mat, FILE *fp);
-void		MAT3print_formatted (MAT3mat, FILE *fp, 
-			 	     char *title, char *head, char *format, char *tail);
-extern int		MAT3equal( void );
-extern double		MAT3trace( void );
-extern int		MAT3power( void );
-extern int		MAT3column_reduce( void );
-extern int		MAT3kernel_basis( void );
-
-/* In MAT3vec.c */
-void		MAT3mult_vec(MAT3vec result_vec, MAT3vec vec, MAT3mat mat);
-int		MAT3mult_hvec (MAT3hvec result_vec, MAT3hvec vec, MAT3mat mat, int normalize);
-void		MAT3cross_product(MAT3vec result,MAT3vec,MAT3vec);
-void		MAT3perp_vec(MAT3vec result_vec, MAT3vec vec, int is_unit);
-
-#endif /* MAT3_HAS_BEEN_INCLUDED */
-
diff --git a/FixObj/obj.c b/FixObj/obj.c
index 9fec7f7e6..018569439 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -29,7 +29,7 @@
 
 #include "obj.h"
 
-#include "mat3.h"
+#include <Math/mat3.h>
 
 
 /* what do ya' know, here's some global variables */
@@ -291,9 +291,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.8  1998/04/08 23:19:37  curt
-/* Adopted Gnu automake/autoconf system.
+/* Revision 1.9  1998/04/18 04:01:03  curt
+/* Now use libMath rather than having local copies of math routines.
 /*
+ * Revision 1.8  1998/04/08 23:19:37  curt
+ * Adopted Gnu automake/autoconf system.
+ *
  * Revision 1.7  1998/03/19 02:51:41  curt
  * Added special case handling to compensate for bugs in our beloved tri striper
  *
diff --git a/SplitTris/MAT3vec.c b/SplitTris/MAT3vec.c
deleted file mode 100644
index a971ebe10..000000000
--- a/SplitTris/MAT3vec.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
-
-/* --------------------------------------------------------------------------
- * This file contains routines that operate on matrices and vectors, or
- * vectors and vectors.
- * -------------------------------------------------------------------------*/
-
-/* #include "sphigslocal.h" */
-
-/* --------------------------  Static Routines	---------------------------- */
-
-/* -------------------------  Internal Routines  --------------------------- */
-
-/* --------------------------  Public Routines	---------------------------- */
-
-/*
- * Multiplies a vector by a matrix, setting the result vector.
- * It assumes all homogeneous coordinates are 1.
- * The two vectors involved may be the same.
- */
-
-#include "mat3.h"
-
-#ifndef TRUE
-#  define TRUE 1
-#endif
-
-#ifndef FALSE
-#  define FALSE 0
-#endif
-
-
-void
-MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
-{
-   MAT3vec		tempvec;
-   register double	*temp = tempvec;
-
-   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
-		vec[2] * mat[2][0] +	      mat[3][0];
-   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
-		vec[2] * mat[2][1] +	      mat[3][1];
-   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
-		vec[2] * mat[2][2] +	      mat[3][2];
-
-   MAT3_COPY_VEC(result_vec, temp);
-}
-
-/*
- * Multiplies a vector of size 4 by a matrix, setting the result vector.
- * The fourth element of the vector is the homogeneous coordinate, which
- * may or may not be 1.  If the "normalize" parameter is TRUE, then the
- * result vector will be normalized so that the homogeneous coordinate is 1.
- * The two vectors involved may be the same.
- * This returns zero if the vector was to be normalized, but couldn't be.
- */
-
-int
-MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
-{
-   MAT3hvec             tempvec;
-   double		norm_fac;
-   register double	*temp = tempvec;
-   register int 	ret = TRUE;
-
-   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
-		vec[2] * mat[2][0] + vec[3] * mat[3][0];
-   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
-		vec[2] * mat[2][1] + vec[3] * mat[3][1];
-   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
-		vec[2] * mat[2][2] + vec[3] * mat[3][2];
-   temp[3] =	vec[0] * mat[0][3] + vec[1] * mat[1][3] +
-		vec[2] * mat[2][3] + vec[3] * mat[3][3];
-
-   /* Normalize if asked for, possible, and necessary */
-   if (normalize) {
-      if (MAT3_IS_ZERO(temp[3])) {
-#ifndef THINK_C
-	 fprintf (stderr,
-		  "Can't normalize vector: homogeneous coordinate is 0");
-#endif
-	 ret = FALSE;
-      }
-      else {
-	 norm_fac = 1.0 / temp[3];
-	 MAT3_SCALE_VEC(result_vec, temp, norm_fac);
-	 result_vec[3] = 1.0;
-      }
-   }
-   else MAT3_COPY_HVEC(result_vec, temp);
-
-   return(ret);
-}
-
-/*
- * Sets the first vector to be the cross-product of the last two vectors.
- */
-
-void
-MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
-{
-   MAT3vec		tempvec;
-   register double	*temp = tempvec;
-
-   temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
-   temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
-   temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
-
-   MAT3_COPY_VEC(result_vec, temp);
-}
-
-/*
- * Finds a vector perpendicular to vec and stores it in result_vec.
- * Method:  take any vector (we use <0,1,0>) and subtract the
- * portion of it pointing in the vec direction.  This doesn't
- * work if vec IS <0,1,0> or is very near it.  So if this is
- * the case, use <0,0,1> instead.
- * If "is_unit" is TRUE, the given vector is assumed to be unit length.
- */
-
-#define SELECT	.7071	/* selection constant (roughly .5*sqrt(2) */
-
-void
-MAT3perp_vec(double *result_vec, double *vec, int is_unit)
-{
-   MAT3vec	norm;
-   double	dot;
-
-   MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
-
-   MAT3_COPY_VEC(norm, vec);
-
-   if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
-
-   /* See if vector is too close to <0,1,0>.  If so, use <0,0,1> */
-   if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
-      result_vec[1] = 0.0;
-      result_vec[2] = 1.0;
-      dot = MAT3_DOT_PRODUCT(norm, result_vec);
-   }
-
-   /* Subtract off non-perpendicular part */
-   result_vec[0] -= dot * norm[0];
-   result_vec[1] -= dot * norm[1];
-   result_vec[2] -= dot * norm[2];
-
-   /* Make result unit length */
-   MAT3_NORMALIZE_VEC(result_vec, dot);
-}
diff --git a/SplitTris/Makefile.am b/SplitTris/Makefile.am
index aeac1186e..d17e02df2 100644
--- a/SplitTris/Makefile.am
+++ b/SplitTris/Makefile.am
@@ -26,21 +26,20 @@
 
 bin_PROGRAMS = splittris
 
-splittris_SOURCES = \
-	MAT3vec.c \
-	fg_geodesy.c fg_geodesy.h \
-	mat3.h \
-	polar.c polar.h \
-	splittris.c splittris.h
+splittris_SOURCES = splittris.c splittris.h
 
 splittris_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la \
+	$(top_builddir)/Lib/Math/libMath.la
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/04/18 04:01:17  curt
+# Now use libMath rather than having local copies of math routines.
+#
 # Revision 1.2  1998/04/14 02:26:06  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index b72e5c752..1282f517e 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -98,15 +98,11 @@ VERSION = @VERSION@
 
 bin_PROGRAMS = splittris
 
-splittris_SOURCES = \
-	MAT3vec.c \
-	fg_geodesy.c fg_geodesy.h \
-	mat3.h \
-	polar.c polar.h \
-	splittris.c splittris.h
+splittris_SOURCES = splittris.c splittris.h
 
 splittris_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la \
+	$(top_builddir)/Lib/Math/libMath.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
@@ -121,8 +117,9 @@ X_CFLAGS = @X_CFLAGS@
 X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
-splittris_OBJECTS =  MAT3vec.o fg_geodesy.o polar.o splittris.o
-splittris_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
+splittris_OBJECTS =  splittris.o
+splittris_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la \
+$(top_builddir)/Lib/Math/libMath.la
 splittris_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -135,8 +132,7 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 TAR = tar
 GZIP = --best
-DEP_FILES =  .deps/MAT3vec.P .deps/fg_geodesy.P .deps/polar.P \
-.deps/splittris.P
+DEP_FILES =  .deps/splittris.P
 SOURCES = $(splittris_SOURCES)
 OBJECTS = $(splittris_OBJECTS)
 
@@ -350,7 +346,10 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.2  1998/04/14 02:26:07  curt
+# Revision 1.3  1998/04/18 04:01:17  curt
+# Now use libMath rather than having local copies of math routines.
+#
+# Revision 1.2  1998/04/14 02:26:06  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
 # Revision 1.1  1998/04/08 23:21:10  curt
diff --git a/SplitTris/fg_geodesy.c b/SplitTris/fg_geodesy.c
deleted file mode 100644
index 773010375..000000000
--- a/SplitTris/fg_geodesy.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/**************************************************************************
- * fg_geodesy.c -- routines to convert between geodetic and geocentric 
- *                 coordinate systems.
- *
- * Copied and adapted directly from LaRCsim/ls_geodesy.c
- *
- * See below for the complete original LaRCsim comments.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#include <math.h>
-
-#include <Include/fg_constants.h>
-
-#include "fg_geodesy.h"
-
-
-/* ONE_SECOND is pi/180/60/60, or about 100 feet at earths' equator */
-#define ONE_SECOND 4.848136811E-6
-
-
-/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
- *     INPUTS:	
- *         lat_geoc	Geocentric latitude, radians, + = North
- *         radius	C.G. radius to earth center, ft
- *
- *     OUTPUTS:
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *         sea_level_r	radius from earth center to sea level at
- *                      local vertical (surface normal) of C.G.
- */
-
-void fgGeocToGeod( double lat_geoc, double radius, double
-		   *lat_geod, double *alt, double *sea_level_r )
-{
-    double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
-    double sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
-
-    if( ( (FG_PI_2 - lat_geoc) < ONE_SECOND )     /* near North pole */
-	|| ( (FG_PI_2 + lat_geoc) < ONE_SECOND ) )   /* near South pole */
-    {
-	*lat_geod = lat_geoc;
-	*sea_level_r = EQUATORIAL_RADIUS_KM*E;
-	*alt = radius - *sea_level_r;
-    } else {
-	t_lat = tan(lat_geoc);
-	x_alpha = E*EQUATORIAL_RADIUS_KM/sqrt(t_lat*t_lat + E*E);
-	mu_alpha = atan2(sqrt(RESQ_KM - x_alpha*x_alpha),E*x_alpha);
-	if (lat_geoc < 0) mu_alpha = - mu_alpha;
-	sin_mu_a = sin(mu_alpha);
-	delt_lambda = mu_alpha - lat_geoc;
-	r_alpha = x_alpha/cos(lat_geoc);
-	l_point = radius - r_alpha;
-	*alt = l_point*cos(delt_lambda);
-	denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
-	rho_alpha = EQUATORIAL_RADIUS_KM*(1-EPS)/
-	    (denom*denom*denom);
-	delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
-	*lat_geod = mu_alpha - delt_mu;
-	lambda_sl = atan( E*E * tan(*lat_geod) ); /* SL geoc. latitude */
-	sin_lambda_sl = sin( lambda_sl );
-	*sea_level_r = 
-	    sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
-    }
-}
-
-
-/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
- *     INPUTS:	
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *
- *     OUTPUTS:
- *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
- *                      get true distance from earth center.
- *         lat_geoc	Geocentric latitude, radians, + = North
- *
- */
-
-void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
-		      double *lat_geoc )
-{
-    double lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
-    
-    lambda_sl = atan( E*E * tan(lat_geod) ); /* sea level geocentric latitude */
-    sin_lambda_sl = sin( lambda_sl );
-    cos_lambda_sl = cos( lambda_sl );
-    sin_mu = sin(lat_geod);	/* Geodetic (map makers') latitude */
-    cos_mu = cos(lat_geod);
-    *sl_radius = 
-	sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
-    py = *sl_radius*sin_lambda_sl + alt*sin_mu;
-    px = *sl_radius*cos_lambda_sl + alt*cos_mu;
-    *lat_geoc = atan2( py, px );
-}
-
-
-/***************************************************************************
-
-	TITLE:	ls_geodesy
-	
-----------------------------------------------------------------------------
-
-	FUNCTION:	Converts geocentric coordinates to geodetic positions
-
-----------------------------------------------------------------------------
-
-	MODULE STATUS:	developmental
-
-----------------------------------------------------------------------------
-
-	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	DESIGNED BY:	E. B. Jackson
-	
-	CODED BY:	E. B. Jackson
-	
-	MAINTAINED BY:	E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	MODIFICATION HISTORY:
-	
-	DATE	PURPOSE						BY
-	
-	930208	Modified to avoid singularity near polar region.	EBJ
-	930602	Moved backwards calcs here from ls_step.		EBJ
-	931214	Changed erroneous Latitude and Altitude variables to 
-		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
-	940111	Changed header files from old ls_eom.h style to ls_types, 
-		and ls_constants.  Also replaced old DATA type with new
-		SCALAR type.						EBJ
-
-	CURRENT RCS HEADER:
-
-$Header$
-$Log$
-Revision 1.1  1998/04/08 23:21:11  curt
-Adopted Gnu automake/autoconf system.
-
-Revision 1.4  1998/01/27 00:47:59  curt
-Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
-system and commandline/config file processing code.
-
-Revision 1.3  1998/01/19 19:27:12  curt
-Merged in make system changes from Bob Kuehne <rpk@sgi.com>
-This should simplify things tremendously.
-
-Revision 1.2  1997/12/15 23:54:54  curt
-Add xgl wrappers for debugging.
-Generate terrain normals on the fly.
-
-Revision 1.1  1997/07/31 23:13:14  curt
-Initial revision.
-
-Revision 1.1  1997/05/29 00:09:56  curt
-Initial Flight Gear revision.
-
- * Revision 1.5  1994/01/11  18:47:05  bjax
- * Changed include files to use types and constants, not ls_eom.h
- * Also changed DATA type to SCALAR type.
- *
- * Revision 1.4  1993/12/14  21:06:47  bjax
- * Removed global variable references Altitude and Latitude.   EBJ
- *
- * Revision 1.3  1993/06/02  15:03:40  bjax
- * Made new subroutine for calculating geodetic to geocentric; changed name
- * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
- *
-
-----------------------------------------------------------------------------
-
-	REFERENCES:
-
-		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
-			Control and Simulation", Wiley and Sons, 1992.
-			ISBN 0-471-61397-5		      
-
-
-----------------------------------------------------------------------------
-
-	CALLED BY:	ls_aux
-
-----------------------------------------------------------------------------
-
-	CALLS TO:
-
-----------------------------------------------------------------------------
-
-	INPUTS:	
-		lat_geoc	Geocentric latitude, radians, + = North
-		radius		C.G. radius to earth center, ft
-
-----------------------------------------------------------------------------
-
-	OUTPUTS:
-		lat_geod	Geodetic latitude, radians, + = North
-		alt		C.G. altitude above mean sea level, ft
-		sea_level_r	radius from earth center to sea level at
-				local vertical (surface normal) of C.G.
-
---------------------------------------------------------------------------*/
-
-
-/* $Log$
-/* Revision 1.1  1998/04/08 23:21:11  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.4  1998/01/27 00:47:59  curt
- * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
- * system and commandline/config file processing code.
- *
- * Revision 1.3  1998/01/19 19:27:12  curt
- * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
- * This should simplify things tremendously.
- *
- * Revision 1.2  1997/12/15 23:54:54  curt
- * Add xgl wrappers for debugging.
- * Generate terrain normals on the fly.
- *
- * Revision 1.1  1997/07/31 23:13:14  curt
- * Initial revision.
- *
- */
diff --git a/SplitTris/fg_geodesy.h b/SplitTris/fg_geodesy.h
deleted file mode 100644
index a40b22df4..000000000
--- a/SplitTris/fg_geodesy.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/**************************************************************************
- * fg_geodesy.h -- routines to convert between geodetic and geocentric 
- *                 coordinate systems.
- *
- * Copied and adapted directly from LaRCsim/ls_geodesy.c
- *
- * See below for the complete original LaRCsim comments.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#ifndef _FG_GEODESY_H
-#define _FG_GEODESY_H
-
-
-/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
- *     INPUTS:	
- *         lat_geoc	Geocentric latitude, radians, + = North
- *         radius	C.G. radius to earth center, ft
- *
- *     OUTPUTS:
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *         sea_level_r	radius from earth center to sea level at
- *                      local vertical (surface normal) of C.G.
- */
-
-void fgGeocToGeod( double lat_geoc, double radius, double
-		   *lat_geod, double *alt, double *sea_level_r );
-
-/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
- *     INPUTS:	
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *
- *     OUTPUTS:
- *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
- *                      get true distance from earth center.
- *         lat_geoc	Geocentric latitude, radians, + = North
- *
- */
-
-void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
-		   double *lat_geoc );
-
-
-
-/***************************************************************************
-
-	TITLE:	ls_geodesy
-	
-----------------------------------------------------------------------------
-
-	FUNCTION:	Converts geocentric coordinates to geodetic positions
-
-----------------------------------------------------------------------------
-
-	MODULE STATUS:	developmental
-
-----------------------------------------------------------------------------
-
-	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	DESIGNED BY:	E. B. Jackson
-	
-	CODED BY:	E. B. Jackson
-	
-	MAINTAINED BY:	E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	MODIFICATION HISTORY:
-	
-	DATE	PURPOSE						BY
-	
-	930208	Modified to avoid singularity near polar region.	EBJ
-	930602	Moved backwards calcs here from ls_step.		EBJ
-	931214	Changed erroneous Latitude and Altitude variables to 
-		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
-	940111	Changed header files from old ls_eom.h style to ls_types, 
-		and ls_constants.  Also replaced old DATA type with new
-		SCALAR type.						EBJ
-
-	CURRENT RCS HEADER:
-
-$Header$
-$Log$
-Revision 1.1  1998/04/08 23:21:12  curt
-Adopted Gnu automake/autoconf system.
-
-Revision 1.2  1998/01/22 02:59:38  curt
-Changed #ifdef FILE_H to #ifdef _FILE_H
-
-Revision 1.1  1997/07/31 23:13:14  curt
-Initial revision.
-
-Revision 1.1  1997/05/29 00:09:56  curt
-Initial Flight Gear revision.
-
- * Revision 1.5  1994/01/11  18:47:05  bjax
- * Changed include files to use types and constants, not ls_eom.h
- * Also changed DATA type to SCALAR type.
- *
- * Revision 1.4  1993/12/14  21:06:47  bjax
- * Removed global variable references Altitude and Latitude.   EBJ
- *
- * Revision 1.3  1993/06/02  15:03:40  bjax
- * Made new subroutine for calculating geodetic to geocentric; changed name
- * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
- *
-
-----------------------------------------------------------------------------
-
-	REFERENCES:
-
-		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
-			Control and Simulation", Wiley and Sons, 1992.
-			ISBN 0-471-61397-5		      
-
-
-----------------------------------------------------------------------------
-
-	CALLED BY:	ls_aux
-
-----------------------------------------------------------------------------
-
-	CALLS TO:
-
-----------------------------------------------------------------------------
-
-	INPUTS:	
-		lat_geoc	Geocentric latitude, radians, + = North
-		radius		C.G. radius to earth center, ft
-
-----------------------------------------------------------------------------
-
-	OUTPUTS:
-		lat_geod	Geodetic latitude, radians, + = North
-		alt		C.G. altitude above mean sea level, ft
-		sea_level_r	radius from earth center to sea level at
-				local vertical (surface normal) of C.G.
-
---------------------------------------------------------------------------*/
-
-
-#endif /* _FG_GEODESY_H */
-
-
-/* $Log$
-/* Revision 1.1  1998/04/08 23:21:12  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.2  1998/01/22 02:59:38  curt
- * Changed #ifdef FILE_H to #ifdef _FILE_H
- *
- * Revision 1.1  1997/07/31 23:13:14  curt
- * Initial revision.
- *
- */
diff --git a/SplitTris/mat3.h b/SplitTris/mat3.h
deleted file mode 100644
index 58c4b9e07..000000000
--- a/SplitTris/mat3.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
-
-/* -------------------------------------------------------------------------
-		       Public MAT3 include file
-   ------------------------------------------------------------------------- */
-
-#ifndef MAT3_HAS_BEEN_INCLUDED
-#define MAT3_HAS_BEEN_INCLUDED
-
-/* -----------------------------  Constants  ------------------------------ */
-
-/*
- * Make sure the math library .h file is included, in case it wasn't.
- */
-
-#ifndef HUGE
-#include <math.h>
-#endif
-#include <stdio.h>
-
-
-#define MAT3_DET0	-1			/* Indicates singular mat */
-#define MAT3_EPSILON	1e-12			/* Close enough to zero   */
-#define MAT3_PI 	3.141592653589793	/* Pi			  */
-
-/* ------------------------------  Types  --------------------------------- */
-
-typedef double MAT3mat[4][4];		/* 4x4 matrix			 */
-typedef double MAT3vec[3];		/* Vector			 */
-typedef double MAT3hvec[4];             /* Vector with homogeneous coord */
-
-/* ------------------------------  Macros  -------------------------------- */
-
-/* Tests if a number is within EPSILON of zero */
-#define MAT3_IS_ZERO(N) 	((N) < MAT3_EPSILON && (N) > -MAT3_EPSILON)
-
-/* Sets a vector to the three given values */
-#define MAT3_SET_VEC(V,X,Y,Z)	((V)[0]=(X), (V)[1]=(Y), (V)[2]=(Z))
-
-/* Tests a vector for all components close to zero */
-#define MAT3_IS_ZERO_VEC(V)	(MAT3_IS_ZERO((V)[0]) && \
-				 MAT3_IS_ZERO((V)[1]) && \
-				 MAT3_IS_ZERO((V)[2]))
-
-/* Dot product of two vectors */
-#define MAT3_DOT_PRODUCT(V1,V2) \
-			((V1)[0]*(V2)[0] + (V1)[1]*(V2)[1] + (V1)[2]*(V2)[2])
-
-/* Copy one vector to other */
-#define MAT3_COPY_VEC(TO,FROM)	((TO)[0] = (FROM)[0], \
-				 (TO)[1] = (FROM)[1], \
-				 (TO)[2] = (FROM)[2])
-
-/* Normalize vector to unit length, using TEMP as temporary variable.
- * TEMP will be zero if vector has zero length */
-#define MAT3_NORMALIZE_VEC(V,TEMP) \
-	if ((TEMP = sqrt(MAT3_DOT_PRODUCT(V,V))) > MAT3_EPSILON) { \
-	   TEMP = 1.0 / TEMP; \
-	   MAT3_SCALE_VEC(V,V,TEMP); \
-	} else TEMP = 0.0
-
-/* Scale vector by given factor, storing result vector in RESULT_V */
-#define MAT3_SCALE_VEC(RESULT_V,V,SCALE) \
-	MAT3_SET_VEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), (V)[2]*(SCALE))
-
-/* Adds vectors V1 and V2, storing result in RESULT_V */
-#define MAT3_ADD_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
-			       (V1)[2]+(V2)[2])
-
-/* Subtracts vector V2 from V1, storing result in RESULT_V */
-#define MAT3_SUB_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
-			       (V1)[2]-(V2)[2])
-
-/* Multiplies vectors V1 and V2, storing result in RESULT_V */
-#define MAT3_MULT_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
-			       (V1)[2]*(V2)[2])
-
-/* Sets RESULT_V to the linear combination of V1 and V2, scaled by
- * SCALE1 and SCALE2, respectively */
-#define MAT3_LINEAR_COMB(RESULT_V,SCALE1,V1,SCALE2,V2) \
-	MAT3_SET_VEC(RESULT_V,	(SCALE1)*(V1)[0] + (SCALE2)*(V2)[0], \
-				(SCALE1)*(V1)[1] + (SCALE2)*(V2)[1], \
-				(SCALE1)*(V1)[2] + (SCALE2)*(V2)[2])
-
-/* Several of the vector macros are useful for homogeneous-coord vectors */
-#define MAT3_SET_HVEC(V,X,Y,Z,W) ((V)[0]=(X), (V)[1]=(Y), \
-				  (V)[2]=(Z), (V)[3]=(W))
-
-#define MAT3_COPY_HVEC(TO,FROM) ((TO)[0] = (FROM)[0], \
-				 (TO)[1] = (FROM)[1], \
-				 (TO)[2] = (FROM)[2], \
-				 (TO)[3] = (FROM)[3])
-
-#define MAT3_SCALE_HVEC(RESULT_V,V,SCALE) \
-	MAT3_SET_HVEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), \
-				(V)[2]*(SCALE), (V)[3]*(SCALE))
-
-#define MAT3_ADD_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
-				(V1)[2]+(V2)[2], (V1)[3]+(V2)[3])
-
-#define MAT3_SUB_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
-				(V1)[2]-(V2)[2], (V1)[3]-(V2)[3])
-
-#define MAT3_MULT_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
-				(V1)[2]*(V2)[2], (V1)[3]*(V2)[3])
-
-/* ------------------------------  Entries  ------------------------------- */
-
-
-/* In MAT3geom.c */
-void 		MAT3direction_matrix (MAT3mat result_mat, MAT3mat mat);
-int 		MAT3normal_matrix (MAT3mat result_mat, MAT3mat mat);
-void		MAT3rotate (MAT3mat result_mat, MAT3vec axis, double angle_in_radians);
-void		MAT3translate (MAT3mat result_mat, MAT3vec trans);
-void		MAT3scale (MAT3mat result_mat, MAT3vec scale);
-void		MAT3shear(MAT3mat result_mat, double xshear, double yshear);
-
-/* In MAT3mat.c */
-void		MAT3identity(MAT3mat);
-void		MAT3zero(MAT3mat);
-void		MAT3copy (MAT3mat to, MAT3mat from);
-void		MAT3mult (MAT3mat result, MAT3mat, MAT3mat);
-void		MAT3transpose (MAT3mat result, MAT3mat);
-int			MAT3invert (MAT3mat result, MAT3mat);
-void		MAT3print (MAT3mat, FILE *fp);
-void		MAT3print_formatted (MAT3mat, FILE *fp, 
-			 	     char *title, char *head, char *format, char *tail);
-extern int		MAT3equal( void );
-extern double		MAT3trace( void );
-extern int		MAT3power( void );
-extern int		MAT3column_reduce( void );
-extern int		MAT3kernel_basis( void );
-
-/* In MAT3vec.c */
-void		MAT3mult_vec(MAT3vec result_vec, MAT3vec vec, MAT3mat mat);
-int		MAT3mult_hvec (MAT3hvec result_vec, MAT3hvec vec, MAT3mat mat, int normalize);
-void		MAT3cross_product(MAT3vec result,MAT3vec,MAT3vec);
-void		MAT3perp_vec(MAT3vec result_vec, MAT3vec vec, int is_unit);
-
-#endif /* MAT3_HAS_BEEN_INCLUDED */
-
diff --git a/SplitTris/polar.c b/SplitTris/polar.c
deleted file mode 100644
index e67881971..000000000
--- a/SplitTris/polar.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/**************************************************************************
- * polar.c -- routines to deal with polar math and transformations
- *
- * Written by Curtis Olson, started June 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#include <math.h>
-#include <stdio.h>
-
-#include <Include/fg_constants.h>
-
-#include "polar.h"
-
-
-/* we can save these values between calls for efficiency */
-static double st, ct, sp, cp;
-
-
-/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
- * must be specified in radians.  The FG convention is for distances
- * to be specified in meters */
-struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius) {
-    struct fgCartesianPoint pnew;
-
-    pnew.x = cos(lon) * cos(lat) * radius;
-    pnew.y = sin(lon) * cos(lat) * radius;
-    pnew.z = sin(lat) * radius;
-
-    return(pnew);
-}
-
-
-/* Precalculate as much as possible so we can do a batch of transforms
- * through the same angles, will rotates a cartesian point about the
- * center of the earth by Theta (longitude axis) and Phi (latitude
- * axis) */
-
-/* Here are the unoptimized transformation equations 
-
-   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
-	     sin(Phi) * z
-   y' = -sin(Theta) * x + cos(Theta) * y
-   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
-	     cos(Phi) * z;
-
- */
-void fgRotateBatchInit(double Theta, double Phi) {
-    printf("Theta = %.3f, Phi = %.3f\n", Theta, Phi);
-
-    st = sin(Theta);
-    ct = cos(Theta);
-    sp = sin(-Phi);
-    cp = cos(-Phi);
-}
-
-/* Rotates a cartesian point about the center of the earth by Theta
- * (longitude axis) and Phi (latitude axis) */
-struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p) {
-    struct fgCartesianPoint p1, p2;
-
-    /* printf("start = %.3f %.3f %.3f\n", p.x, p.y, p.z); */
-
-    /* rotate about the z axis */
-    p1.x = ct * p.x - st * p.y;
-    p1.y = st * p.x + ct * p.y;
-    p1.z = p.z;
-
-    /* printf("step 1 = %.3f %.3f %.3f\n", p1.x, p1.y, p1.z); */
-
-    /* rotate new point about y axis */
-    p2.x = cp * p1.x + sp * p1.z;
-    p2.y = p1.y;
-    p2.z = cp * p1.z - sp * p1.x;
-
-    /* printf("cp = %.5f, sp = %.5f\n", cp, sp); */
-    /* printf("(1) = %.5f, (2) = %.5f\n", cp * p1.z, sp * p1.x); */
-
-    /* printf("step 2 = %.3f %.3f %.3f\n", p2.x, p2.y, p2.z); */
-
-    return(p2);
-}
-
-
-/* $Log$
-/* Revision 1.2  1998/04/14 02:26:07  curt
-/* Code reorganizations.  Added a Lib/ directory for more general libraries.
-/*
- * Revision 1.1  1998/04/08 23:21:12  curt
- * Adopted Gnu automake/autoconf system.
- *
- * Revision 1.5  1998/01/27 00:48:00  curt
- * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
- * system and commandline/config file processing code.
- *
- * Revision 1.4  1998/01/19 19:27:12  curt
- * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
- * This should simplify things tremendously.
- *
- * Revision 1.3  1997/12/15 23:54:54  curt
- * Add xgl wrappers for debugging.
- * Generate terrain normals on the fly.
- *
- * Revision 1.2  1997/07/31 22:52:27  curt
- * Working on redoing internal coordinate systems & scenery transformations.
- *
- * Revision 1.1  1997/07/07 21:02:36  curt
- * Initial revision.
- * */
diff --git a/SplitTris/polar.h b/SplitTris/polar.h
deleted file mode 100644
index 2164d995a..000000000
--- a/SplitTris/polar.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**************************************************************************
- * polar.h -- routines to deal with polar math and transformations
- *
- * Written by Curtis Olson, started June 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#ifndef _POLAR_H
-#define _POLAR_H
-
-
-#include <Include/fg_types.h>
-
-
-/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
- * must be specified in radians.  The FG convention is for distances
- * to be specified in meters */
-struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius);
-
-
-/* Precalculate as much as possible so we can do a batch of transforms
- * through the same angles, will rotates a cartesian point about the
- * center of the earth by Theta (longitude axis) and Phi (latitude
- * axis) */
-
-/* Here are the unoptimized transformation equations 
-
-   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
-	     sin(Phi) * z
-   y' = -sin(Theta) * x + cos(Theta) * y
-   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
-	     cos(Phi) * z;
-
- */
-void fgRotateBatchInit(double Theta, double Phi);
-
-
-/* Rotates a cartesian point about the center of the earth by Theta
- * (longitude axis) and Phi (latitude axis) */
-struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p);
-
-
-#endif /* _POLAR_H */
-
-
-/* $Log$
-/* Revision 1.1  1998/04/08 23:21:13  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.7  1998/01/27 00:48:00  curt
- * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
- * system and commandline/config file processing code.
- *
- * Revision 1.6  1998/01/22 02:59:39  curt
- * Changed #ifdef FILE_H to #ifdef _FILE_H
- *
- * Revision 1.5  1998/01/19 19:27:13  curt
- * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
- * This should simplify things tremendously.
- *
- * Revision 1.4  1997/12/15 23:54:55  curt
- * Add xgl wrappers for debugging.
- * Generate terrain normals on the fly.
- *
- * Revision 1.3  1997/07/31 22:52:28  curt
- * Working on redoing internal coordinate systems & scenery transformations.
- *
- * Revision 1.2  1997/07/23 21:52:21  curt
- * Put comments around the text after an #endif for increased portability.
- *
- * Revision 1.1  1997/07/07 21:02:37  curt
- * Initial revision.
- *
- */
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index e346285e4..c855c7525 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -38,9 +38,9 @@
 #include <Include/fg_types.h>
 #include <Bucket/bucketutils.h>
 
-#include "fg_geodesy.h"
-#include "mat3.h"
-#include "polar.h"
+#include <Math/fg_geodesy.h>
+#include <Math/mat3.h>
+#include <Math/polar.h>
 
 int nodecount, tricount;
 double xmin, xmax, ymin, ymax;
@@ -612,9 +612,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.8  1998/04/14 02:26:08  curt
-/* Code reorganizations.  Added a Lib/ directory for more general libraries.
+/* Revision 1.9  1998/04/18 04:01:20  curt
+/* Now use libMath rather than having local copies of math routines.
 /*
+ * Revision 1.8  1998/04/14 02:26:08  curt
+ * Code reorganizations.  Added a Lib/ directory for more general libraries.
+ *
  * Revision 1.7  1998/04/08 23:21:13  curt
  * Adopted Gnu automake/autoconf system.
  *
diff --git a/Tri2obj/MAT3vec.c b/Tri2obj/MAT3vec.c
deleted file mode 100644
index a971ebe10..000000000
--- a/Tri2obj/MAT3vec.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
-
-/* --------------------------------------------------------------------------
- * This file contains routines that operate on matrices and vectors, or
- * vectors and vectors.
- * -------------------------------------------------------------------------*/
-
-/* #include "sphigslocal.h" */
-
-/* --------------------------  Static Routines	---------------------------- */
-
-/* -------------------------  Internal Routines  --------------------------- */
-
-/* --------------------------  Public Routines	---------------------------- */
-
-/*
- * Multiplies a vector by a matrix, setting the result vector.
- * It assumes all homogeneous coordinates are 1.
- * The two vectors involved may be the same.
- */
-
-#include "mat3.h"
-
-#ifndef TRUE
-#  define TRUE 1
-#endif
-
-#ifndef FALSE
-#  define FALSE 0
-#endif
-
-
-void
-MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
-{
-   MAT3vec		tempvec;
-   register double	*temp = tempvec;
-
-   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
-		vec[2] * mat[2][0] +	      mat[3][0];
-   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
-		vec[2] * mat[2][1] +	      mat[3][1];
-   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
-		vec[2] * mat[2][2] +	      mat[3][2];
-
-   MAT3_COPY_VEC(result_vec, temp);
-}
-
-/*
- * Multiplies a vector of size 4 by a matrix, setting the result vector.
- * The fourth element of the vector is the homogeneous coordinate, which
- * may or may not be 1.  If the "normalize" parameter is TRUE, then the
- * result vector will be normalized so that the homogeneous coordinate is 1.
- * The two vectors involved may be the same.
- * This returns zero if the vector was to be normalized, but couldn't be.
- */
-
-int
-MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
-{
-   MAT3hvec             tempvec;
-   double		norm_fac;
-   register double	*temp = tempvec;
-   register int 	ret = TRUE;
-
-   temp[0] =	vec[0] * mat[0][0] + vec[1] * mat[1][0] +
-		vec[2] * mat[2][0] + vec[3] * mat[3][0];
-   temp[1] =	vec[0] * mat[0][1] + vec[1] * mat[1][1] +
-		vec[2] * mat[2][1] + vec[3] * mat[3][1];
-   temp[2] =	vec[0] * mat[0][2] + vec[1] * mat[1][2] +
-		vec[2] * mat[2][2] + vec[3] * mat[3][2];
-   temp[3] =	vec[0] * mat[0][3] + vec[1] * mat[1][3] +
-		vec[2] * mat[2][3] + vec[3] * mat[3][3];
-
-   /* Normalize if asked for, possible, and necessary */
-   if (normalize) {
-      if (MAT3_IS_ZERO(temp[3])) {
-#ifndef THINK_C
-	 fprintf (stderr,
-		  "Can't normalize vector: homogeneous coordinate is 0");
-#endif
-	 ret = FALSE;
-      }
-      else {
-	 norm_fac = 1.0 / temp[3];
-	 MAT3_SCALE_VEC(result_vec, temp, norm_fac);
-	 result_vec[3] = 1.0;
-      }
-   }
-   else MAT3_COPY_HVEC(result_vec, temp);
-
-   return(ret);
-}
-
-/*
- * Sets the first vector to be the cross-product of the last two vectors.
- */
-
-void
-MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
-{
-   MAT3vec		tempvec;
-   register double	*temp = tempvec;
-
-   temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
-   temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
-   temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
-
-   MAT3_COPY_VEC(result_vec, temp);
-}
-
-/*
- * Finds a vector perpendicular to vec and stores it in result_vec.
- * Method:  take any vector (we use <0,1,0>) and subtract the
- * portion of it pointing in the vec direction.  This doesn't
- * work if vec IS <0,1,0> or is very near it.  So if this is
- * the case, use <0,0,1> instead.
- * If "is_unit" is TRUE, the given vector is assumed to be unit length.
- */
-
-#define SELECT	.7071	/* selection constant (roughly .5*sqrt(2) */
-
-void
-MAT3perp_vec(double *result_vec, double *vec, int is_unit)
-{
-   MAT3vec	norm;
-   double	dot;
-
-   MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
-
-   MAT3_COPY_VEC(norm, vec);
-
-   if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
-
-   /* See if vector is too close to <0,1,0>.  If so, use <0,0,1> */
-   if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
-      result_vec[1] = 0.0;
-      result_vec[2] = 1.0;
-      dot = MAT3_DOT_PRODUCT(norm, result_vec);
-   }
-
-   /* Subtract off non-perpendicular part */
-   result_vec[0] -= dot * norm[0];
-   result_vec[1] -= dot * norm[1];
-   result_vec[2] -= dot * norm[2];
-
-   /* Make result unit length */
-   MAT3_NORMALIZE_VEC(result_vec, dot);
-}
diff --git a/Tri2obj/Makefile.am b/Tri2obj/Makefile.am
index 13bece460..0bf71d497 100644
--- a/Tri2obj/Makefile.am
+++ b/Tri2obj/Makefile.am
@@ -26,21 +26,20 @@
 
 bin_PROGRAMS = tri2obj
 
-tri2obj_SOURCES = \
-	tri2obj.c tri2obj.h \
-	MAT3vec.c \
-	fg_geodesy.c fg_geodesy.h \
-	mat3.h \
-	polar.c polar.h
+tri2obj_SOURCES = tri2obj.c tri2obj.h
 
 tri2obj_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la \
+	$(top_builddir)/Lib/Math/libMath.la
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/04/18 04:01:29  curt
+# Now use libMath rather than having local copies of math routines.
+#
 # Revision 1.2  1998/04/14 02:26:09  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index e344583f9..9a947ad24 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -98,15 +98,11 @@ VERSION = @VERSION@
 
 bin_PROGRAMS = tri2obj
 
-tri2obj_SOURCES = \
-	tri2obj.c tri2obj.h \
-	MAT3vec.c \
-	fg_geodesy.c fg_geodesy.h \
-	mat3.h \
-	polar.c polar.h
+tri2obj_SOURCES = tri2obj.c tri2obj.h
 
 tri2obj_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.la \
+	$(top_builddir)/Lib/Math/libMath.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
@@ -121,8 +117,9 @@ X_CFLAGS = @X_CFLAGS@
 X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
-tri2obj_OBJECTS =  tri2obj.o MAT3vec.o fg_geodesy.o polar.o
-tri2obj_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
+tri2obj_OBJECTS =  tri2obj.o
+tri2obj_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la \
+$(top_builddir)/Lib/Math/libMath.la
 tri2obj_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -135,8 +132,7 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 TAR = tar
 GZIP = --best
-DEP_FILES =  .deps/MAT3vec.P .deps/fg_geodesy.P .deps/polar.P \
-.deps/tri2obj.P
+DEP_FILES =  .deps/tri2obj.P
 SOURCES = $(tri2obj_SOURCES)
 OBJECTS = $(tri2obj_OBJECTS)
 
@@ -350,7 +346,10 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.2  1998/04/14 02:26:10  curt
+# Revision 1.3  1998/04/18 04:01:29  curt
+# Now use libMath rather than having local copies of math routines.
+#
+# Revision 1.2  1998/04/14 02:26:09  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
 # Revision 1.1  1998/04/08 23:22:13  curt
diff --git a/Tri2obj/fg_geodesy.c b/Tri2obj/fg_geodesy.c
deleted file mode 100644
index bedd202b4..000000000
--- a/Tri2obj/fg_geodesy.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/**************************************************************************
- * fg_geodesy.c -- routines to convert between geodetic and geocentric 
- *                 coordinate systems.
- *
- * Copied and adapted directly from LaRCsim/ls_geodesy.c
- *
- * See below for the complete original LaRCsim comments.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#include <math.h>
-
-#include <Include/fg_constants.h>
-
-#include "fg_geodesy.h"
-
-
-/* ONE_SECOND is pi/180/60/60, or about 100 feet at earths' equator */
-#define ONE_SECOND 4.848136811E-6
-
-
-/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
- *     INPUTS:	
- *         lat_geoc	Geocentric latitude, radians, + = North
- *         radius	C.G. radius to earth center, ft
- *
- *     OUTPUTS:
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *         sea_level_r	radius from earth center to sea level at
- *                      local vertical (surface normal) of C.G.
- */
-
-void fgGeocToGeod( double lat_geoc, double radius, double
-		   *lat_geod, double *alt, double *sea_level_r )
-{
-    double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
-    double sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
-
-    if( ( (FG_PI_2 - lat_geoc) < ONE_SECOND )     /* near North pole */
-	|| ( (FG_PI_2 + lat_geoc) < ONE_SECOND ) )   /* near South pole */
-    {
-	*lat_geod = lat_geoc;
-	*sea_level_r = EQUATORIAL_RADIUS_KM*E;
-	*alt = radius - *sea_level_r;
-    } else {
-	t_lat = tan(lat_geoc);
-	x_alpha = E*EQUATORIAL_RADIUS_KM/sqrt(t_lat*t_lat + E*E);
-	mu_alpha = atan2(sqrt(RESQ_KM - x_alpha*x_alpha),E*x_alpha);
-	if (lat_geoc < 0) mu_alpha = - mu_alpha;
-	sin_mu_a = sin(mu_alpha);
-	delt_lambda = mu_alpha - lat_geoc;
-	r_alpha = x_alpha/cos(lat_geoc);
-	l_point = radius - r_alpha;
-	*alt = l_point*cos(delt_lambda);
-	denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
-	rho_alpha = EQUATORIAL_RADIUS_KM*(1-EPS)/
-	    (denom*denom*denom);
-	delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
-	*lat_geod = mu_alpha - delt_mu;
-	lambda_sl = atan( E*E * tan(*lat_geod) ); /* SL geoc. latitude */
-	sin_lambda_sl = sin( lambda_sl );
-	*sea_level_r = 
-	    sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
-    }
-}
-
-
-/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
- *     INPUTS:	
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *
- *     OUTPUTS:
- *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
- *                      get true distance from earth center.
- *         lat_geoc	Geocentric latitude, radians, + = North
- *
- */
-
-void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
-		      double *lat_geoc )
-{
-    double lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
-    
-    lambda_sl = atan( E*E * tan(lat_geod) ); /* sea level geocentric latitude */
-    sin_lambda_sl = sin( lambda_sl );
-    cos_lambda_sl = cos( lambda_sl );
-    sin_mu = sin(lat_geod);	/* Geodetic (map makers') latitude */
-    cos_mu = cos(lat_geod);
-    *sl_radius = 
-	sqrt(RESQ_KM / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
-    py = *sl_radius*sin_lambda_sl + alt*sin_mu;
-    px = *sl_radius*cos_lambda_sl + alt*cos_mu;
-    *lat_geoc = atan2( py, px );
-}
-
-
-/***************************************************************************
-
-	TITLE:	ls_geodesy
-	
-----------------------------------------------------------------------------
-
-	FUNCTION:	Converts geocentric coordinates to geodetic positions
-
-----------------------------------------------------------------------------
-
-	MODULE STATUS:	developmental
-
-----------------------------------------------------------------------------
-
-	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	DESIGNED BY:	E. B. Jackson
-	
-	CODED BY:	E. B. Jackson
-	
-	MAINTAINED BY:	E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	MODIFICATION HISTORY:
-	
-	DATE	PURPOSE						BY
-	
-	930208	Modified to avoid singularity near polar region.	EBJ
-	930602	Moved backwards calcs here from ls_step.		EBJ
-	931214	Changed erroneous Latitude and Altitude variables to 
-		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
-	940111	Changed header files from old ls_eom.h style to ls_types, 
-		and ls_constants.  Also replaced old DATA type with new
-		SCALAR type.						EBJ
-
-	CURRENT RCS HEADER:
-
-$Header$
-$Log$
-Revision 1.1  1998/04/08 23:22:14  curt
-Adopted Gnu automake/autoconf system.
-
-Revision 1.4  1998/01/27 00:47:59  curt
-Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
-system and commandline/config file processing code.
-
-Revision 1.3  1998/01/19 19:27:12  curt
-Merged in make system changes from Bob Kuehne <rpk@sgi.com>
-This should simplify things tremendously.
-
-Revision 1.2  1997/12/15 23:54:54  curt
-Add xgl wrappers for debugging.
-Generate terrain normals on the fly.
-
-Revision 1.1  1997/07/31 23:13:14  curt
-Initial revision.
-
-Revision 1.1  1997/05/29 00:09:56  curt
-Initial Flight Gear revision.
-
- * Revision 1.5  1994/01/11  18:47:05  bjax
- * Changed include files to use types and constants, not ls_eom.h
- * Also changed DATA type to SCALAR type.
- *
- * Revision 1.4  1993/12/14  21:06:47  bjax
- * Removed global variable references Altitude and Latitude.   EBJ
- *
- * Revision 1.3  1993/06/02  15:03:40  bjax
- * Made new subroutine for calculating geodetic to geocentric; changed name
- * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
- *
-
-----------------------------------------------------------------------------
-
-	REFERENCES:
-
-		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
-			Control and Simulation", Wiley and Sons, 1992.
-			ISBN 0-471-61397-5		      
-
-
-----------------------------------------------------------------------------
-
-	CALLED BY:	ls_aux
-
-----------------------------------------------------------------------------
-
-	CALLS TO:
-
-----------------------------------------------------------------------------
-
-	INPUTS:	
-		lat_geoc	Geocentric latitude, radians, + = North
-		radius		C.G. radius to earth center, ft
-
-----------------------------------------------------------------------------
-
-	OUTPUTS:
-		lat_geod	Geodetic latitude, radians, + = North
-		alt		C.G. altitude above mean sea level, ft
-		sea_level_r	radius from earth center to sea level at
-				local vertical (surface normal) of C.G.
-
---------------------------------------------------------------------------*/
-
-
-/* $Log$
-/* Revision 1.1  1998/04/08 23:22:14  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.4  1998/01/27 00:47:59  curt
- * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
- * system and commandline/config file processing code.
- *
- * Revision 1.3  1998/01/19 19:27:12  curt
- * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
- * This should simplify things tremendously.
- *
- * Revision 1.2  1997/12/15 23:54:54  curt
- * Add xgl wrappers for debugging.
- * Generate terrain normals on the fly.
- *
- * Revision 1.1  1997/07/31 23:13:14  curt
- * Initial revision.
- *
- */
diff --git a/Tri2obj/fg_geodesy.h b/Tri2obj/fg_geodesy.h
deleted file mode 100644
index 22a030ffb..000000000
--- a/Tri2obj/fg_geodesy.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/**************************************************************************
- * fg_geodesy.h -- routines to convert between geodetic and geocentric 
- *                 coordinate systems.
- *
- * Copied and adapted directly from LaRCsim/ls_geodesy.c
- *
- * See below for the complete original LaRCsim comments.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#ifndef _FG_GEODESY_H
-#define _FG_GEODESY_H
-
-
-/* fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
- *     INPUTS:	
- *         lat_geoc	Geocentric latitude, radians, + = North
- *         radius	C.G. radius to earth center, ft
- *
- *     OUTPUTS:
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *         sea_level_r	radius from earth center to sea level at
- *                      local vertical (surface normal) of C.G.
- */
-
-void fgGeocToGeod( double lat_geoc, double radius, double
-		   *lat_geod, double *alt, double *sea_level_r );
-
-/* fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
- *     INPUTS:	
- *         lat_geod	Geodetic latitude, radians, + = North
- *         alt		C.G. altitude above mean sea level, ft
- *
- *     OUTPUTS:
- *         sl_radius	SEA LEVEL radius to earth center, ft (add Altitude to
- *                      get true distance from earth center.
- *         lat_geoc	Geocentric latitude, radians, + = North
- *
- */
-
-void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
-		   double *lat_geoc );
-
-
-
-/***************************************************************************
-
-	TITLE:	ls_geodesy
-	
-----------------------------------------------------------------------------
-
-	FUNCTION:	Converts geocentric coordinates to geodetic positions
-
-----------------------------------------------------------------------------
-
-	MODULE STATUS:	developmental
-
-----------------------------------------------------------------------------
-
-	GENEALOGY:	Written as part of LaRCSim project by E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	DESIGNED BY:	E. B. Jackson
-	
-	CODED BY:	E. B. Jackson
-	
-	MAINTAINED BY:	E. B. Jackson
-
-----------------------------------------------------------------------------
-
-	MODIFICATION HISTORY:
-	
-	DATE	PURPOSE						BY
-	
-	930208	Modified to avoid singularity near polar region.	EBJ
-	930602	Moved backwards calcs here from ls_step.		EBJ
-	931214	Changed erroneous Latitude and Altitude variables to 
-		*lat_geod and *alt in routine ls_geoc_to_geod.		EBJ
-	940111	Changed header files from old ls_eom.h style to ls_types, 
-		and ls_constants.  Also replaced old DATA type with new
-		SCALAR type.						EBJ
-
-	CURRENT RCS HEADER:
-
-$Header$
-$Log$
-Revision 1.1  1998/04/08 23:22:15  curt
-Adopted Gnu automake/autoconf system.
-
-Revision 1.2  1998/01/22 02:59:38  curt
-Changed #ifdef FILE_H to #ifdef _FILE_H
-
-Revision 1.1  1997/07/31 23:13:14  curt
-Initial revision.
-
-Revision 1.1  1997/05/29 00:09:56  curt
-Initial Flight Gear revision.
-
- * Revision 1.5  1994/01/11  18:47:05  bjax
- * Changed include files to use types and constants, not ls_eom.h
- * Also changed DATA type to SCALAR type.
- *
- * Revision 1.4  1993/12/14  21:06:47  bjax
- * Removed global variable references Altitude and Latitude.   EBJ
- *
- * Revision 1.3  1993/06/02  15:03:40  bjax
- * Made new subroutine for calculating geodetic to geocentric; changed name
- * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
- *
-
-----------------------------------------------------------------------------
-
-	REFERENCES:
-
-		[ 1]	Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
-			Control and Simulation", Wiley and Sons, 1992.
-			ISBN 0-471-61397-5		      
-
-
-----------------------------------------------------------------------------
-
-	CALLED BY:	ls_aux
-
-----------------------------------------------------------------------------
-
-	CALLS TO:
-
-----------------------------------------------------------------------------
-
-	INPUTS:	
-		lat_geoc	Geocentric latitude, radians, + = North
-		radius		C.G. radius to earth center, ft
-
-----------------------------------------------------------------------------
-
-	OUTPUTS:
-		lat_geod	Geodetic latitude, radians, + = North
-		alt		C.G. altitude above mean sea level, ft
-		sea_level_r	radius from earth center to sea level at
-				local vertical (surface normal) of C.G.
-
---------------------------------------------------------------------------*/
-
-
-#endif /* _FG_GEODESY_H */
-
-
-/* $Log$
-/* Revision 1.1  1998/04/08 23:22:15  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.2  1998/01/22 02:59:38  curt
- * Changed #ifdef FILE_H to #ifdef _FILE_H
- *
- * Revision 1.1  1997/07/31 23:13:14  curt
- * Initial revision.
- *
- */
diff --git a/Tri2obj/mat3.h b/Tri2obj/mat3.h
deleted file mode 100644
index 58c4b9e07..000000000
--- a/Tri2obj/mat3.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
-
-/* -------------------------------------------------------------------------
-		       Public MAT3 include file
-   ------------------------------------------------------------------------- */
-
-#ifndef MAT3_HAS_BEEN_INCLUDED
-#define MAT3_HAS_BEEN_INCLUDED
-
-/* -----------------------------  Constants  ------------------------------ */
-
-/*
- * Make sure the math library .h file is included, in case it wasn't.
- */
-
-#ifndef HUGE
-#include <math.h>
-#endif
-#include <stdio.h>
-
-
-#define MAT3_DET0	-1			/* Indicates singular mat */
-#define MAT3_EPSILON	1e-12			/* Close enough to zero   */
-#define MAT3_PI 	3.141592653589793	/* Pi			  */
-
-/* ------------------------------  Types  --------------------------------- */
-
-typedef double MAT3mat[4][4];		/* 4x4 matrix			 */
-typedef double MAT3vec[3];		/* Vector			 */
-typedef double MAT3hvec[4];             /* Vector with homogeneous coord */
-
-/* ------------------------------  Macros  -------------------------------- */
-
-/* Tests if a number is within EPSILON of zero */
-#define MAT3_IS_ZERO(N) 	((N) < MAT3_EPSILON && (N) > -MAT3_EPSILON)
-
-/* Sets a vector to the three given values */
-#define MAT3_SET_VEC(V,X,Y,Z)	((V)[0]=(X), (V)[1]=(Y), (V)[2]=(Z))
-
-/* Tests a vector for all components close to zero */
-#define MAT3_IS_ZERO_VEC(V)	(MAT3_IS_ZERO((V)[0]) && \
-				 MAT3_IS_ZERO((V)[1]) && \
-				 MAT3_IS_ZERO((V)[2]))
-
-/* Dot product of two vectors */
-#define MAT3_DOT_PRODUCT(V1,V2) \
-			((V1)[0]*(V2)[0] + (V1)[1]*(V2)[1] + (V1)[2]*(V2)[2])
-
-/* Copy one vector to other */
-#define MAT3_COPY_VEC(TO,FROM)	((TO)[0] = (FROM)[0], \
-				 (TO)[1] = (FROM)[1], \
-				 (TO)[2] = (FROM)[2])
-
-/* Normalize vector to unit length, using TEMP as temporary variable.
- * TEMP will be zero if vector has zero length */
-#define MAT3_NORMALIZE_VEC(V,TEMP) \
-	if ((TEMP = sqrt(MAT3_DOT_PRODUCT(V,V))) > MAT3_EPSILON) { \
-	   TEMP = 1.0 / TEMP; \
-	   MAT3_SCALE_VEC(V,V,TEMP); \
-	} else TEMP = 0.0
-
-/* Scale vector by given factor, storing result vector in RESULT_V */
-#define MAT3_SCALE_VEC(RESULT_V,V,SCALE) \
-	MAT3_SET_VEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), (V)[2]*(SCALE))
-
-/* Adds vectors V1 and V2, storing result in RESULT_V */
-#define MAT3_ADD_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
-			       (V1)[2]+(V2)[2])
-
-/* Subtracts vector V2 from V1, storing result in RESULT_V */
-#define MAT3_SUB_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
-			       (V1)[2]-(V2)[2])
-
-/* Multiplies vectors V1 and V2, storing result in RESULT_V */
-#define MAT3_MULT_VEC(RESULT_V,V1,V2) \
-	MAT3_SET_VEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
-			       (V1)[2]*(V2)[2])
-
-/* Sets RESULT_V to the linear combination of V1 and V2, scaled by
- * SCALE1 and SCALE2, respectively */
-#define MAT3_LINEAR_COMB(RESULT_V,SCALE1,V1,SCALE2,V2) \
-	MAT3_SET_VEC(RESULT_V,	(SCALE1)*(V1)[0] + (SCALE2)*(V2)[0], \
-				(SCALE1)*(V1)[1] + (SCALE2)*(V2)[1], \
-				(SCALE1)*(V1)[2] + (SCALE2)*(V2)[2])
-
-/* Several of the vector macros are useful for homogeneous-coord vectors */
-#define MAT3_SET_HVEC(V,X,Y,Z,W) ((V)[0]=(X), (V)[1]=(Y), \
-				  (V)[2]=(Z), (V)[3]=(W))
-
-#define MAT3_COPY_HVEC(TO,FROM) ((TO)[0] = (FROM)[0], \
-				 (TO)[1] = (FROM)[1], \
-				 (TO)[2] = (FROM)[2], \
-				 (TO)[3] = (FROM)[3])
-
-#define MAT3_SCALE_HVEC(RESULT_V,V,SCALE) \
-	MAT3_SET_HVEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), \
-				(V)[2]*(SCALE), (V)[3]*(SCALE))
-
-#define MAT3_ADD_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
-				(V1)[2]+(V2)[2], (V1)[3]+(V2)[3])
-
-#define MAT3_SUB_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
-				(V1)[2]-(V2)[2], (V1)[3]-(V2)[3])
-
-#define MAT3_MULT_HVEC(RESULT_V,V1,V2) \
-	MAT3_SET_HVEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
-				(V1)[2]*(V2)[2], (V1)[3]*(V2)[3])
-
-/* ------------------------------  Entries  ------------------------------- */
-
-
-/* In MAT3geom.c */
-void 		MAT3direction_matrix (MAT3mat result_mat, MAT3mat mat);
-int 		MAT3normal_matrix (MAT3mat result_mat, MAT3mat mat);
-void		MAT3rotate (MAT3mat result_mat, MAT3vec axis, double angle_in_radians);
-void		MAT3translate (MAT3mat result_mat, MAT3vec trans);
-void		MAT3scale (MAT3mat result_mat, MAT3vec scale);
-void		MAT3shear(MAT3mat result_mat, double xshear, double yshear);
-
-/* In MAT3mat.c */
-void		MAT3identity(MAT3mat);
-void		MAT3zero(MAT3mat);
-void		MAT3copy (MAT3mat to, MAT3mat from);
-void		MAT3mult (MAT3mat result, MAT3mat, MAT3mat);
-void		MAT3transpose (MAT3mat result, MAT3mat);
-int			MAT3invert (MAT3mat result, MAT3mat);
-void		MAT3print (MAT3mat, FILE *fp);
-void		MAT3print_formatted (MAT3mat, FILE *fp, 
-			 	     char *title, char *head, char *format, char *tail);
-extern int		MAT3equal( void );
-extern double		MAT3trace( void );
-extern int		MAT3power( void );
-extern int		MAT3column_reduce( void );
-extern int		MAT3kernel_basis( void );
-
-/* In MAT3vec.c */
-void		MAT3mult_vec(MAT3vec result_vec, MAT3vec vec, MAT3mat mat);
-int		MAT3mult_hvec (MAT3hvec result_vec, MAT3hvec vec, MAT3mat mat, int normalize);
-void		MAT3cross_product(MAT3vec result,MAT3vec,MAT3vec);
-void		MAT3perp_vec(MAT3vec result_vec, MAT3vec vec, int is_unit);
-
-#endif /* MAT3_HAS_BEEN_INCLUDED */
-
diff --git a/Tri2obj/polar.c b/Tri2obj/polar.c
deleted file mode 100644
index 665efec33..000000000
--- a/Tri2obj/polar.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/**************************************************************************
- * polar.c -- routines to deal with polar math and transformations
- *
- * Written by Curtis Olson, started June 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#include <math.h>
-#include <stdio.h>
-
-#include <Include/fg_constants.h>
-
-#include "polar.h"
-
-
-/* we can save these values between calls for efficiency */
-static double st, ct, sp, cp;
-
-
-/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
- * must be specified in radians.  The FG convention is for distances
- * to be specified in meters */
-struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius) {
-    struct fgCartesianPoint pnew;
-
-    pnew.x = cos(lon) * cos(lat) * radius;
-    pnew.y = sin(lon) * cos(lat) * radius;
-    pnew.z = sin(lat) * radius;
-
-    return(pnew);
-}
-
-
-/* Precalculate as much as possible so we can do a batch of transforms
- * through the same angles, will rotates a cartesian point about the
- * center of the earth by Theta (longitude axis) and Phi (latitude
- * axis) */
-
-/* Here are the unoptimized transformation equations 
-
-   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
-	     sin(Phi) * z
-   y' = -sin(Theta) * x + cos(Theta) * y
-   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
-	     cos(Phi) * z;
-
- */
-void fgRotateBatchInit(double Theta, double Phi) {
-    printf("Theta = %.3f, Phi = %.3f\n", Theta, Phi);
-
-    st = sin(Theta);
-    ct = cos(Theta);
-    sp = sin(-Phi);
-    cp = cos(-Phi);
-}
-
-/* Rotates a cartesian point about the center of the earth by Theta
- * (longitude axis) and Phi (latitude axis) */
-struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p) {
-    struct fgCartesianPoint p1, p2;
-
-    /* printf("start = %.3f %.3f %.3f\n", p.x, p.y, p.z); */
-
-    /* rotate about the z axis */
-    p1.x = ct * p.x - st * p.y;
-    p1.y = st * p.x + ct * p.y;
-    p1.z = p.z;
-
-    /* printf("step 1 = %.3f %.3f %.3f\n", p1.x, p1.y, p1.z); */
-
-    /* rotate new point about y axis */
-    p2.x = cp * p1.x + sp * p1.z;
-    p2.y = p1.y;
-    p2.z = cp * p1.z - sp * p1.x;
-
-    /* printf("cp = %.5f, sp = %.5f\n", cp, sp); */
-    /* printf("(1) = %.5f, (2) = %.5f\n", cp * p1.z, sp * p1.x); */
-
-    /* printf("step 2 = %.3f %.3f %.3f\n", p2.x, p2.y, p2.z); */
-
-    return(p2);
-}
-
-
-/* $Log$
-/* Revision 1.2  1998/04/14 02:26:10  curt
-/* Code reorganizations.  Added a Lib/ directory for more general libraries.
-/*
- * Revision 1.1  1998/04/08 23:22:16  curt
- * Adopted Gnu automake/autoconf system.
- *
- * Revision 1.5  1998/01/27 00:48:00  curt
- * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
- * system and commandline/config file processing code.
- *
- * Revision 1.4  1998/01/19 19:27:12  curt
- * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
- * This should simplify things tremendously.
- *
- * Revision 1.3  1997/12/15 23:54:54  curt
- * Add xgl wrappers for debugging.
- * Generate terrain normals on the fly.
- *
- * Revision 1.2  1997/07/31 22:52:27  curt
- * Working on redoing internal coordinate systems & scenery transformations.
- *
- * Revision 1.1  1997/07/07 21:02:36  curt
- * Initial revision.
- * */
diff --git a/Tri2obj/polar.h b/Tri2obj/polar.h
deleted file mode 100644
index fc54a77c5..000000000
--- a/Tri2obj/polar.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**************************************************************************
- * polar.h -- routines to deal with polar math and transformations
- *
- * Written by Curtis Olson, started June 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#ifndef _POLAR_H
-#define _POLAR_H
-
-
-#include <Include/fg_types.h>
-
-
-/* Convert a polar coordinate to a cartesian coordinate.  Lon and Lat
- * must be specified in radians.  The FG convention is for distances
- * to be specified in meters */
-struct fgCartesianPoint fgPolarToCart(double lon, double lat, double radius);
-
-
-/* Precalculate as much as possible so we can do a batch of transforms
- * through the same angles, will rotates a cartesian point about the
- * center of the earth by Theta (longitude axis) and Phi (latitude
- * axis) */
-
-/* Here are the unoptimized transformation equations 
-
-   x' = cos(Phi) * cos(Theta) * x + cos(Phi) * sin(Theta) * y + 
-	     sin(Phi) * z
-   y' = -sin(Theta) * x + cos(Theta) * y
-   z' = -sin(Phi) * sin(Theta) * y - sin(Phi) * cos(Theta) * x + 
-	     cos(Phi) * z;
-
- */
-void fgRotateBatchInit(double Theta, double Phi);
-
-
-/* Rotates a cartesian point about the center of the earth by Theta
- * (longitude axis) and Phi (latitude axis) */
-struct fgCartesianPoint fgRotateCartesianPoint(struct fgCartesianPoint p);
-
-
-#endif /* _POLAR_H */
-
-
-/* $Log$
-/* Revision 1.1  1998/04/08 23:22:17  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.7  1998/01/27 00:48:00  curt
- * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
- * system and commandline/config file processing code.
- *
- * Revision 1.6  1998/01/22 02:59:39  curt
- * Changed #ifdef FILE_H to #ifdef _FILE_H
- *
- * Revision 1.5  1998/01/19 19:27:13  curt
- * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
- * This should simplify things tremendously.
- *
- * Revision 1.4  1997/12/15 23:54:55  curt
- * Add xgl wrappers for debugging.
- * Generate terrain normals on the fly.
- *
- * Revision 1.3  1997/07/31 22:52:28  curt
- * Working on redoing internal coordinate systems & scenery transformations.
- *
- * Revision 1.2  1997/07/23 21:52:21  curt
- * Put comments around the text after an #endif for increased portability.
- *
- * Revision 1.1  1997/07/07 21:02:37  curt
- * Initial revision.
- *
- */
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 482906b37..4b12310de 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -36,9 +36,9 @@
 #include <Include/fg_types.h>
 #include <Bucket/bucketutils.h>
 
-#include "fg_geodesy.h"
-#include "mat3.h"
-#include "polar.h"
+#include <Math/fg_geodesy.h>
+#include <Math/mat3.h>
+#include <Math/polar.h>
 
 
 int nodecount, tricount;
@@ -640,9 +640,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.13  1998/04/14 02:26:11  curt
-/* Code reorganizations.  Added a Lib/ directory for more general libraries.
+/* Revision 1.14  1998/04/18 04:01:32  curt
+/* Now use libMath rather than having local copies of math routines.
 /*
+ * Revision 1.13  1998/04/14 02:26:11  curt
+ * Code reorganizations.  Added a Lib/ directory for more general libraries.
+ *
  * Revision 1.12  1998/04/08 23:22:18  curt
  * Adopted Gnu automake/autoconf system.
  *

From efcd77da4ac1c9bf6d1d81c22bebb35155da8531 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 18 Apr 1998 04:02:48 +0000
Subject: [PATCH 064/283] Added zlib support in placed and other misc. tweaks.

---
 AssemTris/Makefile.in |  5 ++++-
 DemRaw2ascii/Makefile | 51 -------------------------------------------
 FixNode/Makefile.am   |  6 ++++-
 FixNode/Makefile.in   | 11 +++++++---
 4 files changed, 17 insertions(+), 56 deletions(-)
 delete mode 100644 DemRaw2ascii/Makefile

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index f40608c87..62a291872 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,7 +344,10 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.2  1998/04/14 02:26:00  curt
+# Revision 1.3  1998/04/18 04:02:48  curt
+# Added zlib support in placed and other misc. tweaks.
+#
+# Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
 # Revision 1.1  1998/04/08 22:54:57  curt
diff --git a/DemRaw2ascii/Makefile b/DemRaw2ascii/Makefile
deleted file mode 100644
index 1a11a998f..000000000
--- a/DemRaw2ascii/Makefile
+++ /dev/null
@@ -1,51 +0,0 @@
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started February 1998.
-#
-# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-TARGET = raw2ascii
-
-CFILES = main.c rawdem.c
-LDLIBS = -lm
-
-
-include $(FG_ROOT_SRC)/commondefs
-
-
-#---------------------------------------------------------------------------
-# Rule for TARGET
-#---------------------------------------------------------------------------
-
-$(TARGET): $(OBJECTS)
-	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
-
-
-include $(COMMONRULES)
-
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.1  1998/03/02 23:31:00  curt
-# Initial revision.
-#
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index fa6b8ef2d..04d7e2094 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -33,7 +33,8 @@ fixnode_SOURCES = \
 
 fixnode_LDADD = \
 	$(top_builddir)/Lib/DEM/libDEM.la \
-        $(top_builddir)/Lib/Bucket/libBucket.la
+        $(top_builddir)/Lib/Bucket/libBucket.la \
+        $(top_builddir)/Lib/zlib/libz.la
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
@@ -45,6 +46,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/04/18 04:02:54  curt
+# Added zlib support in placed and other misc. tweaks.
+#
 # Revision 1.2  1998/04/14 02:26:02  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index 828ad939a..f10ec5740 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -105,7 +105,8 @@ fixnode_SOURCES = \
 
 fixnode_LDADD = \
 	$(top_builddir)/Lib/DEM/libDEM.la \
-        $(top_builddir)/Lib/Bucket/libBucket.la
+        $(top_builddir)/Lib/Bucket/libBucket.la \
+        $(top_builddir)/Lib/zlib/libz.la
 
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
@@ -127,7 +128,8 @@ X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 fixnode_OBJECTS =  fixnode.o main.o triload.o
 fixnode_DEPENDENCIES =  $(top_builddir)/Lib/DEM/libDEM.la \
-$(top_builddir)/Lib/Bucket/libBucket.la
+$(top_builddir)/Lib/Bucket/libBucket.la \
+$(top_builddir)/Lib/zlib/libz.la
 fixnode_LDFLAGS = 
 CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
@@ -369,7 +371,10 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.2  1998/04/14 02:26:03  curt
+# Revision 1.3  1998/04/18 04:02:54  curt
+# Added zlib support in placed and other misc. tweaks.
+#
+# Revision 1.2  1998/04/14 02:26:02  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
 # Revision 1.1  1998/04/08 23:05:54  curt

From d365ac9affd9df569c421a07d9849e0337822124 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 21 Apr 1998 17:03:41 +0000
Subject: [PATCH 065/283] Prepairing for C++ integration.

---
 DEM/dem.hxx      |  8 +++++
 DEM/leastsqs.cxx | 72 ++++++++++++++++++++--------------------
 DEM/leastsqs.hxx | 86 ++++++++++++++++++++++++++++--------------------
 3 files changed, 95 insertions(+), 71 deletions(-)

diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 23f55b4aa..4a84871d2 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -28,6 +28,11 @@
 #define _DEM_H
 
 
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
 #include <stdio.h>
 
 #include <Bucket/bucketutils.h>
@@ -125,6 +130,9 @@ public:
 
 
 // $Log$
+// Revision 1.4  1998/04/21 17:03:41  curt
+// Prepairing for C++ integration.
+//
 // Revision 1.3  1998/04/18 03:53:06  curt
 // Added zlib support.
 //
diff --git a/DEM/leastsqs.cxx b/DEM/leastsqs.cxx
index 7414fa628..a97581de4 100644
--- a/DEM/leastsqs.cxx
+++ b/DEM/leastsqs.cxx
@@ -1,26 +1,26 @@
-/* leastsqs.c -- Implements a simple linear least squares best fit routine
- *
- * Written by Curtis Olson, started September 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
+// leastsqs.c -- Implements a simple linear least squares best fit routine
+//
+// Written by Curtis Olson, started September 1997.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
 
 
 #include <stdio.h>
@@ -81,7 +81,7 @@ double least_squares_error(double *x, double *y, int n, double m, double b) {
     for ( i = 0; i < n; i++ ) {
 	error = y[i] - (m * x[i] + b);
 	sum += error * error;
-	/* printf("%.2f %.2f\n", error, sum); */
+	// printf("%.2f %.2f\n", error, sum);
     }
 
     return ( sum / (double)n );
@@ -111,14 +111,16 @@ double least_squares_max_error(double *x, double *y, int n, double m, double b){
 }
 
 
-/* $Log$
-/* Revision 1.1  1998/04/08 22:57:24  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.1  1998/03/19 02:54:47  curt
- * Reorganized into a class lib called fgDEM.
- *
- * Revision 1.1  1997/10/13 17:02:35  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.2  1998/04/21 17:03:41  curt
+// Prepairing for C++ integration.
+//
+// Revision 1.1  1998/04/08 22:57:24  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.1  1998/03/19 02:54:47  curt
+// Reorganized into a class lib called fgDEM.
+//
+// Revision 1.1  1997/10/13 17:02:35  curt
+// Initial revision.
+//
diff --git a/DEM/leastsqs.hxx b/DEM/leastsqs.hxx
index 8e0d3dec8..71760ba70 100644
--- a/DEM/leastsqs.hxx
+++ b/DEM/leastsqs.hxx
@@ -1,26 +1,35 @@
-/* leastsqs.h -- Implements a simple linear least squares best fit routine
- *
- * Written by Curtis Olson, started September 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
+// leastsqs.h -- Implements a simple linear least squares best fit routine
+//
+// Written by Curtis Olson, started September 1997.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+///
+
+
+#ifndef _LEASTSQS_H
+#define _LEASTSQS_H
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
 
 
 /* 
@@ -45,7 +54,7 @@ void least_squares(double *x, double *y, int n, double *m, double *b);
               (y[i] - y_hat[i])^2
               -------------------
                       n
- */
+*/
 double least_squares_error(double *x, double *y, int n, double m, double b);
 
 
@@ -53,18 +62,23 @@ double least_squares_error(double *x, double *y, int n, double m, double b);
   return the maximum least squares error:
 
               (y[i] - y_hat[i])^2
- */
+*/
 double least_squares_max_error(double *x, double *y, int n, double m, double b);
 
 
-/* $Log$
-/* Revision 1.1  1998/04/08 22:57:25  curt
-/* Adopted Gnu automake/autoconf system.
-/*
- * Revision 1.1  1998/03/19 02:54:48  curt
- * Reorganized into a class lib called fgDEM.
- *
- * Revision 1.1  1997/10/13 17:02:35  curt
- * Initial revision.
- *
- */
+#endif // _LEASTSQS_H
+
+
+// $Log$
+// Revision 1.2  1998/04/21 17:03:42  curt
+// Prepairing for C++ integration.
+//
+// Revision 1.1  1998/04/08 22:57:25  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.1  1998/03/19 02:54:48  curt
+// Reorganized into a class lib called fgDEM.
+//
+// Revision 1.1  1997/10/13 17:02:35  curt
+// Initial revision.
+//

From 18ae70b3b1c653571c8bf3c984dda11e5651c722 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 22 Apr 1998 13:14:46 +0000
Subject: [PATCH 066/283] Fixed a bug in zlib usage.

---
 DEM/dem.cxx | 11 +++++++----
 DEM/dem.hxx |  7 +++++--
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 821f23fc3..462013bf9 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -125,7 +125,7 @@ int fgDEM::close ( void ) {
 
 
 // return next token from input stream
-static void next_token(gzFile *fd, char *token) {
+static void next_token(gzFile fd, char *token) {
     int i, result;
     char c;
 
@@ -152,7 +152,7 @@ static void next_token(gzFile *fd, char *token) {
 
 
 // return next integer from input stream
-static int next_int(gzFile *fd) {
+static int next_int(gzFile fd) {
     char token[80];
 
     next_token(fd, token);
@@ -161,7 +161,7 @@ static int next_int(gzFile *fd) {
 
 
 // return next double from input stream
-static double next_double(gzFile *fd) {
+static double next_double(gzFile fd) {
     char token[80];
 
     next_token(fd, token);
@@ -170,7 +170,7 @@ static double next_double(gzFile *fd) {
 
 
 // return next exponential num from input stream
-static int next_exp(gzFile *fd) {
+static int next_exp(gzFile fd) {
     char token[80];
     double mantissa;
     int exp, acc;
@@ -772,6 +772,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.4  1998/04/22 13:14:46  curt
+// Fixed a bug in zlib usage.
+//
 // Revision 1.3  1998/04/18 03:53:05  curt
 // Added zlib support.
 //
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 4a84871d2..065ead15c 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -45,7 +45,7 @@
 
 class fgDEM {
     // file pointer for input
-    gzFile *fd;
+    gzFile fd;
 
     // coordinates (in arc seconds) of south west corner
     double originx, originy;
@@ -79,7 +79,7 @@ class fgDEM {
 
 public:
 
-    // Constructor (opens a DEM file)
+    // Constructor
     fgDEM( void );
 
     // open a DEM file (use "-" if input is coming from stdin)
@@ -130,6 +130,9 @@ public:
 
 
 // $Log$
+// Revision 1.5  1998/04/22 13:14:46  curt
+// Fixed a bug in zlib usage.
+//
 // Revision 1.4  1998/04/21 17:03:41  curt
 // Prepairing for C++ integration.
 //

From fe33bf171ee771b320b0db883d126fddf04ffe91 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 24 Apr 1998 00:43:59 +0000
Subject: [PATCH 067/283] Added zlib support.

---
 AssemTris/Makefile.in    |  4 ++--
 DemRaw2ascii/Makefile.am |  5 ++++-
 DemRaw2ascii/Makefile.in |  7 +++++--
 FixNode/Makefile.in      |  3 +++
 FixObj/Makefile.am       |  8 +++++++-
 FixObj/Makefile.in       | 11 +++++++++--
 SplitTris/Makefile.am    |  7 ++++++-
 SplitTris/Makefile.in    | 10 ++++++++--
 Tri2obj/Makefile.am      |  7 ++++++-
 Tri2obj/Makefile.in      | 10 ++++++++--
 10 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index 62a291872..c227dfc9a 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.3  1998/04/18 04:02:48  curt
-# Added zlib support in placed and other misc. tweaks.
+# Revision 1.4  1998/04/24 00:43:59  curt
+# Added zlib support.
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.am b/DemRaw2ascii/Makefile.am
index ab05c9034..2ff4fb31e 100644
--- a/DemRaw2ascii/Makefile.am
+++ b/DemRaw2ascii/Makefile.am
@@ -26,7 +26,7 @@
 
 bin_PROGRAMS = raw2ascii
 
-raw2ascii_SOURCES = main.c rawdem.c
+raw2ascii_SOURCES = main.c rawdem.c rawdem.h
 
 raw2ascii_LDADD = 
 
@@ -35,6 +35,9 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/04/24 00:44:04  curt
+# Added zlib support.
+#
 # Revision 1.1  1998/04/18 03:59:44  curt
 # Incorporated into gnu automake/autoconf system.
 #
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index 3e72c38fc..dbfe637ee 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -98,7 +98,7 @@ VERSION = @VERSION@
 
 bin_PROGRAMS = raw2ascii
 
-raw2ascii_SOURCES = main.c rawdem.c
+raw2ascii_SOURCES = main.c rawdem.c rawdem.h
 
 raw2ascii_LDADD = 
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -343,7 +343,10 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.1  1998/04/18 03:59:45  curt
+# Revision 1.2  1998/04/24 00:44:04  curt
+# Added zlib support.
+#
+# Revision 1.1  1998/04/18 03:59:44  curt
 # Incorporated into gnu automake/autoconf system.
 #
 
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index f10ec5740..a9ccdeaeb 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,6 +371,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/24 00:44:04  curt
+# Added zlib support.
+#
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
 #
diff --git a/FixObj/Makefile.am b/FixObj/Makefile.am
index e041122ea..2ee3159b4 100644
--- a/FixObj/Makefile.am
+++ b/FixObj/Makefile.am
@@ -28,13 +28,19 @@ bin_PROGRAMS = fixobj
 
 fixobj_SOURCES = main.c obj.c obj.h
 
-fixobj_LDADD = $(top_builddir)/Lib/Math/libMath.la
+fixobj_LDADD = \
+	$(top_builddir)/Lib/Math/libMath.la \
+	$(top_builddir)/Lib/Debug/libDebug.la \
+	$(top_builddir)/Lib/zlib/libz.la
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/24 00:44:05  curt
+# Added zlib support.
+#
 # Revision 1.3  1998/04/18 04:01:02  curt
 # Now use libMath rather than having local copies of math routines.
 #
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index de2c960d3..02a640867 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -100,7 +100,10 @@ bin_PROGRAMS = fixobj
 
 fixobj_SOURCES = main.c obj.c obj.h
 
-fixobj_LDADD = $(top_builddir)/Lib/Math/libMath.la
+fixobj_LDADD = \
+	$(top_builddir)/Lib/Math/libMath.la \
+	$(top_builddir)/Lib/Debug/libDebug.la \
+	$(top_builddir)/Lib/zlib/libz.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
@@ -116,7 +119,8 @@ X_LIBS = @X_LIBS@
 X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 fixobj_OBJECTS =  main.o obj.o
-fixobj_DEPENDENCIES =  $(top_builddir)/Lib/Math/libMath.la
+fixobj_DEPENDENCIES =  $(top_builddir)/Lib/Math/libMath.la \
+$(top_builddir)/Lib/Debug/libDebug.la $(top_builddir)/Lib/zlib/libz.la
 fixobj_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -343,6 +347,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/24 00:44:05  curt
+# Added zlib support.
+#
 # Revision 1.3  1998/04/18 04:01:02  curt
 # Now use libMath rather than having local copies of math routines.
 #
diff --git a/SplitTris/Makefile.am b/SplitTris/Makefile.am
index d17e02df2..e928787d7 100644
--- a/SplitTris/Makefile.am
+++ b/SplitTris/Makefile.am
@@ -30,13 +30,18 @@ splittris_SOURCES = splittris.c splittris.h
 
 splittris_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la
+	$(top_builddir)/Lib/Math/libMath.la \
+        $(top_builddir)/Lib/Debug/libDebug.la \
+        $(top_builddir)/Lib/zlib/libz.la
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/24 00:44:06  curt
+# Added zlib support.
+#
 # Revision 1.3  1998/04/18 04:01:17  curt
 # Now use libMath rather than having local copies of math routines.
 #
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index 1282f517e..5ab5c561f 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -102,7 +102,9 @@ splittris_SOURCES = splittris.c splittris.h
 
 splittris_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la
+	$(top_builddir)/Lib/Math/libMath.la \
+        $(top_builddir)/Lib/Debug/libDebug.la \
+        $(top_builddir)/Lib/zlib/libz.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
@@ -119,7 +121,8 @@ X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 splittris_OBJECTS =  splittris.o
 splittris_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la \
-$(top_builddir)/Lib/Math/libMath.la
+$(top_builddir)/Lib/Math/libMath.la \
+$(top_builddir)/Lib/Debug/libDebug.la $(top_builddir)/Lib/zlib/libz.la
 splittris_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -346,6 +349,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/24 00:44:06  curt
+# Added zlib support.
+#
 # Revision 1.3  1998/04/18 04:01:17  curt
 # Now use libMath rather than having local copies of math routines.
 #
diff --git a/Tri2obj/Makefile.am b/Tri2obj/Makefile.am
index 0bf71d497..86b10ba82 100644
--- a/Tri2obj/Makefile.am
+++ b/Tri2obj/Makefile.am
@@ -30,13 +30,18 @@ tri2obj_SOURCES = tri2obj.c tri2obj.h
 
 tri2obj_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la
+	$(top_builddir)/Lib/Math/libMath.la \
+        $(top_builddir)/Lib/Debug/libDebug.la \
+        $(top_builddir)/Lib/zlib/libz.la
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/24 00:44:07  curt
+# Added zlib support.
+#
 # Revision 1.3  1998/04/18 04:01:29  curt
 # Now use libMath rather than having local copies of math routines.
 #
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index 9a947ad24..4dd02536c 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -102,7 +102,9 @@ tri2obj_SOURCES = tri2obj.c tri2obj.h
 
 tri2obj_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la
+	$(top_builddir)/Lib/Math/libMath.la \
+        $(top_builddir)/Lib/Debug/libDebug.la \
+        $(top_builddir)/Lib/zlib/libz.la
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../../Include/config.h
 CONFIG_CLEAN_FILES = 
@@ -119,7 +121,8 @@ X_EXTRA_LIBS = @X_EXTRA_LIBS@
 X_PRE_LIBS = @X_PRE_LIBS@
 tri2obj_OBJECTS =  tri2obj.o
 tri2obj_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la \
-$(top_builddir)/Lib/Math/libMath.la
+$(top_builddir)/Lib/Math/libMath.la \
+$(top_builddir)/Lib/Debug/libDebug.la $(top_builddir)/Lib/zlib/libz.la
 tri2obj_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -346,6 +349,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/04/24 00:44:07  curt
+# Added zlib support.
+#
 # Revision 1.3  1998/04/18 04:01:29  curt
 # Now use libMath rather than having local copies of math routines.
 #

From b2567ad1ccecd6d369524eac6167ef29801598ab Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 25 Apr 1998 15:00:32 +0000
Subject: [PATCH 068/283] Changed "r" to "rb" in gzopen() options.  This fixes
 bad behavior in win32.

---
 DEM/dem.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 462013bf9..3aacf75c8 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -105,7 +105,7 @@ int fgDEM::open ( char *file ) {
 	// fd = stdin;
 	fd = gzdopen(STDIN_FILENO, "r");
     } else {
-	if ( (fd = gzopen(file, "r")) == NULL ) {
+	if ( (fd = gzopen(file, "rb")) == NULL ) {
 	    printf("Cannot gzopen %s\n", file);
 	    return(0);
 	}
@@ -772,6 +772,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.5  1998/04/25 15:00:32  curt
+// Changed "r" to "rb" in gzopen() options.  This fixes bad behavior in win32.
+//
 // Revision 1.4  1998/04/22 13:14:46  curt
 // Fixed a bug in zlib usage.
 //

From 87db7184eae8c9c3f23c31d16eb91f7dbe5956f8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 25 Apr 1998 15:12:08 +0000
Subject: [PATCH 069/283] Misc. tweaks.

---
 AssemTris/Makefile.in    | 4 ++--
 DemRaw2ascii/Makefile.in | 3 +++
 FixNode/Makefile.in      | 4 ++--
 FixObj/Makefile.in       | 3 +++
 SplitTris/Makefile.in    | 3 +++
 Tri2obj/Makefile.in      | 3 +++
 6 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index c227dfc9a..0dd97ba9e 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.4  1998/04/24 00:43:59  curt
-# Added zlib support.
+# Revision 1.5  1998/04/25 15:12:08  curt
+# Misc. tweaks.
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index dbfe637ee..a1bd49d30 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,6 +343,9 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/04/25 15:12:11  curt
+# Misc. tweaks.
+#
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
 #
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index a9ccdeaeb..a9c2c0615 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.4  1998/04/24 00:44:04  curt
-# Added zlib support.
+# Revision 1.5  1998/04/25 15:12:12  curt
+# Misc. tweaks.
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index 02a640867..f2208f05b 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,6 +347,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/04/25 15:12:12  curt
+# Misc. tweaks.
+#
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
 #
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index 5ab5c561f..7fde8cd0f 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,6 +349,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/04/25 15:12:13  curt
+# Misc. tweaks.
+#
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
 #
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index 4dd02536c..b9221b9a4 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,6 +349,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/04/25 15:12:14  curt
+# Misc. tweaks.
+#
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.
 #

From 901d45860a450f513afa524873de3b87366a8c07 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 25 Apr 1998 22:06:35 +0000
Subject: [PATCH 070/283] Edited cvs log messages in source files ... bad bad
 bad!

---
 Tools/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 2147c3a22..8f3355b90 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	AssemTris \
 	Dem2node \
+	Deminfo \
 	DemRaw2ascii \
 	FixNode \
 	FixObj \

From 8ec9cfff669aa440a4d91fb2aca12201a6ba068e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 26 Apr 1998 05:01:28 +0000
Subject: [PATCH 071/283] Tweaks.

---
 AssemTris/Makefile.in    | 4 ++--
 DemRaw2ascii/Makefile.in | 4 ++--
 Tools/Makefile.in        | 1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index 0dd97ba9e..8b0483d03 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.5  1998/04/25 15:12:08  curt
-# Misc. tweaks.
+# Revision 1.6  1998/04/26 05:01:31  curt
+# Tweaks.
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index a1bd49d30..e1d47af29 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,8 +343,8 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.3  1998/04/25 15:12:11  curt
-# Misc. tweaks.
+# Revision 1.4  1998/04/26 05:01:34  curt
+# Tweaks.
 #
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
diff --git a/Tools/Makefile.in b/Tools/Makefile.in
index 352c4f3de..b9699ac0f 100644
--- a/Tools/Makefile.in
+++ b/Tools/Makefile.in
@@ -76,6 +76,7 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	AssemTris \
 	Dem2node \
+	Deminfo \
 	DemRaw2ascii \
 	FixNode \
 	FixObj \

From 5834ac2582bd746f3370a95a1f8b57b6d234ec51 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 26 Apr 1998 05:02:06 +0000
Subject: [PATCH 072/283] Added #ifdef HAVE_STDLIB_H

---
 FixNode/Makefile.in | 4 ++--
 FixNode/main.cxx    | 7 +++++++
 FixNode/triload.cxx | 7 +++++++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index a9c2c0615..b08f7768a 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.5  1998/04/25 15:12:12  curt
-# Misc. tweaks.
+# Revision 1.6  1998/04/26 05:02:06  curt
+# Added #ifdef HAVE_STDLIB_H
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/FixNode/main.cxx b/FixNode/main.cxx
index 8130ab8d4..2952d0cf8 100644
--- a/FixNode/main.cxx
+++ b/FixNode/main.cxx
@@ -29,6 +29,10 @@
 #include <string.h>
 #include <sys/types.h>
 
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif // HAVE_STDLIB_H
+
 #include <DEM/dem.hxx>
 
 #include "fixnode.hxx"
@@ -104,6 +108,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.3  1998/04/26 05:02:06  curt
+// Added #ifdef HAVE_STDLIB_H
+//
 // Revision 1.2  1998/04/14 02:26:04  curt
 // Code reorganizations.  Added a Lib/ directory for more general libraries.
 //
diff --git a/FixNode/triload.cxx b/FixNode/triload.cxx
index 3986780ac..6852f643d 100644
--- a/FixNode/triload.cxx
+++ b/FixNode/triload.cxx
@@ -26,6 +26,10 @@
 #include <stdio.h>
 #include <string.h>
 
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif // HAVE_STDLIB_H
+
 #include "triload.hxx"
 
 
@@ -65,6 +69,9 @@ void triload(char *filename, double nodes[MAX_NODES][3]) {
 
 
 // $Log$
+// Revision 1.2  1998/04/26 05:02:06  curt
+// Added #ifdef HAVE_STDLIB_H
+//
 // Revision 1.1  1998/04/08 23:05:58  curt
 // Adopted Gnu automake/autoconf system.
 //

From 821c04f55bc138ec8c8d22bb442f27a16a6f2cf7 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 26 Apr 1998 05:02:12 +0000
Subject: [PATCH 073/283] Tweaks

---
 FixObj/Makefile.in    | 4 ++--
 SplitTris/Makefile.in | 4 ++--
 Tri2obj/Makefile.in   | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index f2208f05b..a925f70c2 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.5  1998/04/25 15:12:12  curt
-# Misc. tweaks.
+# Revision 1.6  1998/04/26 05:02:12  curt
+# Tweaks
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index 7fde8cd0f..720ef4864 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.5  1998/04/25 15:12:13  curt
-# Misc. tweaks.
+# Revision 1.6  1998/04/26 05:02:14  curt
+# Tweaks
 #
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index b9221b9a4..e6a4ddbcd 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.5  1998/04/25 15:12:14  curt
-# Misc. tweaks.
+# Revision 1.6  1998/04/26 05:02:22  curt
+# Tweaks
 #
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.

From 05efe17b9240a6b19c4d9b0dee1a5b5e31f47952 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 26 Apr 1998 13:29:12 +0000
Subject: [PATCH 074/283] Removed DemInfo for now.

---
 Tools/Makefile.am | 1 -
 Tools/Makefile.in | 1 -
 2 files changed, 2 deletions(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 8f3355b90..2147c3a22 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -3,7 +3,6 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	AssemTris \
 	Dem2node \
-	Deminfo \
 	DemRaw2ascii \
 	FixNode \
 	FixObj \
diff --git a/Tools/Makefile.in b/Tools/Makefile.in
index b9699ac0f..352c4f3de 100644
--- a/Tools/Makefile.in
+++ b/Tools/Makefile.in
@@ -76,7 +76,6 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	AssemTris \
 	Dem2node \
-	Deminfo \
 	DemRaw2ascii \
 	FixNode \
 	FixObj \

From 5c90891d016b84c1be6d83e6882c1f92d123e531 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 26 Apr 1998 13:37:11 +0000
Subject: [PATCH 075/283] Removed DemInfo for now.

---
 AssemTris/Makefile.in    | 4 ++--
 DemRaw2ascii/Makefile.in | 4 ++--
 FixNode/Makefile.in      | 4 ++--
 FixObj/Makefile.in       | 4 ++--
 SplitTris/Makefile.in    | 4 ++--
 Tri2obj/Makefile.in      | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index 8b0483d03..1e25fa0fb 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.6  1998/04/26 05:01:31  curt
-# Tweaks.
+# Revision 1.7  1998/04/26 13:37:11  curt
+# Removed DemInfo for now.
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index e1d47af29..51a6868a4 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,8 +343,8 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.4  1998/04/26 05:01:34  curt
-# Tweaks.
+# Revision 1.5  1998/04/26 13:37:12  curt
+# Removed DemInfo for now.
 #
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index b08f7768a..946aedb51 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.6  1998/04/26 05:02:06  curt
-# Added #ifdef HAVE_STDLIB_H
+# Revision 1.7  1998/04/26 13:37:12  curt
+# Removed DemInfo for now.
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index a925f70c2..f5f38a830 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.6  1998/04/26 05:02:12  curt
-# Tweaks
+# Revision 1.7  1998/04/26 13:37:13  curt
+# Removed DemInfo for now.
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index 720ef4864..29bc1bb36 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.6  1998/04/26 05:02:14  curt
-# Tweaks
+# Revision 1.7  1998/04/26 13:37:13  curt
+# Removed DemInfo for now.
 #
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index e6a4ddbcd..0a3d34c60 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.6  1998/04/26 05:02:22  curt
-# Tweaks
+# Revision 1.7  1998/04/26 13:37:14  curt
+# Removed DemInfo for now.
 #
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.

From 41515d1bae29b43b51b53aae18fd89ca7b1a0149 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 27 Apr 1998 03:32:03 +0000
Subject: [PATCH 076/283] Wrapped rint()'s in #ifdef HAVE_RINT

---
 DemRaw2ascii/rawdem.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/DemRaw2ascii/rawdem.c b/DemRaw2ascii/rawdem.c
index bab0bb105..8411035bd 100644
--- a/DemRaw2ascii/rawdem.c
+++ b/DemRaw2ascii/rawdem.c
@@ -23,6 +23,10 @@
  */
 
 
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <math.h>      /* rint() */
 #include <stdio.h>
 #include <stdlib.h>    /* atoi() atof() */
@@ -82,16 +86,32 @@ void rawReadDemHdr( fgRAWDEM *raw, char *hdr_file ) {
 	    raw->ncols = atoi(value);
 	} else if ( strcmp(key, "ULXMAP") == 0 ) {
 	    tmp = atof(value);
+#ifdef HAVE_RINT
 	    raw->ulxmap = (int)rint(tmp * 3600.0); /* convert to arcsec */
+#else
+#  error Port me rint()
+#endif
 	} else if ( strcmp(key, "ULYMAP") == 0 ) {
 	    tmp = atof(value);
+#ifdef HAVE_RINT
 	    raw->ulymap = (int)rint(tmp * 3600.0); /* convert to arcsec */
+#else
+#  error Port me rint()
+#endif
 	} else if ( strcmp(key, "XDIM") == 0 ) {
 	    tmp = atof(value);
+#ifdef HAVE_RINT
 	    raw->xdim = (int)rint(tmp * 3600.0);   /* convert to arcsec */
+#else
+#  error Port me rint()
+#endif
 	} else if ( strcmp(key, "YDIM") == 0 ) {
 	    tmp = atof(value);
+#ifdef HAVE_RINT
 	    raw->ydim = (int)rint(tmp * 3600.0);   /* convert to arcsec */
+#else
+#  error Port me rint()
+#endif
 	} else {
 	    /* ignore for now */
 	}
@@ -442,9 +462,12 @@ void rawProcessStrip( fgRAWDEM *raw, int lat_degrees, char *path ) {
 
 
 /* $Log$
-/* Revision 1.5  1998/04/18 03:59:46  curt
-/* Incorporated into gnu automake/autoconf system.
+/* Revision 1.6  1998/04/27 03:32:03  curt
+/* Wrapped rint()'s in #ifdef HAVE_RINT
 /*
+ * Revision 1.5  1998/04/18 03:59:46  curt
+ * Incorporated into gnu automake/autoconf system.
+ *
  * Revision 1.4  1998/04/06 21:09:43  curt
  * Additional win32 support.
  * Fixed a bad bug in dem file parsing that was causing the output to be

From 9cc98181fac9d578586194c67290c27b4a119e91 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 27 Apr 1998 03:33:11 +0000
Subject: [PATCH 077/283] Code now calculates a center reference points and
 outputs everything relative to that.  This is useful in the rendering engine
 to keep everything close to (0, 0, 0) where we can avoid many GLfloat
 precision problems.

---
 FixObj/obj.c | 122 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 107 insertions(+), 15 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index 018569439..fb15780da 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -35,6 +35,8 @@
 /* what do ya' know, here's some global variables */
 static double nodes[MAXNODES][3];
 static double normals[MAXNODES][3];
+static int faces[MAXNODES][3];
+int ncount, vncount, fcount;
 
 static int ccw_list[MAXNODES];
 int ccw_list_ptr;
@@ -44,6 +46,8 @@ int cw_list_ptr;
 
 FILE *in, *out;
 
+double refx, refy, refz;
+
 
 /* some simple list routines */
 
@@ -67,6 +71,42 @@ void list_add(int *list, int *list_ptr, int node) {
 }
 
 
+/* dump nodes */
+void dump_nodes( void ) {
+    int i;
+
+    fprintf(out, "\n");
+    for ( i = 0; i < ncount; i++ ) {
+	fprintf(out, "v %.4lf %.4lf %.4lf\n",
+		nodes[i][0] - refx, nodes[i][1] - refy, nodes[i][2] - refz);
+    }
+}
+
+
+/* dump normals */
+void dump_normals( void ) {
+    int i;
+
+    fprintf(out, "\n");
+    for ( i = 0; i < vncount; i++ ) {
+	fprintf(out, "vn %.4lf %.4lf %.4lf\n", 
+		normals[i][0], normals[i][1], normals[i][2]);
+    }
+}
+
+
+/* dump faces */
+void dump_faces( void ) {
+    int i;
+
+    fprintf(out, "\n");
+    for ( i = 0; i < fcount; i++ ) {
+	fprintf(out, "f %d %d %d\n", 
+		faces[i][0], faces[i][1], faces[i][2]);
+    }
+}
+
+
 /* dump list */
 void dump_list(int *list, int list_ptr) {
     int i;
@@ -142,7 +182,8 @@ double check_cur_face(int n1, int n2, int n3) {
 void obj_fix(char *infile, char *outfile) {
     char line[256];
     double dot_prod;
-    int first, ncount, vncount, n1, n2, n3, n4;
+    int first, n1, n2, n3, n4;
+    double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin;
     int is_ccw;
 
     if ( (in = fopen(infile, "r")) == NULL ) {
@@ -159,8 +200,9 @@ void obj_fix(char *infile, char *outfile) {
     list_init(&cw_list_ptr);
 
     first = 1;
-    ncount = 1;
-    vncount = 1;
+    ncount = 0;
+    vncount = 0;
+    fcount = 0;
 
     printf("Reading file:  %s\n", infile);
 
@@ -169,16 +211,37 @@ void obj_fix(char *infile, char *outfile) {
 	    /* pass along the comments verbatim */
 	    fprintf(out, "%s", line);
 	} else if ( strlen(line) <= 1 ) {
-	    /* pass along empty lines */
-	    fprintf(out, "%s", line);
+	    /* don't pass along empty lines */
+	    // fprintf(out, "%s", line);
 	} else if ( strncmp(line, "v ", 2) == 0 ) {
 	    /* save vertex to memory and output to file */
             if ( ncount < MAXNODES ) {
                 /* printf("vertex = %s", line); */
-                sscanf(line, "v %lf %lf %lf\n", 
-                       &nodes[ncount][0], &nodes[ncount][1], &nodes[ncount][2]);
-		fprintf(out, "v %.2f %.2f %.2f\n", 
-		       nodes[ncount][0], nodes[ncount][1], nodes[ncount][2]);
+                sscanf(line, "v %lf %lf %lf\n", &x, &y, &z);
+		nodes[ncount][0] = x;
+		nodes[ncount][1] = y;
+		nodes[ncount][2] = z;
+
+		/* first time through set min's and max'es */
+		if ( ncount == 1 ) {
+		    xmin = x;
+		    xmax = x;
+		    ymin = y;
+		    ymax = y;
+		    zmin = z;
+		    zmax = z;
+		}
+    
+		/* keep track of min/max vertex values */
+		if ( x < xmin ) xmin = x;
+		if ( x > xmax ) xmax = x;
+		if ( y < ymin ) ymin = y;
+		if ( y > ymax ) ymax = y;
+		if ( z < zmin ) zmin = z;
+		if ( z > zmax ) zmax = z;		
+
+		// fprintf(out, "v %.2f %.2f %.2f\n", 
+		//       nodes[ncount][0], nodes[ncount][1], nodes[ncount][2]);
 		ncount++;
             } else {
                 printf("Read too many nodes ... dying :-(\n");
@@ -191,8 +254,8 @@ void obj_fix(char *infile, char *outfile) {
                 sscanf(line, "vn %lf %lf %lf\n", 
                        &normals[vncount][0], &normals[vncount][1], 
                        &normals[vncount][2]);
-		fprintf(out, "vn %.4f %.4f %.4f\n", normals[vncount][0], 
-			normals[vncount][1], normals[vncount][2]);
+		// fprintf(out, "vn %.4f %.4f %.4f\n", normals[vncount][0], 
+		//	normals[vncount][1], normals[vncount][2]);
                 vncount++;
             } else {
                 printf("Read too many vertex normals ... dying :-(\n");
@@ -252,8 +315,20 @@ void obj_fix(char *infile, char *outfile) {
 		}
 	    }
 	} else if ( line[0] == 'f' ) {
-	    /* pass along the unoptimized faces verbatim */
-	    fprintf(out, "%s", line);
+	    if ( fcount < MAXNODES ) {
+		/* pass along the unoptimized faces verbatim */
+		sscanf(line, "f %d %d %d\n", &n1, &n2, &n3);
+		faces[fcount][0] = n1;
+		faces[fcount][1] = n2;
+		faces[fcount][2] = n3;
+
+		fcount++;
+	    } else {
+		printf("Read too many unoptimized faces ... dying :-(\n");
+                exit(-1);
+	    }
+ 
+	    // fprintf(out, "%s", line);
 	} else if ( line[0] == 'q' ) {
 	    /* continue a triangle strip */
 	    n1 = n2 = 0;
@@ -279,6 +354,18 @@ void obj_fix(char *infile, char *outfile) {
 	}
     }
 
+    /* reference point is the "center" */
+    refx = (xmin + xmax) / 2.0;
+    refy = (ymin + ymax) / 2.0;
+    refz = (zmin + zmax) / 2.0;
+
+    fprintf(out, "\n");
+    fprintf(out, "ref %.2f %.2f %.2f\n", refx, refy, refz);	
+
+    dump_nodes();
+    dump_normals();
+    dump_faces();
+
     fprintf(out, "winding ccw\n");
     dump_list(ccw_list, ccw_list_ptr);
 
@@ -291,9 +378,14 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.9  1998/04/18 04:01:03  curt
-/* Now use libMath rather than having local copies of math routines.
+/* Revision 1.10  1998/04/27 03:33:11  curt
+/* Code now calculates a center reference points and outputs everything
+/* relative to that.  This is useful in the rendering engine to keep everything
+/* close to (0, 0, 0) where we can avoid many GLfloat precision problems.
 /*
+ * Revision 1.9  1998/04/18 04:01:03  curt
+ * Now use libMath rather than having local copies of math routines.
+ *
  * Revision 1.8  1998/04/08 23:19:37  curt
  * Adopted Gnu automake/autoconf system.
  *

From de8f726b622773ab82298dca9cadb9bebaa33c8a Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 27 Apr 1998 15:59:24 +0000
Subject: [PATCH 078/283] Fixed an off by one error.

---
 FixObj/obj.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index fb15780da..fac87b623 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -76,7 +76,7 @@ void dump_nodes( void ) {
     int i;
 
     fprintf(out, "\n");
-    for ( i = 0; i < ncount; i++ ) {
+    for ( i = 1; i <= ncount; i++ ) {
 	fprintf(out, "v %.4lf %.4lf %.4lf\n",
 		nodes[i][0] - refx, nodes[i][1] - refy, nodes[i][2] - refz);
     }
@@ -88,7 +88,7 @@ void dump_normals( void ) {
     int i;
 
     fprintf(out, "\n");
-    for ( i = 0; i < vncount; i++ ) {
+    for ( i = 1; i <= vncount; i++ ) {
 	fprintf(out, "vn %.4lf %.4lf %.4lf\n", 
 		normals[i][0], normals[i][1], normals[i][2]);
     }
@@ -100,7 +100,7 @@ void dump_faces( void ) {
     int i;
 
     fprintf(out, "\n");
-    for ( i = 0; i < fcount; i++ ) {
+    for ( i = 1; i <= fcount; i++ ) {
 	fprintf(out, "f %d %d %d\n", 
 		faces[i][0], faces[i][1], faces[i][2]);
     }
@@ -199,10 +199,12 @@ void obj_fix(char *infile, char *outfile) {
     list_init(&ccw_list_ptr);
     list_init(&cw_list_ptr);
 
+    /* I start counting at one because that is how the triangle
+       program refers to nodes and normals */
     first = 1;
-    ncount = 0;
-    vncount = 0;
-    fcount = 0;
+    ncount = 1;
+    vncount = 1;
+    fcount = 1;
 
     printf("Reading file:  %s\n", infile);
 
@@ -378,11 +380,14 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.10  1998/04/27 03:33:11  curt
-/* Code now calculates a center reference points and outputs everything
-/* relative to that.  This is useful in the rendering engine to keep everything
-/* close to (0, 0, 0) where we can avoid many GLfloat precision problems.
+/* Revision 1.11  1998/04/27 15:59:24  curt
+/* Fixed an off by one error.
 /*
+ * Revision 1.10  1998/04/27 03:33:11  curt
+ * Code now calculates a center reference points and outputs everything
+ * relative to that.  This is useful in the rendering engine to keep everything
+ * close to (0, 0, 0) where we can avoid many GLfloat precision problems.
+ *
  * Revision 1.9  1998/04/18 04:01:03  curt
  * Now use libMath rather than having local copies of math routines.
  *

From 1d3e840fef0e4e488cbedaa3ef7f0879636d5afb Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 28 Apr 1998 01:23:25 +0000
Subject: [PATCH 079/283] Added a work around so that we can get past the
 "triangle" program hanging, by aborting and rerunning with that tile marked
 to use the "-i" option.

---
 Tools/process-dem.pl | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index c98be79a6..1fa022559 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -255,7 +255,20 @@ sub triangle_2 {
 	print $file;
 	chop($file);
 	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
-	    $command = "Triangle/triangle $subdir/$file";
+	    $base = $file;
+	    $base =~ s/\.node$//;
+	    print("Test for $subdir/$base.q\n");
+	    if ( -r "$subdir/$base.q" ) {
+
+		# if triangle hangs, we can create a filebase.q for
+		# the file it hung on.  Then, we test for that file
+		# here which causes the incremental algorithm to run
+		# (which shouldn't ever hang.)
+
+		$command = "Triangle/triangle -i $subdir/$file";
+	    } else {
+		$command = "Triangle/triangle $subdir/$file";
+	    }
 	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
@@ -375,6 +388,11 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.17  1998/04/28 01:23:25  curt
+# Added a work around so that we can get past the "triangle" program
+# hanging, by aborting and rerunning with that tile marked to use the "-i"
+# option.
+#
 # Revision 1.16  1998/04/18 03:57:53  curt
 # Added zlib library support.
 #

From 7989d27bf8f00cc99f5960c31d40d98397684480 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 28 Apr 1998 01:24:01 +0000
Subject: [PATCH 080/283] Updates ...

---
 AssemTris/Makefile.in    | 4 ++--
 DemRaw2ascii/Makefile.in | 4 ++--
 FixNode/Makefile.in      | 4 ++--
 FixObj/Makefile.in       | 4 ++--
 SplitTris/Makefile.in    | 4 ++--
 Tri2obj/Makefile.in      | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index 1e25fa0fb..e7bddf4dd 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.7  1998/04/26 13:37:11  curt
-# Removed DemInfo for now.
+# Revision 1.8  1998/04/28 01:24:01  curt
+# Updates ...
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index 51a6868a4..b0f93ab8b 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,8 +343,8 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.5  1998/04/26 13:37:12  curt
-# Removed DemInfo for now.
+# Revision 1.6  1998/04/28 01:24:08  curt
+# Updates ...
 #
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index 946aedb51..e36cfe0d8 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.7  1998/04/26 13:37:12  curt
-# Removed DemInfo for now.
+# Revision 1.8  1998/04/28 01:24:10  curt
+# Updates ...
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index f5f38a830..a1b855567 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.7  1998/04/26 13:37:13  curt
-# Removed DemInfo for now.
+# Revision 1.8  1998/04/28 01:24:12  curt
+# Updates ...
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index 29bc1bb36..da4c6b09c 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.7  1998/04/26 13:37:13  curt
-# Removed DemInfo for now.
+# Revision 1.8  1998/04/28 01:24:14  curt
+# Updates ...
 #
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index 0a3d34c60..a11019a07 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.7  1998/04/26 13:37:14  curt
-# Removed DemInfo for now.
+# Revision 1.8  1998/04/28 01:24:16  curt
+# Updates ...
 #
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.

From af753f2679868a1eacb263e8bfc3de13cfab8582 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 2 May 1998 01:49:21 +0000
Subject: [PATCH 081/283] Fixed a bug where the wrong variable was being
 initialized.

---
 DEM/dem.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 3aacf75c8..0e3351f18 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -375,7 +375,7 @@ void fgDEM::read_b_record( void ) {
 int fgDEM::parse( void ) {
     int i;
 
-    cur_row = 0;
+    cur_col = 0;
 
     read_a_record();
 
@@ -772,6 +772,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.6  1998/05/02 01:49:21  curt
+// Fixed a bug where the wrong variable was being initialized.
+//
 // Revision 1.5  1998/04/25 15:00:32  curt
 // Changed "r" to "rb" in gzopen() options.  This fixes bad behavior in win32.
 //

From 4b4aef9d3a0e92488b259bdcda8d38d100217903 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 2 May 1998 01:54:24 +0000
Subject: [PATCH 082/283] Converting to polar3d.h routines.

---
 AssemTris/Makefile.in    |  4 ++--
 DemRaw2ascii/Makefile.in |  4 ++--
 FixNode/Makefile.in      |  4 ++--
 FixObj/Makefile.in       |  4 ++--
 SplitTris/Makefile.in    |  4 ++--
 SplitTris/splittris.c    | 29 ++++++++++++++++++-----------
 Tri2obj/Makefile.in      |  4 ++--
 Tri2obj/tri2obj.c        | 29 ++++++++++++++++++-----------
 8 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index e7bddf4dd..a66482ce8 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.8  1998/04/28 01:24:01  curt
-# Updates ...
+# Revision 1.9  1998/05/02 01:54:24  curt
+# Converting to polar3d.h routines.
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index b0f93ab8b..c8a21b660 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,8 +343,8 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.6  1998/04/28 01:24:08  curt
-# Updates ...
+# Revision 1.7  1998/05/02 01:54:34  curt
+# Converting to polar3d.h routines.
 #
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index e36cfe0d8..9b90de5e2 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.8  1998/04/28 01:24:10  curt
-# Updates ...
+# Revision 1.9  1998/05/02 01:54:35  curt
+# Converting to polar3d.h routines.
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index a1b855567..e86c771d5 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.8  1998/04/28 01:24:12  curt
-# Updates ...
+# Revision 1.9  1998/05/02 01:54:36  curt
+# Converting to polar3d.h routines.
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index da4c6b09c..fdd82b9da 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.8  1998/04/28 01:24:14  curt
-# Updates ...
+# Revision 1.9  1998/05/02 01:54:36  curt
+# Converting to polar3d.h routines.
 #
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index c855c7525..c40000794 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -40,7 +40,7 @@
 
 #include <Math/fg_geodesy.h>
 #include <Math/mat3.h>
-#include <Math/polar.h>
+#include <Math/polar3d.h>
 
 int nodecount, tricount;
 double xmin, xmax, ymin, ymax;
@@ -49,15 +49,16 @@ static double nodes_orig[MAX_NODES][3];
 static int tris[MAX_TRIS][3];
 /* static int new_tris[MAX_TRIS][3]; */
 
-static struct fgCartesianPoint nodes_cart[MAX_NODES];
+static fgCartesianPoint3d nodes_cart[MAX_NODES];
 
 struct fgBUCKET ne_index, nw_index, sw_index, se_index;
 struct fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
-struct fgCartesianPoint geod_to_cart(double geod[3]) {
-    struct fgCartesianPoint p;
+fgCartesianPoint3d geod_to_cart(double geod[3]) {
+    fgCartesianPoint3d cp;
+    fgPolarPoint3d pp;
     double gc_lon, gc_lat, sl_radius;
 
     /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
@@ -69,17 +70,20 @@ struct fgCartesianPoint geod_to_cart(double geod[3]) {
     /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
 	   gc_lat, sl_radius+geod[2]); */
 
-    p = fgPolarToCart(gc_lon, gc_lat, sl_radius+geod[2]);
+    pp.lon = gc_lon;
+    pp.lat = gc_lat;
+    pp.radius = sl_radius+geod[2];
+    cp = fgPolarToCart3d(pp);
     
-    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", p.x, p.y, p.z); */
+    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z); */
 
-    return(p);
+    return(cp);
 }
 
 
 /* given three points defining a triangle, calculate the normal */
-void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2, 
-		 struct fgCartesianPoint p3, double normal[3])
+void calc_normal(fgCartesianPoint3d p1, fgCartesianPoint3d p2, 
+		 fgCartesianPoint3d p3, double normal[3])
 {
     double v1[3], v2[3];
     double temp;
@@ -612,9 +616,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.9  1998/04/18 04:01:20  curt
-/* Now use libMath rather than having local copies of math routines.
+/* Revision 1.10  1998/05/02 01:54:37  curt
+/* Converting to polar3d.h routines.
 /*
+ * Revision 1.9  1998/04/18 04:01:20  curt
+ * Now use libMath rather than having local copies of math routines.
+ *
  * Revision 1.8  1998/04/14 02:26:08  curt
  * Code reorganizations.  Added a Lib/ directory for more general libraries.
  *
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index a11019a07..221a2f247 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.8  1998/04/28 01:24:16  curt
-# Updates ...
+# Revision 1.9  1998/05/02 01:54:38  curt
+# Converting to polar3d.h routines.
 #
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 4b12310de..5c6390afe 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -38,12 +38,12 @@
 
 #include <Math/fg_geodesy.h>
 #include <Math/mat3.h>
-#include <Math/polar.h>
+#include <Math/polar3d.h>
 
 
 int nodecount, tricount;
 int normalcount = 0;
-static struct fgCartesianPoint nodes[MAX_NODES];
+static fgCartesianPoint3d nodes[MAX_NODES];
 static int tris[MAX_TRIS][3];
 
 static double normals[MAX_NODES][3];
@@ -54,8 +54,9 @@ struct fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
-struct fgCartesianPoint geod_to_cart(double geod[3]) {
-    struct fgCartesianPoint p;
+fgCartesianPoint3d geod_to_cart(double geod[3]) {
+    fgCartesianPoint3d cp;
+    fgPolarPoint3d pp;
     double gc_lon, gc_lat, sl_radius;
 
     /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
@@ -67,17 +68,20 @@ struct fgCartesianPoint geod_to_cart(double geod[3]) {
     /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
 	   gc_lat, sl_radius+geod[2]); */
 
-    p = fgPolarToCart(gc_lon, gc_lat, sl_radius+geod[2]);
+    pp.lon = gc_lon;
+    pp.lat = gc_lat;
+    pp.radius = sl_radius+geod[2];
+    cp = fgPolarToCart3d(pp);
     
-    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", p.x, p.y, p.z); */
+    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z); */
 
-    return(p);
+    return(cp);
 }
 
 
 /* given three points defining a triangle, calculate the normal */
-void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2, 
-		 struct fgCartesianPoint p3, double normal[3])
+void calc_normal(fgCartesianPoint3d p1, fgCartesianPoint3d p2, 
+		 fgCartesianPoint3d p3, double normal[3])
 {
     double v1[3], v2[3];
     double temp;
@@ -640,9 +644,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.14  1998/04/18 04:01:32  curt
-/* Now use libMath rather than having local copies of math routines.
+/* Revision 1.15  1998/05/02 01:54:39  curt
+/* Converting to polar3d.h routines.
 /*
+ * Revision 1.14  1998/04/18 04:01:32  curt
+ * Now use libMath rather than having local copies of math routines.
+ *
  * Revision 1.13  1998/04/14 02:26:11  curt
  * Code reorganizations.  Added a Lib/ directory for more general libraries.
  *

From a565fb559f84c34b277b20c1c81770fd466d7056 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 7 May 1998 23:16:05 +0000
Subject: [PATCH 083/283] ...

---
 AssemTris/Makefile.in    | 4 ++--
 DemRaw2ascii/Makefile.in | 4 ++--
 FixNode/Makefile.in      | 4 ++--
 FixObj/Makefile.in       | 4 ++--
 SplitTris/Makefile.in    | 4 ++--
 Tri2obj/Makefile.in      | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index a66482ce8..11e39ec54 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.9  1998/05/02 01:54:24  curt
-# Converting to polar3d.h routines.
+# Revision 1.10  1998/05/07 23:16:05  curt
+# ...
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index c8a21b660..688cca415 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,8 +343,8 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.7  1998/05/02 01:54:34  curt
-# Converting to polar3d.h routines.
+# Revision 1.8  1998/05/07 23:16:09  curt
+# ...
 #
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index 9b90de5e2..35a2bfee0 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.9  1998/05/02 01:54:35  curt
-# Converting to polar3d.h routines.
+# Revision 1.10  1998/05/07 23:16:10  curt
+# ...
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index e86c771d5..01b122aa0 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.9  1998/05/02 01:54:36  curt
-# Converting to polar3d.h routines.
+# Revision 1.10  1998/05/07 23:16:11  curt
+# ...
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index fdd82b9da..f40c4461c 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.9  1998/05/02 01:54:36  curt
-# Converting to polar3d.h routines.
+# Revision 1.10  1998/05/07 23:16:12  curt
+# ...
 #
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index 221a2f247..b58fcb695 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.9  1998/05/02 01:54:38  curt
-# Converting to polar3d.h routines.
+# Revision 1.10  1998/05/07 23:16:12  curt
+# ...
 #
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.

From 9ddf836a79e6352dca63dcb8571e0bd039c25364 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 13 May 1998 18:30:14 +0000
Subject: [PATCH 084/283] Updated ...

---
 AssemTris/Makefile.in    | 4 ++--
 DemRaw2ascii/Makefile.in | 4 ++--
 FixNode/Makefile.in      | 4 ++--
 FixObj/Makefile.in       | 4 ++--
 SplitTris/Makefile.in    | 4 ++--
 Tri2obj/Makefile.in      | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index 11e39ec54..dca0e004b 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.10  1998/05/07 23:16:05  curt
-# ...
+# Revision 1.11  1998/05/13 18:30:14  curt
+# Updated ...
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index 688cca415..111f6cf93 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,8 +343,8 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.8  1998/05/07 23:16:09  curt
-# ...
+# Revision 1.9  1998/05/13 18:30:18  curt
+# Updated ...
 #
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index 35a2bfee0..dbb737c63 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.10  1998/05/07 23:16:10  curt
-# ...
+# Revision 1.11  1998/05/13 18:30:19  curt
+# Updated ...
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index 01b122aa0..7b70d91da 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.10  1998/05/07 23:16:11  curt
-# ...
+# Revision 1.11  1998/05/13 18:30:20  curt
+# Updated ...
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index f40c4461c..47b374fd4 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.10  1998/05/07 23:16:12  curt
-# ...
+# Revision 1.11  1998/05/13 18:30:21  curt
+# Updated ...
 #
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index b58fcb695..23868cddf 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.10  1998/05/07 23:16:12  curt
-# ...
+# Revision 1.11  1998/05/13 18:30:22  curt
+# Updated ...
 #
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.

From e30c10841c7f9d92770372374b890f9b6ac2e336 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 16 May 1998 13:11:25 +0000
Subject: [PATCH 085/283] Fixed an off by one error in node, normal, and face
 counters.

---
 FixObj/Makefile.in |  4 ++--
 FixObj/obj.c       | 13 ++++++++-----
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index 7b70d91da..b42166e35 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.11  1998/05/13 18:30:20  curt
-# Updated ...
+# Revision 1.12  1998/05/16 13:11:25  curt
+# Fixed an off by one error in node, normal, and face counters.
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/FixObj/obj.c b/FixObj/obj.c
index fac87b623..b06c0d6b0 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -202,9 +202,9 @@ void obj_fix(char *infile, char *outfile) {
     /* I start counting at one because that is how the triangle
        program refers to nodes and normals */
     first = 1;
-    ncount = 1;
-    vncount = 1;
-    fcount = 1;
+    ncount = 0;
+    vncount = 0;
+    fcount = 0;
 
     printf("Reading file:  %s\n", infile);
 
@@ -380,9 +380,12 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.11  1998/04/27 15:59:24  curt
-/* Fixed an off by one error.
+/* Revision 1.12  1998/05/16 13:11:26  curt
+/* Fixed an off by one error in node, normal, and face counters.
 /*
+ * Revision 1.11  1998/04/27 15:59:24  curt
+ * Fixed an off by one error.
+ *
  * Revision 1.10  1998/04/27 03:33:11  curt
  * Code now calculates a center reference points and outputs everything
  * relative to that.  This is useful in the rendering engine to keep everything

From f00f7f02d40114984ad1b6fbbd5b2b8662c5608d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 20 May 1998 20:55:18 +0000
Subject: [PATCH 086/283] Fixed arbitrary polygon winding problem here so all
 tristrips are passed to runtime simulator with a consistant counter clockwise
 winding.

---
 FixObj/Makefile.in |   5 +-
 FixObj/obj.c       | 135 +++++++++++++++++++++++++++++++++++++++------
 2 files changed, 121 insertions(+), 19 deletions(-)

diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
index b42166e35..6f4875315 100644
--- a/FixObj/Makefile.in
+++ b/FixObj/Makefile.in
@@ -347,8 +347,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.12  1998/05/16 13:11:25  curt
-# Fixed an off by one error in node, normal, and face counters.
+# Revision 1.13  1998/05/20 20:55:18  curt
+# Fixed arbitrary polygon winding problem here so all tristrips are passed
+# to runtime simulator with a consistant counter clockwise winding.
 #
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
diff --git a/FixObj/obj.c b/FixObj/obj.c
index b06c0d6b0..77e0d8e13 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -71,13 +71,105 @@ void list_add(int *list, int *list_ptr, int node) {
 }
 
 
+/* fix the cw list and append to ccw_list */
+void fix_cw_list(int *list, int list_ptr) {
+    int i, j, len;
+
+    if ( list_ptr < 3 ) {
+	printf("List is empty ... skipping\n");
+	return;
+    }
+
+    printf("Fixing cw list, size = %d\n", list_ptr);
+
+    i = 0;
+    while ( i < list_ptr ) { 
+	/* do next strip */
+
+	/* find length */
+	len = 0;
+	/* scan rest of strip (until -1) */
+	while ( ((i+len) < list_ptr) && (list[i+len] != -1) ) { 
+	    // printf("len = %d item = %d\n", len, list[i+len] );
+	    len++;
+	}
+	// printf("          Final length = %d\n", len);
+
+	if ( (len % 2) != 0 ) {
+	    /* if length is odd, just reverse order of nodes to reverse
+	       winding */
+	    if ( ccw_list_ptr ) {
+		list_add(ccw_list, &ccw_list_ptr, -1);
+	    }
+	    for ( j = i + len - 1; j >= i; j-- ) {
+		// printf(" odd -> item = %d\n", list[j] );
+		list_add(ccw_list, &ccw_list_ptr, list[j]);
+	    }
+	} else {
+	    /* if length is even, reverse order of (n-1) nodes to
+	       reverse winding, and create an orphan triangle for the
+	       last "nth" node */
+	    if ( ccw_list_ptr ) {
+		list_add(ccw_list, &ccw_list_ptr, -1);
+	    }
+	    for ( j = i + len - 2; j >= i; j-- ) {
+		// printf(" even -> item = %d\n", list[j] );
+		list_add(ccw_list, &ccw_list_ptr, list[j]);
+	    }
+
+	    // printf(" even bonus -> item = %d\n", list[i + len - 1] );
+	    // printf(" even bonus -> item = %d\n", list[i + len - 2] );
+	    // printf(" even bonus -> item = %d\n", list[i + len - 3] );
+	    list_add(ccw_list, &ccw_list_ptr, -1);
+	    list_add(ccw_list, &ccw_list_ptr, list[i + len - 3]);
+	    list_add(ccw_list, &ccw_list_ptr, list[i + len - 2]);
+	    list_add(ccw_list, &ccw_list_ptr, list[i + len - 1]);
+	}
+
+	i += len + 1;
+    }
+}
+
+
+// Calculate distance between (0,0,0) and the specified point
+static double calc_dist(double x, double y, double z) {
+    return ( sqrt(x*x + y*y + z*z) );
+}
+
+
+void dump_global_bounds( void ) {
+    double dist, radius;
+    int i;
+
+    radius = 0.0;
+
+    fprintf(out, "\n");
+
+    for ( i = 1; i < ncount; i++ ) {
+
+	dist = calc_dist(nodes[i][0] - refx, nodes[i][1] - refy, 
+			 nodes[i][2] - refz);
+	// printf("node = %.2f %.2f %.2f dist = %.2f\n", 
+        //        nodes[i][0], nodes[i][1], nodes[i][2],
+	//        dist);
+
+	if ( dist > radius ) {
+	    radius = dist;
+	}
+
+    }
+
+    fprintf(out, "gb %.4f %.4f %.4f %.2f\n", refx, refy, refz, radius);
+}
+
+
 /* dump nodes */
 void dump_nodes( void ) {
     int i;
 
     fprintf(out, "\n");
-    for ( i = 1; i <= ncount; i++ ) {
-	fprintf(out, "v %.4lf %.4lf %.4lf\n",
+    for ( i = 1; i < ncount; i++ ) {
+	fprintf(out, "v %.4f %.4f %.4f\n",
 		nodes[i][0] - refx, nodes[i][1] - refy, nodes[i][2] - refz);
     }
 }
@@ -88,8 +180,8 @@ void dump_normals( void ) {
     int i;
 
     fprintf(out, "\n");
-    for ( i = 1; i <= vncount; i++ ) {
-	fprintf(out, "vn %.4lf %.4lf %.4lf\n", 
+    for ( i = 1; i < vncount; i++ ) {
+	fprintf(out, "vn %.4f %.4f %.4f\n", 
 		normals[i][0], normals[i][1], normals[i][2]);
     }
 }
@@ -100,7 +192,7 @@ void dump_faces( void ) {
     int i;
 
     fprintf(out, "\n");
-    for ( i = 1; i <= fcount; i++ ) {
+    for ( i = 1; i < fcount; i++ ) {
 	fprintf(out, "f %d %d %d\n", 
 		faces[i][0], faces[i][1], faces[i][2]);
     }
@@ -122,6 +214,12 @@ void dump_list(int *list, int list_ptr) {
     while ( i < list_ptr ) { 
 	/* do next strip */
 
+	if ( (i % 2) == 0 ) {
+	    fprintf(out, "\nusemtl desert1\n");
+	} else {
+	    fprintf(out, "\nusemtl desert2\n");
+	}
+
 	/* dump header */
 	fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]);
 	/* printf("t %d %d %d\n", list[i], list[i+1], list[i+2]); */
@@ -202,9 +300,9 @@ void obj_fix(char *infile, char *outfile) {
     /* I start counting at one because that is how the triangle
        program refers to nodes and normals */
     first = 1;
-    ncount = 0;
-    vncount = 0;
-    fcount = 0;
+    ncount = 1;
+    vncount = 1;
+    fcount = 1;
 
     printf("Reading file:  %s\n", infile);
 
@@ -361,28 +459,31 @@ void obj_fix(char *infile, char *outfile) {
     refy = (ymin + ymax) / 2.0;
     refz = (zmin + zmax) / 2.0;
 
-    fprintf(out, "\n");
-    fprintf(out, "ref %.2f %.2f %.2f\n", refx, refy, refz);	
+    /* convert the cw_list to ccw add append to ccw_list */
+    fix_cw_list(cw_list, cw_list_ptr);
 
+    dump_global_bounds();
     dump_nodes();
     dump_normals();
-    dump_faces();
+    if ( fcount > 1 ) {
+	dump_faces();
+    }
 
-    fprintf(out, "winding ccw\n");
     dump_list(ccw_list, ccw_list_ptr);
 
-    fprintf(out, "winding cw\n");
-    dump_list(cw_list, cw_list_ptr);
-
     fclose(in);
     fclose(out);
 }
 
 
 /* $Log$
-/* Revision 1.12  1998/05/16 13:11:26  curt
-/* Fixed an off by one error in node, normal, and face counters.
+/* Revision 1.13  1998/05/20 20:55:19  curt
+/* Fixed arbitrary polygon winding problem here so all tristrips are passed
+/* to runtime simulator with a consistant counter clockwise winding.
 /*
+ * Revision 1.12  1998/05/16 13:11:26  curt
+ * Fixed an off by one error in node, normal, and face counters.
+ *
  * Revision 1.11  1998/04/27 15:59:24  curt
  * Fixed an off by one error.
  *

From de4c486c168636eefac84c36aeeb2671d977ae5f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 20 May 1998 20:55:40 +0000
Subject: [PATCH 087/283] Makefile tweaks

---
 AssemTris/Makefile.in    |  4 ++--
 DemRaw2ascii/Makefile.in |  4 ++--
 FixNode/Makefile.in      |  4 ++--
 SplitTris/Makefile.in    |  4 ++--
 Tools/process-dem.pl     | 23 +++++++++++++----------
 Tri2obj/Makefile.in      |  4 ++--
 6 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
index dca0e004b..73b4d0299 100644
--- a/AssemTris/Makefile.in
+++ b/AssemTris/Makefile.in
@@ -344,8 +344,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.11  1998/05/13 18:30:14  curt
-# Updated ...
+# Revision 1.12  1998/05/20 20:55:44  curt
+# Makefile tweaks
 #
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
index 111f6cf93..3ffd6cec4 100644
--- a/DemRaw2ascii/Makefile.in
+++ b/DemRaw2ascii/Makefile.in
@@ -343,8 +343,8 @@ INCLUDES +=
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.9  1998/05/13 18:30:18  curt
-# Updated ...
+# Revision 1.10  1998/05/20 20:55:46  curt
+# Makefile tweaks
 #
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
index dbb737c63..909e93f10 100644
--- a/FixNode/Makefile.in
+++ b/FixNode/Makefile.in
@@ -371,8 +371,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.11  1998/05/13 18:30:19  curt
-# Updated ...
+# Revision 1.12  1998/05/20 20:55:47  curt
+# Makefile tweaks
 #
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
index 47b374fd4..5f59333c3 100644
--- a/SplitTris/Makefile.in
+++ b/SplitTris/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.11  1998/05/13 18:30:21  curt
-# Updated ...
+# Revision 1.12  1998/05/20 20:55:49  curt
+# Makefile tweaks
 #
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 1fa022559..fe7cc3284 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -28,15 +28,15 @@
 
 $| = 1;                         # flush buffers after every write
 
-$do_dem2node =     1;
-$do_triangle_1 = 1;
-$do_fixnode =    1;
-$do_splittris =  1;
-$do_assemtris =  1;
-$do_triangle_2 = 1;
+$do_dem2node =     0;
+$do_triangle_1 = 0;
+$do_fixnode =    0;
+$do_splittris =  0;
+$do_assemtris =  0;
+$do_triangle_2 = 0;
 
-$do_tri2obj =    1;
-$do_strips =     1;
+$do_tri2obj =    0;
+$do_strips =     0;
 $do_fixobj =     1;
 
 
@@ -68,7 +68,7 @@ while ( $dem_file = shift(@ARGV) ) {
     if ( $do_dem2node ) {
 	dem2node() ;
     } else {
-	$subdir = "../Scenery/w100n040/w093n045";
+	$subdir = "../Scenery/w120n030/w111n033";
 	print "WARNING:  Hardcoding subdir = $subdir\n";
     }
 
@@ -380,7 +380,7 @@ sub fixobj {
 	    }
 	    close(OUT);
 
-	    unlink("$subdir/$file");
+	    # unlink("$subdir/$file");
 	}
     }
 }
@@ -388,6 +388,9 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.18  1998/05/20 20:55:40  curt
+# Makefile tweaks
+#
 # Revision 1.17  1998/04/28 01:23:25  curt
 # Added a work around so that we can get past the "triangle" program
 # hanging, by aborting and rerunning with that tile marked to use the "-i"
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
index 23868cddf..97fe30a01 100644
--- a/Tri2obj/Makefile.in
+++ b/Tri2obj/Makefile.in
@@ -349,8 +349,8 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
-# Revision 1.11  1998/05/13 18:30:22  curt
-# Updated ...
+# Revision 1.12  1998/05/20 20:55:50  curt
+# Makefile tweaks
 #
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.

From 8da60b798dfd490df4b7124c48c2271281b13428 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 23 May 1998 14:18:25 +0000
Subject: [PATCH 088/283] Derived file "Makefile.in" removed from version
 control.

---
 AssemTris/Makefile.in    | 365 -----------------------------------
 DEM/Makefile.in          | 339 --------------------------------
 DemRaw2ascii/Makefile.in | 358 ----------------------------------
 FixNode/Makefile.in      | 403 ---------------------------------------
 FixObj/Makefile.in       | 375 ------------------------------------
 SplitTris/Makefile.in    | 379 ------------------------------------
 Stripe_u/Makefile.in     | 349 ---------------------------------
 Tri2obj/Makefile.in      | 376 ------------------------------------
 Triangle/Makefile.in     | 333 --------------------------------
 9 files changed, 3277 deletions(-)
 delete mode 100644 AssemTris/Makefile.in
 delete mode 100644 DEM/Makefile.in
 delete mode 100644 DemRaw2ascii/Makefile.in
 delete mode 100644 FixNode/Makefile.in
 delete mode 100644 FixObj/Makefile.in
 delete mode 100644 SplitTris/Makefile.in
 delete mode 100644 Stripe_u/Makefile.in
 delete mode 100644 Tri2obj/Makefile.in
 delete mode 100644 Triangle/Makefile.in

diff --git a/AssemTris/Makefile.in b/AssemTris/Makefile.in
deleted file mode 100644
index 73b4d0299..000000000
--- a/AssemTris/Makefile.in
+++ /dev/null
@@ -1,365 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started January 1998.
-#
-# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = assemtris
-
-assemtris_SOURCES = assemtris.c assemtris.h
-
-assemtris_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-assemtris_OBJECTS =  assemtris.o
-assemtris_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
-assemtris_LDFLAGS = 
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/assemtris.P
-SOURCES = $(assemtris_SOURCES)
-OBJECTS = $(assemtris_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/AssemTris/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-assemtris: $(assemtris_OBJECTS) $(assemtris_DEPENDENCIES)
-	@rm -f assemtris
-	$(LINK) $(assemtris_LDFLAGS) $(assemtris_OBJECTS) $(assemtris_LDADD) $(LIBS)
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/AssemTris
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/AssemTris/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.12  1998/05/20 20:55:44  curt
-# Makefile tweaks
-#
-# Revision 1.2  1998/04/14 02:25:59  curt
-# Code reorganizations.  Added a Lib/ directory for more general libraries.
-#
-# Revision 1.1  1998/04/08 22:54:57  curt
-# Adopted Gnu automake/autoconf system.
-#
-# Revision 1.2  1998/01/21 02:55:46  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.1  1998/01/15 02:45:25  curt
-# Initial revision.
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/DEM/Makefile.in b/DEM/Makefile.in
deleted file mode 100644
index bd39aee3c..000000000
--- a/DEM/Makefile.in
+++ /dev/null
@@ -1,339 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-libdir  = ${exec_prefix}/lib
-
-lib_LTLIBRARIES = libDEM.la
-
-libDEM_la_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
-
-# We can't build this with "-O2" (optimization) since this causes a seg fault
-# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
-# setting it to "-g"
-CXXFLAGS = -g
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-LTLIBRARIES =  $(lib_LTLIBRARIES)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-libDEM_la_LDFLAGS = 
-libDEM_la_LIBADD = 
-libDEM_la_OBJECTS =  dem.lo leastsqs.lo
-CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/dem.P .deps/leastsqs.P
-CXXMKDEP = $(CXX) -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-SOURCES = $(libDEM_la_SOURCES)
-OBJECTS = $(libDEM_la_OBJECTS)
-
-all: Makefile $(LTLIBRARIES)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .cxx .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Lib/DEM/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-libLTLIBRARIES:
-
-clean-libLTLIBRARIES:
-	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
-
-distclean-libLTLIBRARIES:
-
-maintainer-clean-libLTLIBRARIES:
-
-install-libLTLIBRARIES: $(lib_LTLIBRARIES)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(libdir)
-	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo "$(LIBTOOL)  --mode=install $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \
-	  else :; fi; \
-	done
-
-uninstall-libLTLIBRARIES:
-	@$(NORMAL_UNINSTALL)
-	list='$(lib_LTLIBRARIES)'; for p in $$list; do \
-	  $(LIBTOOL)  --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-libDEM.la: $(libDEM_la_OBJECTS) $(libDEM_la_DEPENDENCIES)
-	$(CXXLINK) -rpath $(libdir) $(libDEM_la_LDFLAGS) $(libDEM_la_OBJECTS) $(libDEM_la_LIBADD) $(LIBS)
-.cxx.o:
-	$(CXXCOMPILE) -c $<
-.cxx.lo:
-	$(LTCXXCOMPILE) -c $<
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Lib/DEM
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Lib/DEM/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-
-%.o: %.cxx
-	@echo '$(CXXCOMPILE) -c $<'; \
-	$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.cxx
-	@echo '$(LTCXXCOMPILE) -c $<'; \
-	$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-libLTLIBRARIES
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-libLTLIBRARIES
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(libdir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-libLTLIBRARIES mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-libLTLIBRARIES distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-libLTLIBRARIES \
-		maintainer-clean-compile maintainer-clean-libtool \
-		maintainer-clean-tags maintainer-clean-depend \
-		maintainer-clean-generic distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \
-clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \
-uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \
-distclean-compile clean-compile maintainer-clean-compile \
-mostlyclean-libtool distclean-libtool clean-libtool \
-maintainer-clean-libtool tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir mostlyclean-depend \
-distclean-depend clean-depend maintainer-clean-depend info dvi \
-installcheck install-exec install-data install uninstall all \
-installdirs mostlyclean-generic distclean-generic clean-generic \
-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
-
-
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/DemRaw2ascii/Makefile.in b/DemRaw2ascii/Makefile.in
deleted file mode 100644
index 3ffd6cec4..000000000
--- a/DemRaw2ascii/Makefile.in
+++ /dev/null
@@ -1,358 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started February 1998.
-#
-# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = raw2ascii
-
-raw2ascii_SOURCES = main.c rawdem.c rawdem.h
-
-raw2ascii_LDADD = 
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-raw2ascii_OBJECTS =  main.o rawdem.o
-raw2ascii_DEPENDENCIES = 
-raw2ascii_LDFLAGS = 
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/main.P .deps/rawdem.P
-SOURCES = $(raw2ascii_SOURCES)
-OBJECTS = $(raw2ascii_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/DemRaw2ascii/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-raw2ascii: $(raw2ascii_OBJECTS) $(raw2ascii_DEPENDENCIES)
-	@rm -f raw2ascii
-	$(LINK) $(raw2ascii_LDFLAGS) $(raw2ascii_OBJECTS) $(raw2ascii_LDADD) $(LIBS)
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/DemRaw2ascii
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/DemRaw2ascii/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-INCLUDES += 
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.10  1998/05/20 20:55:46  curt
-# Makefile tweaks
-#
-# Revision 1.2  1998/04/24 00:44:04  curt
-# Added zlib support.
-#
-# Revision 1.1  1998/04/18 03:59:44  curt
-# Incorporated into gnu automake/autoconf system.
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/FixNode/Makefile.in b/FixNode/Makefile.in
deleted file mode 100644
index 909e93f10..000000000
--- a/FixNode/Makefile.in
+++ /dev/null
@@ -1,403 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started October 1997.
-#
-# Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = fixnode
-
-fixnode_SOURCES = \
-	fixnode.cxx fixnode.hxx \
-	main.cxx \
-	triload.cxx triload.hxx
-
-fixnode_LDADD = \
-	$(top_builddir)/Lib/DEM/libDEM.la \
-        $(top_builddir)/Lib/Bucket/libBucket.la \
-        $(top_builddir)/Lib/zlib/libz.la
-
-# We can't build this with "-O2" (optimization) since this causes a seg fault
-# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
-# setting it to "-g"
-CXXFLAGS = -g
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-fixnode_OBJECTS =  fixnode.o main.o triload.o
-fixnode_DEPENDENCIES =  $(top_builddir)/Lib/DEM/libDEM.la \
-$(top_builddir)/Lib/Bucket/libBucket.la \
-$(top_builddir)/Lib/zlib/libz.la
-fixnode_LDFLAGS = 
-CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/fixnode.P .deps/main.P .deps/triload.P
-CXXMKDEP = $(CXX) -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-SOURCES = $(fixnode_SOURCES)
-OBJECTS = $(fixnode_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .cxx .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/FixNode/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-fixnode: $(fixnode_OBJECTS) $(fixnode_DEPENDENCIES)
-	@rm -f fixnode
-	$(CXXLINK) $(fixnode_LDFLAGS) $(fixnode_OBJECTS) $(fixnode_LDADD) $(LIBS)
-.cxx.o:
-	$(CXXCOMPILE) -c $<
-.cxx.lo:
-	$(LTCXXCOMPILE) -c $<
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/FixNode
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/FixNode/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-
-%.o: %.cxx
-	@echo '$(CXXCOMPILE) -c $<'; \
-	$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.cxx
-	@echo '$(LTCXXCOMPILE) -c $<'; \
-	$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.12  1998/05/20 20:55:47  curt
-# Makefile tweaks
-#
-# Revision 1.3  1998/04/18 04:02:54  curt
-# Added zlib support in placed and other misc. tweaks.
-#
-# Revision 1.2  1998/04/14 02:26:02  curt
-# Code reorganizations.  Added a Lib/ directory for more general libraries.
-#
-# Revision 1.1  1998/04/08 23:05:54  curt
-# Adopted Gnu automake/autoconf system.
-#
-# Revision 1.4  1998/04/06 21:09:44  curt
-# Additional win32 support.
-# Fixed a bad bug in dem file parsing that was causing the output to be
-# flipped about x = y.
-#
-# Revision 1.3  1998/03/19 02:50:19  curt
-# Updated to support -lDEM class.
-#
-# Revision 1.2  1998/01/21 02:55:50  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.1  1997/11/27 00:17:32  curt
-# Initial revision.
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/FixObj/Makefile.in b/FixObj/Makefile.in
deleted file mode 100644
index 6f4875315..000000000
--- a/FixObj/Makefile.in
+++ /dev/null
@@ -1,375 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started October 1997.
-#
-# Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = fixobj
-
-fixobj_SOURCES = main.c obj.c obj.h
-
-fixobj_LDADD = \
-	$(top_builddir)/Lib/Math/libMath.la \
-	$(top_builddir)/Lib/Debug/libDebug.la \
-	$(top_builddir)/Lib/zlib/libz.la
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-fixobj_OBJECTS =  main.o obj.o
-fixobj_DEPENDENCIES =  $(top_builddir)/Lib/Math/libMath.la \
-$(top_builddir)/Lib/Debug/libDebug.la $(top_builddir)/Lib/zlib/libz.la
-fixobj_LDFLAGS = 
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/main.P .deps/obj.P
-SOURCES = $(fixobj_SOURCES)
-OBJECTS = $(fixobj_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/FixObj/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-fixobj: $(fixobj_OBJECTS) $(fixobj_DEPENDENCIES)
-	@rm -f fixobj
-	$(LINK) $(fixobj_LDFLAGS) $(fixobj_OBJECTS) $(fixobj_LDADD) $(LIBS)
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/FixObj
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/FixObj/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.13  1998/05/20 20:55:18  curt
-# Fixed arbitrary polygon winding problem here so all tristrips are passed
-# to runtime simulator with a consistant counter clockwise winding.
-#
-# Revision 1.4  1998/04/24 00:44:05  curt
-# Added zlib support.
-#
-# Revision 1.3  1998/04/18 04:01:02  curt
-# Now use libMath rather than having local copies of math routines.
-#
-# Revision 1.2  1998/04/14 02:26:05  curt
-# Code reorganizations.  Added a Lib/ directory for more general libraries.
-#
-# Revision 1.1  1998/04/08 23:19:35  curt
-# Adopted Gnu automake/autoconf system.
-#
-# Revision 1.2  1998/01/21 02:55:53  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.1  1997/12/08 19:28:54  curt
-# Initial revision.
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/SplitTris/Makefile.in b/SplitTris/Makefile.in
deleted file mode 100644
index 5f59333c3..000000000
--- a/SplitTris/Makefile.in
+++ /dev/null
@@ -1,379 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started January 1998.
-#
-# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = splittris
-
-splittris_SOURCES = splittris.c splittris.h
-
-splittris_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la \
-        $(top_builddir)/Lib/Debug/libDebug.la \
-        $(top_builddir)/Lib/zlib/libz.la
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-splittris_OBJECTS =  splittris.o
-splittris_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la \
-$(top_builddir)/Lib/Math/libMath.la \
-$(top_builddir)/Lib/Debug/libDebug.la $(top_builddir)/Lib/zlib/libz.la
-splittris_LDFLAGS = 
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/splittris.P
-SOURCES = $(splittris_SOURCES)
-OBJECTS = $(splittris_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/SplitTris/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-splittris: $(splittris_OBJECTS) $(splittris_DEPENDENCIES)
-	@rm -f splittris
-	$(LINK) $(splittris_LDFLAGS) $(splittris_OBJECTS) $(splittris_LDADD) $(LIBS)
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/SplitTris
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/SplitTris/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.12  1998/05/20 20:55:49  curt
-# Makefile tweaks
-#
-# Revision 1.4  1998/04/24 00:44:06  curt
-# Added zlib support.
-#
-# Revision 1.3  1998/04/18 04:01:17  curt
-# Now use libMath rather than having local copies of math routines.
-#
-# Revision 1.2  1998/04/14 02:26:06  curt
-# Code reorganizations.  Added a Lib/ directory for more general libraries.
-#
-# Revision 1.1  1998/04/08 23:21:10  curt
-# Adopted Gnu automake/autoconf system.
-#
-# Revision 1.3  1998/01/21 02:55:55  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.2  1998/01/14 15:54:42  curt
-# Initial revision completed.
-#
-# Revision 1.1  1998/01/14 02:11:30  curt
-# Initial revision.
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/Stripe_u/Makefile.in b/Stripe_u/Makefile.in
deleted file mode 100644
index db9d8599e..000000000
--- a/Stripe_u/Makefile.in
+++ /dev/null
@@ -1,349 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = strips
-
-strips_SOURCES = \
-	add.c add.h \
-	bands.c \
-	common.c common.h \
-	define.h \
-	extend.h \
-	free.c free.h \
-	global.h \
-	glove.h \
-	init.c init.h \
-	local.c local.h \
-	my_global.h \
-	newpolve.c \
-	options.c options.h \
-	output.c output.h \
-	outputex.c outputex.h \
-	partial.c partial.h \
-	polverts.h polvertsex.h \
-	queue.c queue.h \
-	sgi_triang.c sgi_triangex.c \
-	struct.c struct.h \
-	structex.c \
-	sturcts.h sturctsex.h \
-	ties.c ties.h \
-	triangulate.h triangulatex.h \
-	util.c util.h
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-strips_OBJECTS =  add.o bands.o common.o free.o init.o local.o \
-newpolve.o options.o output.o outputex.o partial.o queue.o sgi_triang.o \
-sgi_triangex.o struct.o structex.o ties.o util.o
-strips_LDADD = $(LDADD)
-strips_DEPENDENCIES = 
-strips_LDFLAGS = 
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/add.P .deps/bands.P .deps/common.P .deps/free.P \
-.deps/init.P .deps/local.P .deps/newpolve.P .deps/options.P \
-.deps/output.P .deps/outputex.P .deps/partial.P .deps/queue.P \
-.deps/sgi_triang.P .deps/sgi_triangex.P .deps/struct.P .deps/structex.P \
-.deps/ties.P .deps/util.P
-SOURCES = $(strips_SOURCES)
-OBJECTS = $(strips_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Stripe_u/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-strips: $(strips_OBJECTS) $(strips_DEPENDENCIES)
-	@rm -f strips
-	$(LINK) $(strips_LDFLAGS) $(strips_OBJECTS) $(strips_LDADD) $(LIBS)
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/Stripe_u
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Stripe_u/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/Tri2obj/Makefile.in b/Tri2obj/Makefile.in
deleted file mode 100644
index 97fe30a01..000000000
--- a/Tri2obj/Makefile.in
+++ /dev/null
@@ -1,376 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started January 1998.
-#
-# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = tri2obj
-
-tri2obj_SOURCES = tri2obj.c tri2obj.h
-
-tri2obj_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la \
-        $(top_builddir)/Lib/Debug/libDebug.la \
-        $(top_builddir)/Lib/zlib/libz.la
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-tri2obj_OBJECTS =  tri2obj.o
-tri2obj_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la \
-$(top_builddir)/Lib/Math/libMath.la \
-$(top_builddir)/Lib/Debug/libDebug.la $(top_builddir)/Lib/zlib/libz.la
-tri2obj_LDFLAGS = 
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/tri2obj.P
-SOURCES = $(tri2obj_SOURCES)
-OBJECTS = $(tri2obj_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Tri2obj/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-tri2obj: $(tri2obj_OBJECTS) $(tri2obj_DEPENDENCIES)
-	@rm -f tri2obj
-	$(LINK) $(tri2obj_LDFLAGS) $(tri2obj_OBJECTS) $(tri2obj_LDADD) $(LIBS)
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/Tri2obj
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Tri2obj/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.12  1998/05/20 20:55:50  curt
-# Makefile tweaks
-#
-# Revision 1.4  1998/04/24 00:44:07  curt
-# Added zlib support.
-#
-# Revision 1.3  1998/04/18 04:01:29  curt
-# Now use libMath rather than having local copies of math routines.
-#
-# Revision 1.2  1998/04/14 02:26:09  curt
-# Code reorganizations.  Added a Lib/ directory for more general libraries.
-#
-# Revision 1.1  1998/04/08 23:22:13  curt
-# Adopted Gnu automake/autoconf system.
-#
-# Revision 1.2  1998/01/21 02:55:46  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.1  1998/01/15 02:45:25  curt
-# Initial revision.
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/Triangle/Makefile.in b/Triangle/Makefile.in
deleted file mode 100644
index e5a0a2ccf..000000000
--- a/Triangle/Makefile.in
+++ /dev/null
@@ -1,333 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-# DEFS 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 DEFS line is:
-#
-#   DEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ../..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-bin_PROGRAMS = triangle # showme
-
-triangle_SOURCES = triangle.c triangle.h
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../../Include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-triangle_OBJECTS =  triangle.o
-triangle_LDADD = $(LDADD)
-triangle_DEPENDENCIES = 
-triangle_LDFLAGS = 
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
-LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  README Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/triangle.P
-SOURCES = $(triangle_SOURCES)
-OBJECTS = $(triangle_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .s
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Triangle/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-triangle: $(triangle_OBJECTS) $(triangle_DEPENDENCIES)
-	@rm -f triangle
-	$(LINK) $(triangle_LDFLAGS) $(triangle_OBJECTS) $(triangle_LDADD) $(LIBS)
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/Triangle
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Triangle/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-DEFS += 
-
-# showme_SOURCES = showme.c
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:

From f0a9195ceccf359c1a11b550bbd005a5d78124c0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 23 May 1998 14:31:49 +0000
Subject: [PATCH 089/283] Removed derived files "Makefile.in" from version
 control.

---
 Tools/Makefile.in | 297 ----------------------------------------------
 1 file changed, 297 deletions(-)
 delete mode 100644 Tools/Makefile.in

diff --git a/Tools/Makefile.in b/Tools/Makefile.in
deleted file mode 100644
index 352c4f3de..000000000
--- a/Tools/Makefile.in
+++ /dev/null
@@ -1,297 +0,0 @@
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = ..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-LD = @LD@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-NM = @NM@
-PACKAGE = @PACKAGE@
-RANLIB = @RANLIB@
-VERSION = @VERSION@
-
-EXTRA_DIST = process-dem.pl
-
-SUBDIRS = \
-	AssemTris \
-	Dem2node \
-	DemRaw2ascii \
-	FixNode \
-	FixObj \
-	SplitTris \
-	Stripe_u \
-	Tri2obj \
-	Triangle
-
-bin_SCRIPTS = process-dem.pl
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../Include/config.h
-CONFIG_CLEAN_FILES = 
-SCRIPTS =  $(bin_SCRIPTS)
-
-DIST_COMMON =  README Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-all: all-recursive all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-install-binSCRIPTS: $(bin_SCRIPTS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_SCRIPTS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else if test -f $(srcdir)/$$p; then \
-	    echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; fi; \
-	done
-
-uninstall-binSCRIPTS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_SCRIPTS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run `make' without going through this Makefile.
-# To change the values of `make' variables: instead of editing Makefiles,
-# (1) if the variable is set in `config.status', edit `config.status'
-#     (which will cause the Makefiles to be regenerated when you run `make');
-# (2) otherwise, pass the desired values on the `make' command line.
-
-@SET_MAKE@
-
-all-recursive install-data-recursive install-exec-recursive \
-installdirs-recursive install-recursive uninstall-recursive  \
-check-recursive installcheck-recursive info-recursive dvi-recursive:
-	@set fnord $(MAKEFLAGS); amf=$$2; \
-	list='$(SUBDIRS)'; for subdir in $$list; do \
-	  target=`echo $@ | sed s/-recursive//`; \
-	  echo "Making $$target in $$subdir"; \
-	  (cd $$subdir && $(MAKE) $$target) \
-	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
-	done && test -z "$$fail"
-
-mostlyclean-recursive clean-recursive distclean-recursive \
-maintainer-clean-recursive:
-	@set fnord $(MAKEFLAGS); amf=$$2; \
-	rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
-	  rev="$$subdir $$rev"; \
-	done; \
-	for subdir in $$rev; do \
-	  target=`echo $@ | sed s/-recursive//`; \
-	  echo "Making $$target in $$subdir"; \
-	  (cd $$subdir && $(MAKE) $$target) \
-	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
-	done && test -z "$$fail"
-tags-recursive:
-	list='$(SUBDIRS)'; for subdir in $$list; do \
-	  (cd $$subdir && $(MAKE) tags); \
-	done
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SUBDIRS)'; for subdir in $$list; do \
-	  test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
-	done; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-	for subdir in $(SUBDIRS); do \
-	  test -d $(distdir)/$$subdir \
-	  || mkdir $(distdir)/$$subdir \
-	  || exit 1; \
-	  chmod 777 $(distdir)/$$subdir; \
-	  (cd $$subdir && $(MAKE) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
-	    || exit 1; \
-	done
-info: info-recursive
-dvi: dvi-recursive
-check: all-am
-	$(MAKE) check-recursive
-installcheck: installcheck-recursive
-all-am: Makefile $(SCRIPTS)
-
-install-exec-am: install-binSCRIPTS
-
-uninstall-am: uninstall-binSCRIPTS
-
-install-exec: install-exec-recursive install-exec-am
-	@$(NORMAL_INSTALL)
-
-install-data: install-data-recursive
-	@$(NORMAL_INSTALL)
-
-install: install-recursive install-exec-am
-	@:
-
-uninstall: uninstall-recursive uninstall-am
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs: installdirs-recursive
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean-am:  mostlyclean-tags mostlyclean-generic
-
-clean-am:  clean-tags clean-generic mostlyclean-am
-
-distclean-am:  distclean-tags distclean-generic clean-am
-
-maintainer-clean-am:  maintainer-clean-tags maintainer-clean-generic \
-		distclean-am
-
-mostlyclean:  mostlyclean-recursive mostlyclean-am
-
-clean:  clean-recursive clean-am
-
-distclean:  distclean-recursive distclean-am
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-recursive maintainer-clean-am
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: uninstall-binSCRIPTS install-binSCRIPTS install-data-recursive \
-uninstall-data-recursive install-exec-recursive \
-uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
-all-recursive check-recursive installcheck-recursive info-recursive \
-dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
-maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir info dvi \
-installcheck all-am install-exec-am uninstall-am install-exec \
-install-data install uninstall all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:

From e49deb790eb7008e2c587fd53691525216606cbb Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 23 May 1998 15:19:49 +0000
Subject: [PATCH 090/283] Output more digits after the decimal place.

---
 FixObj/obj.c      | 15 +++++++++------
 Tri2obj/tri2obj.c |  9 ++++++---
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index 77e0d8e13..cf7648604 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -159,7 +159,7 @@ void dump_global_bounds( void ) {
 
     }
 
-    fprintf(out, "gb %.4f %.4f %.4f %.2f\n", refx, refy, refz, radius);
+    fprintf(out, "gb %.5f %.5f %.5f %.2f\n", refx, refy, refz, radius);
 }
 
 
@@ -169,7 +169,7 @@ void dump_nodes( void ) {
 
     fprintf(out, "\n");
     for ( i = 1; i < ncount; i++ ) {
-	fprintf(out, "v %.4f %.4f %.4f\n",
+	fprintf(out, "v %.5f %.5f %.5f\n",
 		nodes[i][0] - refx, nodes[i][1] - refy, nodes[i][2] - refz);
     }
 }
@@ -181,7 +181,7 @@ void dump_normals( void ) {
 
     fprintf(out, "\n");
     for ( i = 1; i < vncount; i++ ) {
-	fprintf(out, "vn %.4f %.4f %.4f\n", 
+	fprintf(out, "vn %.5f %.5f %.5f\n", 
 		normals[i][0], normals[i][1], normals[i][2]);
     }
 }
@@ -477,10 +477,13 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.13  1998/05/20 20:55:19  curt
-/* Fixed arbitrary polygon winding problem here so all tristrips are passed
-/* to runtime simulator with a consistant counter clockwise winding.
+/* Revision 1.14  1998/05/23 15:19:49  curt
+/* Output more digits after the decimal place.
 /*
+ * Revision 1.13  1998/05/20 20:55:19  curt
+ * Fixed arbitrary polygon winding problem here so all tristrips are passed
+ * to runtime simulator with a consistant counter clockwise winding.
+ *
  * Revision 1.12  1998/05/16 13:11:26  curt
  * Fixed an off by one error in node, normal, and face counters.
  *
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 5c6390afe..071c0e359 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -517,7 +517,7 @@ void dump_obj(char *basename) {
     /* dump vertices */
     printf("  writing vertices\n");
     for ( i = 1; i <= nodecount; i++ ) {
-	fprintf(obj, "v %.2f %.2f %.2f\n", 
+	fprintf(obj, "v %.6f %.6f %.6f\n", 
 		nodes[i].x, nodes[i].y, nodes[i].z);
     }
 
@@ -644,9 +644,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.15  1998/05/02 01:54:39  curt
-/* Converting to polar3d.h routines.
+/* Revision 1.16  1998/05/23 15:20:41  curt
+/* Output more digits after the decimal place.
 /*
+ * Revision 1.15  1998/05/02 01:54:39  curt
+ * Converting to polar3d.h routines.
+ *
  * Revision 1.14  1998/04/18 04:01:32  curt
  * Now use libMath rather than having local copies of math routines.
  *

From 7f250ecb901135d08b347e132ce6e51545c275be Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 24 May 1998 02:47:47 +0000
Subject: [PATCH 091/283] For each strip, specify a default material property
 and calculate a center and bounding sphere.

---
 FixObj/obj.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 97 insertions(+), 8 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index cf7648604..99245a90d 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -159,7 +159,7 @@ void dump_global_bounds( void ) {
 
     }
 
-    fprintf(out, "gb %.5f %.5f %.5f %.2f\n", refx, refy, refz, radius);
+    fprintf(out, "gbs %.5f %.5f %.5f %.2f\n", refx, refy, refz, radius);
 }
 
 
@@ -189,19 +189,59 @@ void dump_normals( void ) {
 
 /* dump faces */
 void dump_faces( void ) {
-    int i;
+    int i, n1, n2, n3;
+    double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
 
     fprintf(out, "\n");
     for ( i = 1; i < fcount; i++ ) {
-	fprintf(out, "f %d %d %d\n", 
-		faces[i][0], faces[i][1], faces[i][2]);
+	n1 = faces[i][0];
+	n2 = faces[i][1];
+	n3 = faces[i][2];
+
+	/* calc center of face */
+	xmin = xmax = nodes[n1][0];
+	ymin = ymax = nodes[n1][1];
+	zmin = zmax = nodes[n1][2];
+
+	if ( nodes[n2][0] < xmin ) { xmin = nodes[n2][0]; }
+	if ( nodes[n2][0] > xmax ) { xmax = nodes[n2][0]; }
+	if ( nodes[n2][1] < ymin ) { ymin = nodes[n2][1]; }
+	if ( nodes[n2][1] > ymax ) { ymax = nodes[n2][1]; }
+	if ( nodes[n2][2] < zmin ) { zmin = nodes[n2][2]; }
+	if ( nodes[n2][2] > zmax ) { zmax = nodes[n2][2]; }
+
+	if ( nodes[n3][0] < xmin ) { xmin = nodes[n3][0]; }
+	if ( nodes[n3][0] > xmax ) { xmax = nodes[n3][0]; }
+	if ( nodes[n3][1] < ymin ) { ymin = nodes[n3][1]; }
+	if ( nodes[n3][1] > ymax ) { ymax = nodes[n3][1]; }
+	if ( nodes[n3][2] < zmin ) { zmin = nodes[n3][2]; }
+	if ( nodes[n3][2] > zmax ) { zmax = nodes[n3][2]; }
+
+	x = (xmin + xmax) / 2.0;
+	y = (ymin + ymax) / 2.0;
+	z = (zmin + zmax) / 2.0;
+
+	/* calc bounding radius */
+	radius = calc_dist(nodes[n1][0] - x, nodes[n1][1] - y, 
+			   nodes[n1][2] - z);
+
+	dist = calc_dist(nodes[n2][0] - x, nodes[n2][1] - y, nodes[n2][2] - z);
+	if ( dist > radius ) { radius = dist; }
+
+	dist = calc_dist(nodes[n3][0] - x, nodes[n3][1] - y, nodes[n3][2] - z);
+	if ( dist > radius ) { radius = dist; }
+	
+	/* output data */
+	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", x, y, z, radius);
+	fprintf(out, "f %d %d %d\n", n1, n2, n3);
     }
 }
 
 
 /* dump list */
 void dump_list(int *list, int list_ptr) {
-    int i;
+    double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
+    int i, j, len, n;
 
     if ( list_ptr < 3 ) {
 	printf("List is empty ... skipping\n");
@@ -220,7 +260,52 @@ void dump_list(int *list, int list_ptr) {
 	    fprintf(out, "\nusemtl desert2\n");
 	}
 
-	/* dump header */
+	/* find length of next tri strip */
+	len = 0;
+	/* scan rest of strip (until -1) */
+	while ( ((i+len) < list_ptr) && (list[i+len] != -1) ) { 
+	    // printf("len = %d item = %d\n", len, list[i+len] );
+	    len++;
+	}
+	// printf("strip length = %d\n", len);
+
+	/* calc center of face */
+	n = list[i];
+	xmin = xmax = nodes[n][0];
+	ymin = ymax = nodes[n][1];
+	zmin = zmax = nodes[n][2];
+	printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
+
+	for ( j = i + 1; j < i + len; j++ ) {
+	    // printf("j = %d\n", j);
+	    n = list[j];
+	    if ( nodes[n][0] < xmin ) { xmin = nodes[n][0]; }
+	    if ( nodes[n][0] > xmax ) { xmax = nodes[n][0]; }
+	    if ( nodes[n][1] < ymin ) { ymin = nodes[n][1]; }
+	    if ( nodes[n][1] > ymax ) { ymax = nodes[n][1]; }
+	    if ( nodes[n][2] < zmin ) { zmin = nodes[n][2]; }
+	    if ( nodes[n][2] > zmax ) { zmax = nodes[n][2]; }
+	    printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
+	}	    
+	x = (xmin + xmax) / 2.0;
+	y = (ymin + ymax) / 2.0;
+	z = (zmin + zmax) / 2.0;
+	printf("center = %.2f %.2f %.2f\n", x, y, z);
+
+	/* calc bounding radius */
+	n = list[i];
+	radius = calc_dist(nodes[n][0] - x, nodes[n][1] - y, nodes[n][2] - z);
+
+	for ( j = i + 1; j < i + len; j++ ) {
+	    n = list[j];
+	    dist = calc_dist(nodes[n][0] - x, nodes[n][1] - y, 
+			     nodes[n][2] - z);
+	    if ( dist > radius ) { radius = dist; }
+	}
+	printf("radius = %.2f\n", radius);
+
+	/* dump bounding sphere and header */
+	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", x, y, z, radius);
 	fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]);
 	/* printf("t %d %d %d\n", list[i], list[i+1], list[i+2]); */
 	i += 3;
@@ -477,9 +562,13 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.14  1998/05/23 15:19:49  curt
-/* Output more digits after the decimal place.
+/* Revision 1.15  1998/05/24 02:47:47  curt
+/* For each strip, specify a default material property and calculate a center
+/* and bounding sphere.
 /*
+ * Revision 1.14  1998/05/23 15:19:49  curt
+ * Output more digits after the decimal place.
+ *
  * Revision 1.13  1998/05/20 20:55:19  curt
  * Fixed arbitrary polygon winding problem here so all tristrips are passed
  * to runtime simulator with a consistant counter clockwise winding.

From e1934115dce5449e04d0826e90172796bc888e7d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 27 May 1998 02:25:26 +0000
Subject: [PATCH 092/283] Added a flag to the first run of "triangle" to impose
 a maximum triangle size.  This forces really flat areas to be subdivided a
 certain amount anyways.  This makes for slightly more interesting scenery.

---
 Tools/process-dem.pl | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index fe7cc3284..b585e839d 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -26,17 +26,19 @@
 #---------------------------------------------------------------------------
 
 
+$max_area = 10000;            # maximum triangle area
+
 $| = 1;                         # flush buffers after every write
 
-$do_dem2node =     0;
-$do_triangle_1 = 0;
-$do_fixnode =    0;
-$do_splittris =  0;
-$do_assemtris =  0;
-$do_triangle_2 = 0;
+$do_dem2node =   1;
+$do_triangle_1 = 1;
+$do_fixnode =    1;
+$do_splittris =  1;
+$do_assemtris =  1;
+$do_triangle_2 = 1;
 
-$do_tri2obj =    0;
-$do_strips =     0;
+$do_tri2obj =    1;
+$do_strips =     1;
 $do_fixobj =     1;
 
 
@@ -148,7 +150,7 @@ sub triangle_1 {
 	print $file;
 	chop($file);
 	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
-	    $command = "Triangle/triangle -q $subdir/$file";
+	    $command = "Triangle/triangle -a$max_area -q $subdir/$file";
 	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
@@ -388,6 +390,11 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.19  1998/05/27 02:25:26  curt
+# Added a flag to the first run of "triangle" to impose a maximum triangle
+# size.  This forces really flat areas to be subdivided a certain amount
+# anyways.  This makes for slightly more interesting scenery.
+#
 # Revision 1.18  1998/05/20 20:55:40  curt
 # Makefile tweaks
 #

From 17dbfaeee023e8681453a1e8a08ad3290397ba32 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 27 May 1998 02:27:22 +0000
Subject: [PATCH 093/283] Commented out a couple of debugging messages.

---
 FixObj/obj.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/FixObj/obj.c b/FixObj/obj.c
index 99245a90d..31942ea61 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.c
@@ -274,7 +274,7 @@ void dump_list(int *list, int list_ptr) {
 	xmin = xmax = nodes[n][0];
 	ymin = ymax = nodes[n][1];
 	zmin = zmax = nodes[n][2];
-	printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
+	// printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
 
 	for ( j = i + 1; j < i + len; j++ ) {
 	    // printf("j = %d\n", j);
@@ -285,12 +285,12 @@ void dump_list(int *list, int list_ptr) {
 	    if ( nodes[n][1] > ymax ) { ymax = nodes[n][1]; }
 	    if ( nodes[n][2] < zmin ) { zmin = nodes[n][2]; }
 	    if ( nodes[n][2] > zmax ) { zmax = nodes[n][2]; }
-	    printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
+	    // printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
 	}	    
 	x = (xmin + xmax) / 2.0;
 	y = (ymin + ymax) / 2.0;
 	z = (zmin + zmax) / 2.0;
-	printf("center = %.2f %.2f %.2f\n", x, y, z);
+	// printf("center = %.2f %.2f %.2f\n", x, y, z);
 
 	/* calc bounding radius */
 	n = list[i];
@@ -302,7 +302,7 @@ void dump_list(int *list, int list_ptr) {
 			     nodes[n][2] - z);
 	    if ( dist > radius ) { radius = dist; }
 	}
-	printf("radius = %.2f\n", radius);
+	// printf("radius = %.2f\n", radius);
 
 	/* dump bounding sphere and header */
 	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", x, y, z, radius);
@@ -562,10 +562,13 @@ void obj_fix(char *infile, char *outfile) {
 
 
 /* $Log$
-/* Revision 1.15  1998/05/24 02:47:47  curt
-/* For each strip, specify a default material property and calculate a center
-/* and bounding sphere.
+/* Revision 1.16  1998/05/27 02:27:22  curt
+/* Commented out a couple of debugging messages.
 /*
+ * Revision 1.15  1998/05/24 02:47:47  curt
+ * For each strip, specify a default material property and calculate a center
+ * and bounding sphere.
+ *
  * Revision 1.14  1998/05/23 15:19:49  curt
  * Output more digits after the decimal place.
  *

From 96de3b06e8e4b1a65ee15d0cb66729576292a1e4 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Jun 1998 17:58:19 +0000
Subject: [PATCH 094/283] Added a slight border overlap to try to minimize
 pixel wide gaps between tiles due to round off error.  This is not a perfect
 solution, but helps.

---
 AssemTris/assemtris.c | 38 +++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index 572990386..fcab575b6 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -309,14 +309,22 @@ FILE *my_open(char *basename, char *basepath, char *ext) {
 }
 
 
-/* given a file pointer, read all the gdn (geodetic nodes from it) */
-void read_nodes(FILE *fp) {
+/* given a file pointer, read all the gdn (geodetic nodes from it.)
+   The specified offset values (in arcsec) are used to overlap the
+   edges of the tile slightly to cover gaps induced by floating point
+   precision problems.  1 arcsec == about 100 feet so 0.01 arcsec ==
+   about 1 foot */
+void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
     char line[256];
 
     while ( fgets(line, 250, fp) != NULL ) {
 	if ( strncmp(line, "gdn ", 4) == 0 ) {
 	    sscanf(line, "gdn %lf %lf %lf\n", &nodes[nodecount][0], 
 		   &nodes[nodecount][1], &nodes[nodecount][2]);
+
+	    nodes[nodecount][0] += offset_lon;
+	    nodes[nodecount][1] += offset_lat;
+
 	    /*
 	    printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
 		   nodes[nodecount][0], nodes[nodecount][1], 
@@ -334,39 +342,39 @@ void build_node_list(char *basename, char *basepath) {
     FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
 
     ne = my_open(basename, basepath, ".ne");
-    read_nodes(ne);
+    read_nodes(ne, 0.1, 0.1);
     fclose(ne);
 
     nw = my_open(basename, basepath, ".nw");
-    read_nodes(nw);
+    read_nodes(nw, -0.1, 0.1);
     fclose(nw);
 
     se = my_open(basename, basepath, ".se");
-    read_nodes(se);
+    read_nodes(se, 0.1, -0.1);
     fclose(se);
 
     sw = my_open(basename, basepath, ".sw");
-    read_nodes(sw);
+    read_nodes(sw, -0.1, -0.1);
     fclose(sw);
 
     north = my_open(basename, basepath, ".north");
-    read_nodes(north);
+    read_nodes(north, 0.0, 0.1);
     fclose(north);
 
     south = my_open(basename, basepath, ".south");
-    read_nodes(south);
+    read_nodes(south, 0.0, -0.1);
     fclose(south);
 
     east = my_open(basename, basepath, ".east");
-    read_nodes(east);
+    read_nodes(east, 0.1, 0.0);
     fclose(east);
 
     west = my_open(basename, basepath, ".west");
-    read_nodes(west);
+    read_nodes(west, -0.1, 0.0);
     fclose(west);
 
     body = my_open(basename, basepath, ".body");
-    read_nodes(body);
+    read_nodes(body, 0.0, 0.0);
     fclose(body);
 }
 
@@ -454,9 +462,13 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.7  1998/04/14 02:26:00  curt
-/* Code reorganizations.  Added a Lib/ directory for more general libraries.
+/* Revision 1.8  1998/06/01 17:58:19  curt
+/* Added a slight border overlap to try to minimize pixel wide gaps between
+/* tiles due to round off error.  This is not a perfect solution, but helps.
 /*
+ * Revision 1.7  1998/04/14 02:26:00  curt
+ * Code reorganizations.  Added a Lib/ directory for more general libraries.
+ *
  * Revision 1.6  1998/04/08 22:54:58  curt
  * Adopted Gnu automake/autoconf system.
  *

From 51f153543dc9d26d324db325d40d7181f30feff0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:50 +0000
Subject: [PATCH 095/283] initial checkin of checkoutlist

---
 CVSROOT/checkoutlist | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 CVSROOT/checkoutlist

diff --git a/CVSROOT/checkoutlist b/CVSROOT/checkoutlist
new file mode 100644
index 000000000..b04b3501f
--- /dev/null
+++ b/CVSROOT/checkoutlist
@@ -0,0 +1,13 @@
+# The "checkoutlist" file is used to support additional version controlled
+# administrative files in $CVSROOT/CVSROOT, such as template files.
+#
+# The first entry on a line is a filename which will be checked out from
+# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
+# The remainder of the line is an error message to use if the file cannot
+# be checked out.
+#
+# File format:
+#
+#	[<whitespace>]<filename><whitespace><error message><end-of-line>
+#
+# comment lines begin with '#'

From 725048d01082ca84bf2e78ce898ecb5a385675fc Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:50 +0000
Subject: [PATCH 096/283] initial checkin of commitinfo

---
 CVSROOT/commitinfo | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 CVSROOT/commitinfo

diff --git a/CVSROOT/commitinfo b/CVSROOT/commitinfo
new file mode 100644
index 000000000..b19e7b7a6
--- /dev/null
+++ b/CVSROOT/commitinfo
@@ -0,0 +1,15 @@
+# The "commitinfo" file is used to control pre-commit checks.
+# The filter on the right is invoked with the repository and a list 
+# of files to check.  A non-zero exit of the filter program will 
+# cause the commit to be aborted.
+#
+# The first entry on a line is a regular expression which is tested
+# against the directory that the change is being committed to, relative
+# to the $CVSROOT.  For the first match that is found, then the remainder
+# of the line is the name of the filter to run.
+#
+# If the repository name does not match any of the regular expressions in this
+# file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".

From 754a00b1f3d0fb91c6a85543203ab00b0cf06127 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:50 +0000
Subject: [PATCH 097/283] initial checkin of editinfo

---
 CVSROOT/editinfo | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 CVSROOT/editinfo

diff --git a/CVSROOT/editinfo b/CVSROOT/editinfo
new file mode 100644
index 000000000..d78886c15
--- /dev/null
+++ b/CVSROOT/editinfo
@@ -0,0 +1,21 @@
+# The "editinfo" file is used to allow verification of logging
+# information.  It works best when a template (as specified in the
+# rcsinfo file) is provided for the logging procedure.  Given a
+# template with locations for, a bug-id number, a list of people who
+# reviewed the code before it can be checked in, and an external
+# process to catalog the differences that were code reviewed, the
+# following test can be applied to the code:
+#
+#   Making sure that the entered bug-id number is correct.
+#   Validating that the code that was reviewed is indeed the code being
+#       checked in (using the bug-id number or a seperate review
+#       number to identify this particular code set.).
+#
+# If any of the above test failed, then the commit would be aborted.
+#
+# Actions such as mailing a copy of the report to each reviewer are
+# better handled by an entry in the loginfo file.
+#
+# One thing that should be noted is the the ALL keyword is not
+# supported.  There can be only one entry that matches a given
+# repository.

From df88f8f09755b5c3e59a696f87476bd91550bec6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:50 +0000
Subject: [PATCH 098/283] initial checkin of loginfo

---
 CVSROOT/loginfo | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 CVSROOT/loginfo

diff --git a/CVSROOT/loginfo b/CVSROOT/loginfo
new file mode 100644
index 000000000..226e93771
--- /dev/null
+++ b/CVSROOT/loginfo
@@ -0,0 +1,19 @@
+# The "loginfo" file is used to control where "cvs commit" log information is
+# sent.  The first entry on a line is a regular expression which is tested
+# against the directory that the change is being made to, relative to the
+# $CVSROOT.  For the first match that is found, the remainder of the line is a
+# filter program that should expect log information on its standard input
+#
+# If the repository name does not match any of the regular expressions in the
+# first field of this file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".
+#
+# The filter program may use one and only one "%s" modifier (ala printf).  If
+# such a "%s" is specified in the filter program, a brief title is included
+# (as one argument, enclosed in single quotes) showing the relative directory
+# name and listing the modified file names.
+#
+# For example:
+#DEFAULT		(echo ""; who am i; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog

From 515cef272c125d8cb7b2f02b1bb297b95b7df94f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:50 +0000
Subject: [PATCH 099/283] initial checkin of rcsinfo

---
 CVSROOT/rcsinfo | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 CVSROOT/rcsinfo

diff --git a/CVSROOT/rcsinfo b/CVSROOT/rcsinfo
new file mode 100644
index 000000000..49e59f4d0
--- /dev/null
+++ b/CVSROOT/rcsinfo
@@ -0,0 +1,13 @@
+# The "rcsinfo" file is used to control templates with which the editor
+# is invoked on commit and import.
+#
+# The first entry on a line is a regular expression which is tested
+# against the directory that the change is being made to, relative to the
+# $CVSROOT.  For the first match that is found, then the remainder of the
+# line is the name of the file that contains the template.
+#
+# If the repository name does not match any of the regular expressions in this
+# file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".

From 701f49f4f98c53598b656ae0120e715ea8b676f8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:50 +0000
Subject: [PATCH 100/283] initial checkin of taginfo

---
 CVSROOT/taginfo | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 CVSROOT/taginfo

diff --git a/CVSROOT/taginfo b/CVSROOT/taginfo
new file mode 100644
index 000000000..274a46dd5
--- /dev/null
+++ b/CVSROOT/taginfo
@@ -0,0 +1,20 @@
+# The "taginfo" file is used to control pre-tag checks.
+# The filter on the right is invoked with the following arguments:
+#
+# $1 -- tagname
+# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
+# $3 -- repository
+# $4->  file revision [file revision ...]
+#
+# A non-zero exit of the filter program will cause the tag to be aborted.
+#
+# The first entry on a line is a regular expression which is tested
+# against the directory that the change is being committed to, relative
+# to the $CVSROOT.  For the first match that is found, then the remainder
+# of the line is the name of the filter to run.
+#
+# If the repository name does not match any of the regular expressions in this
+# file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".

From fec6317b27da642a35f7094b3cc166cbc764668e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:51 +0000
Subject: [PATCH 101/283] initial checkin of cvswrappers

---
 CVSROOT/cvswrappers | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 CVSROOT/cvswrappers

diff --git a/CVSROOT/cvswrappers b/CVSROOT/cvswrappers
new file mode 100644
index 000000000..5047bf1c5
--- /dev/null
+++ b/CVSROOT/cvswrappers
@@ -0,0 +1,22 @@
+# This file describes wrappers and other binary files to CVS.
+#
+# Wrappers are the concept where directories of files are to be
+# treated as a single file.  The intended use is to wrap up a wrapper
+# into a single tar such that the tar archive can be treated as a
+# single binary file in CVS.
+#
+# To solve the problem effectively, it was also necessary to be able to
+# prevent rcsmerge from merging these files.
+#
+# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
+#
+#  wildcard	[option value][option value]...
+#
+#  where option is one of
+#  -f		from cvs filter		value: path to filter
+#  -t		to cvs filter		value: path to filter
+#  -m		update methodology	value: MERGE or COPY
+#
+#  and value is a single-quote delimited value.
+#
+# For example:

From b6ecbc2fa345a4da77bcfdfccd68bd863746eaad Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:51 +0000
Subject: [PATCH 102/283] initial checkin of modules

---
 CVSROOT/modules | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 CVSROOT/modules

diff --git a/CVSROOT/modules b/CVSROOT/modules
new file mode 100644
index 000000000..cb9e9efc9
--- /dev/null
+++ b/CVSROOT/modules
@@ -0,0 +1,26 @@
+# Three different line formats are valid:
+#	key	-a    aliases...
+#	key [options] directory
+#	key [options] directory files...
+#
+# Where "options" are composed of:
+#	-i prog		Run "prog" on "cvs commit" from top-level of module.
+#	-o prog		Run "prog" on "cvs checkout" of module.
+#	-e prog		Run "prog" on "cvs export" of module.
+#	-t prog		Run "prog" on "cvs rtag" of module.
+#	-u prog		Run "prog" on "cvs update" of module.
+#	-d dir		Place module in directory "dir" instead of module name.
+#	-l		Top-level directory only -- do not recurse.
+#
+# NOTE:  If you change any of the "Run" options above, you'll have to
+# release and re-checkout any working directories of these modules.
+#
+# And "directory" is a path to a directory relative to $CVSROOT.
+#
+# The "-a" option specifies an alias.  An alias is interpreted as if
+# everything on the right of the "-a" had been typed on the command line.
+#
+# You can encode a module within a module by using the special '&'
+# character to interpose another module into the current module.  This
+# can be useful for creating a module that consists of many directories
+# spread out over the entire source repository.

From dcd80906b96b5ee279cc41376b1fb3270838ed9b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Jun 1998 21:59:51 +0000
Subject: [PATCH 103/283] initial checkin of notify

---
 CVSROOT/notify | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 CVSROOT/notify

diff --git a/CVSROOT/notify b/CVSROOT/notify
new file mode 100644
index 000000000..34f0bc288
--- /dev/null
+++ b/CVSROOT/notify
@@ -0,0 +1,12 @@
+# The "notify" file controls where notifications from watches set by
+# "cvs watch add" or "cvs edit" are sent.  The first entry on a line is
+# a regular expression which is tested against the directory that the
+# change is being made to, relative to the $CVSROOT.  If it matches,
+# then the remainder of the line is a filter program that should contain
+# one occurrence of %s for the user to notify, and information on its
+# standard input.
+#
+# "ALL" or "DEFAULT" can be used in place of the regular expression.
+#
+# For example:
+#ALL mail %s -s "CVS notification"

From 5880cd9ec06f1e986d9d2441fc70b2931834a2ec Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 4 Jun 1998 19:18:04 +0000
Subject: [PATCH 104/283] Initial revision.

---
 DemInfo/Makefile.am        | 49 +++++++++++++++++++++++++
 DemInfo/deminfo.cxx        | 73 ++++++++++++++++++++++++++++++++++++++
 DemInfo/gather-dem-info.pl | 61 +++++++++++++++++++++++++++++++
 3 files changed, 183 insertions(+)
 create mode 100644 DemInfo/Makefile.am
 create mode 100644 DemInfo/deminfo.cxx
 create mode 100755 DemInfo/gather-dem-info.pl

diff --git a/DemInfo/Makefile.am b/DemInfo/Makefile.am
new file mode 100644
index 000000000..4bfa93f57
--- /dev/null
+++ b/DemInfo/Makefile.am
@@ -0,0 +1,49 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started June 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+bin_PROGRAMS = deminfo
+
+deminfo_SOURCES = \
+	deminfo.cxx
+
+deminfo_LDADD = \
+	$(top_builddir)/Lib/DEM/libDEM.la \
+	$(top_builddir)/Lib/Bucket/libBucket.la \
+	$(top_builddir)/Lib/zlib/libz.la
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+
+# We can't build this with "-O2" (optimization) since this causes a seg fault
+# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
+# setting it to "-g"
+CXXFLAGS = -g 
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/06/04 19:18:04  curt
+# Initial revision.
+#
diff --git a/DemInfo/deminfo.cxx b/DemInfo/deminfo.cxx
new file mode 100644
index 000000000..9af81a9dd
--- /dev/null
+++ b/DemInfo/deminfo.cxx
@@ -0,0 +1,73 @@
+// deminfo.cxx -- main loop
+//
+// Written by Curtis Olson, started June 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <DEM/dem.hxx>
+
+
+// static float dem_data[DEM_SIZE_1][DEM_SIZE_1];
+// static float output_data[DEM_SIZE_1][DEM_SIZE_1];
+
+
+int main(int argc, char **argv) {
+    // DEM data
+    fgDEM dem;
+    char fg_root[256];
+    char filename[256];
+    double error;
+    int i, j;
+
+    if ( argc != 2 ) {
+	printf("Usage: %s <file.dem>\n", argv[0]);
+	exit(-1);
+    }
+
+    // set input dem file name
+    strcpy(filename, argv[1]);
+
+    dem.open(filename);
+
+    if ( dem.read_a_record() ) {
+	printf("Results = %s  %.1f %.1f\n", 
+	       filename, 
+	       dem.info_originx() / 3600.0,
+	       dem.info_originy() / 3600.0 ) ;
+    } else {
+	printf("Error parsing DEM file.\n");
+    }
+
+    dem.close();
+
+    return(0);
+}
+
+
+// $Log$
+// Revision 1.1  1998/06/04 19:18:05  curt
+// Initial revision.
+//
diff --git a/DemInfo/gather-dem-info.pl b/DemInfo/gather-dem-info.pl
new file mode 100755
index 000000000..746d7120e
--- /dev/null
+++ b/DemInfo/gather-dem-info.pl
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+
+#---------------------------------------------------------------------------
+# script to gather DEM position info so we can associate a file name with a
+# position.
+#
+# Written by Curtis Olson, started June 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+if ( $#ARGV < 0 ) {
+    die "Usage: $0 search_dir ... \n";
+}
+
+while ( $dir = shift(@ARGV) ) {
+    # print "processing $dir\n";
+
+    @allfiles = `find $dir -print`;
+
+    foreach $file (@allfiles) {
+	chop($file);
+	# print "trying $file\n";
+	if ( -f $file ) {
+	    # print "really trying $file\n";
+	    open ( INFO, "./deminfo $file |" );
+	    while ( <INFO> ) {
+		if ( m/Results = / ) {
+		    $_ =~ s/Results = //;
+		    print $_;
+		}
+	    }
+	    close(INFO);
+	}
+    }
+}
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/06/04 19:18:06  curt
+# Initial revision.
+#

From 317854534f70b945e79e5c4ef6e9996a469064a6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 5 Jun 1998 18:14:39 +0000
Subject: [PATCH 105/283] Abort out early when reading the "A" record if it
 doesn't look like a proper DEM file.

---
 DEM/dem.cxx | 18 +++++++++++++++---
 DEM/dem.hxx |  6 +++++-
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 0e3351f18..b76f183b1 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -198,7 +198,7 @@ static int next_exp(gzFile fd) {
 
 
 // read and parse DEM "A" record
-void fgDEM::read_a_record( void ) {
+int fgDEM::read_a_record( void ) {
     int i, inum;
     double dnum;
     char name[144];
@@ -225,6 +225,10 @@ void fgDEM::read_a_record( void ) {
     inum = next_int(fd);
     printf("    DEM level code = %d\n", inum);
 
+    if ( inum > 3 ) {
+	return(0);
+    }
+
     // Pattern code, 1 indicates a regular elevation pattern
     inum = next_int(fd);
     printf("    Pattern code = %d\n", inum);
@@ -331,6 +335,8 @@ void fgDEM::read_a_record( void ) {
     // number of profiles
     dem_num_profiles = cols = next_int(fd);
     printf("    Expecting %d profiles\n", dem_num_profiles);
+
+    return(1);
 }
 
 
@@ -377,7 +383,9 @@ int fgDEM::parse( void ) {
 
     cur_col = 0;
 
-    read_a_record();
+    if ( !read_a_record() ) {
+	return(0);
+    }
 
     for ( i = 0; i < dem_num_profiles; i++ ) {
 	// printf("Ready to read next b record\n");
@@ -391,7 +399,7 @@ int fgDEM::parse( void ) {
 
     printf("    Done parsing\n");
 
-    return(0);
+    return(1);
 }
 
 
@@ -772,6 +780,10 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.7  1998/06/05 18:14:39  curt
+// Abort out early when reading the "A" record if it doesn't look like
+// a proper DEM file.
+//
 // Revision 1.6  1998/05/02 01:49:21  curt
 // Fixed a bug where the wrong variable was being initialized.
 //
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 065ead15c..31870b125 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -92,7 +92,7 @@ public:
     int parse( void );
 
     // read and parse DEM "A" record
-    void read_a_record( void );
+    int read_a_record( void );
 
     // read and parse DEM "B" record
     void read_b_record( void );
@@ -130,6 +130,10 @@ public:
 
 
 // $Log$
+// Revision 1.6  1998/06/05 18:14:40  curt
+// Abort out early when reading the "A" record if it doesn't look like
+// a proper DEM file.
+//
 // Revision 1.5  1998/04/22 13:14:46  curt
 // Fixed a bug in zlib usage.
 //

From 35295a4535175196782904a4269a98aa01ad970b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 5 Jun 1998 18:20:23 +0000
Subject: [PATCH 106/283] Added DemInfo to dump out "A" record DEM info.
 Modified process-dem.pl to work in a temp directory and compress/copy the
 result to the final destination.

---
 Tools/Makefile.am    |  1 +
 Tools/process-dem.pl | 60 +++++++++++++++++++++++++++++++++++---------
 2 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 2147c3a22..9e51072b1 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	AssemTris \
 	Dem2node \
+	DemInfo \
 	DemRaw2ascii \
 	FixNode \
 	FixObj \
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index b585e839d..31a4624cb 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -41,20 +41,17 @@ $do_tri2obj =    1;
 $do_strips =     1;
 $do_fixobj =     1;
 
-
-# set the FG_ROOT environment variable if it hasn't already been set.
-if ( $ENV{FG_ROOT} eq "" ) {
-    # look for a file called fgtop as a place marker
-    die "You must remember to set the FG_ROOT environment variable!\n";
-}
+$do_install =    1;
 
 
-if ( $#ARGV < 1 ) {
-    die "Usage: $0 <error^2> dem-file1 [ dem-file2 dem-file3 ... ]\n";
+if ( $#ARGV < 3 ) {
+    die "Usage: $0 <fg-root-dir> <work-dir> <error^2> dem-file(s)\n";
 }
 
 # Start with file.dem
 
+$fg_root = shift(@ARGV);
+$work_dir = shift(@ARGV);
 $error = shift(@ARGV);
 $error += 0.0;
 
@@ -70,7 +67,7 @@ while ( $dem_file = shift(@ARGV) ) {
     if ( $do_dem2node ) {
 	dem2node() ;
     } else {
-	$subdir = "../Scenery/w120n030/w111n033";
+	$subdir = "./work/Scenery/e010n080/e019n084";
 	print "WARNING:  Hardcoding subdir = $subdir\n";
     }
 
@@ -82,6 +79,7 @@ while ( $dem_file = shift(@ARGV) ) {
     tri2obj() if ( $do_tri2obj );
     strips() if ( $do_strips );
     fixobj() if ( $do_fixobj );
+    install() if ( $do_install );
 }
 
 
@@ -114,7 +112,7 @@ sub file_root {
 }
 
 
-# 1.  dem2node $FG_ROOT dem_file tolerance^2 (meters)
+# 1.  dem2node work_dir dem_file tolerance^2 (meters)
 # 
 #     - dem2node .. dem_file 160000
 #
@@ -122,7 +120,7 @@ sub file_root {
 #     irregularly fitted vertices
 
 sub dem2node {
-    $command = "Dem2node/dem2node $ENV{FG_ROOT} $dem_file $error";
+    $command = "Dem2node/dem2node $work_dir $dem_file $error";
     $command = fix_command($command);
     print "Running '$command'\n";
 
@@ -382,7 +380,40 @@ sub fixobj {
 	    }
 	    close(OUT);
 
-	    # unlink("$subdir/$file");
+	    unlink("$subdir/$file");
+	}
+    }
+}
+
+
+# 9.  install
+#
+#     rename, compress, and install scenery files
+
+sub install {
+    $tmp = $subdir;
+    $tmp =~ s/$work_dir//;
+    # print "Temp dir = $tmp\n";
+    $install_dir = "$fg_root/$tmp";
+    print "Install dir = $install_dir\n";
+    system("mkdir -p $install_dir");
+
+    @FILES = `ls $subdir`;
+    foreach $file ( @FILES ) {
+	chop($file);
+	if ( $file =~ m/\d\d.obj$/ ) {
+	    $new_file = file_root($file);
+	    
+	    $command = "gzip -v --best < $subdir/$file > $install_dir/$new_file.gz";
+	    # $command = fix_command($command);
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
+
+	    unlink("$subdir/$file");
 	}
     }
 }
@@ -390,6 +421,11 @@ sub fixobj {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.20  1998/06/05 18:20:24  curt
+# Added DemInfo to dump out "A" record DEM info.
+# Modified process-dem.pl to work in a temp directory and compress/copy the
+# result to the final destination.
+#
 # Revision 1.19  1998/05/27 02:25:26  curt
 # Added a flag to the first run of "triangle" to impose a maximum triangle
 # size.  This forces really flat areas to be subdivided a certain amount

From f7a80a9de3b3d1380cb23dbdbb6db4feea9d34c6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Jun 1998 17:11:44 +0000
Subject: [PATCH 107/283] Renamed *.[ch] to *.[ch]xx

---
 FixObj/Makefile.am        |   5 +-
 FixObj/main.c             |  55 --------
 FixObj/main.cxx           |  57 ++++++++
 FixObj/{obj.c => obj.cxx} | 290 +++++++++++++++++++-------------------
 FixObj/obj.h              |  54 -------
 FixObj/obj.hxx            |  60 ++++++++
 6 files changed, 267 insertions(+), 254 deletions(-)
 delete mode 100644 FixObj/main.c
 create mode 100644 FixObj/main.cxx
 rename FixObj/{obj.c => obj.cxx} (67%)
 delete mode 100644 FixObj/obj.h
 create mode 100644 FixObj/obj.hxx

diff --git a/FixObj/Makefile.am b/FixObj/Makefile.am
index 2ee3159b4..0f7f16710 100644
--- a/FixObj/Makefile.am
+++ b/FixObj/Makefile.am
@@ -26,7 +26,7 @@
 
 bin_PROGRAMS = fixobj
 
-fixobj_SOURCES = main.c obj.c obj.h
+fixobj_SOURCES = main.cxx obj.cxx obj.hxx
 
 fixobj_LDADD = \
 	$(top_builddir)/Lib/Math/libMath.la \
@@ -38,6 +38,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/06/08 17:11:44  curt
+# Renamed *.[ch] to *.[ch]xx
+#
 # Revision 1.4  1998/04/24 00:44:05  curt
 # Added zlib support.
 #
diff --git a/FixObj/main.c b/FixObj/main.c
deleted file mode 100644
index bb20a0e37..000000000
--- a/FixObj/main.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* main.c -- read and fix the stripping order of a .obj file
- *
- * Written by Curtis Olson, started December 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
-
-
-#include <stdio.h>
-
-#include "obj.h"
-
-
-int main(int argc, char **argv) {
-    char infile[256], outfile[256];
-
-    if ( argc != 3 ) {
-	printf("Usage %s: infile outfile\n", argv[0]);
-    }
-
-    strcpy(infile, argv[1]);
-    strcpy(outfile, argv[2]);
-
-    /* load the input data files */
-    obj_fix(infile, outfile);
-
-    return(0);
-}
-
-
-/* $Log$
-/* Revision 1.2  1998/01/09 23:03:12  curt
-/* Restructured to split 1deg x 1deg dem's into 64 subsections.
-/*
- * Revision 1.1  1997/12/08 19:28:54  curt
- * Initial revision.
- *
- */
diff --git a/FixObj/main.cxx b/FixObj/main.cxx
new file mode 100644
index 000000000..bf117a10c
--- /dev/null
+++ b/FixObj/main.cxx
@@ -0,0 +1,57 @@
+// main.cxx -- read and fix the stripping order of a .obj file
+//
+// Written by Curtis Olson, started December 1997.
+//
+// Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include <stdio.h>
+
+#include "obj.hxx"
+
+
+int main(int argc, char **argv) {
+    char infile[256], outfile[256];
+
+    if ( argc != 3 ) {
+	printf("Usage %s: infile outfile\n", argv[0]);
+    }
+
+    strcpy(infile, argv[1]);
+    strcpy(outfile, argv[2]);
+
+    // load the input data files
+    obj_fix(infile, outfile);
+
+    return(0);
+}
+
+
+// $Log$
+// Revision 1.1  1998/06/08 17:11:45  curt
+// Renamed *.[ch] to *.[ch]xx
+//
+// Revision 1.2  1998/01/09 23:03:12  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.1  1997/12/08 19:28:54  curt
+// Initial revision.
+//
+
diff --git a/FixObj/obj.c b/FixObj/obj.cxx
similarity index 67%
rename from FixObj/obj.c
rename to FixObj/obj.cxx
index 31942ea61..25690d5b4 100644
--- a/FixObj/obj.c
+++ b/FixObj/obj.cxx
@@ -1,38 +1,38 @@
-/**************************************************************************
- * obj.c -- routines to handle WaveFront .obj format files.
- *
- * Written by Curtis Olson, started October 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
+// obj.cxx -- routines to handle WaveFront .obj format files.
+//
+// Written by Curtis Olson, started October 1997.
+//
+// Copyright (C) 1997 - 1998  Curtis L. Olson - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
 
 
 #include <stdio.h>
 #include <string.h>
 
-#include "obj.h"
+#include "obj.hxx"
 
 #include <Math/mat3.h>
 
 
-/* what do ya' know, here's some global variables */
+
+
+// what do ya' know, here's some global variables
 static double nodes[MAXNODES][3];
 static double normals[MAXNODES][3];
 static int faces[MAXNODES][3];
@@ -49,15 +49,15 @@ FILE *in, *out;
 double refx, refy, refz;
 
 
-/* some simple list routines */
+// some simple list routines
 
-/* reset the list */
+// reset the list
 void list_init(int *list_ptr) {
     *list_ptr = 0;
 }
 
 
-/* add to list */
+// add to list
 void list_add(int *list, int *list_ptr, int node) {
     if ( *list_ptr >= MAXNODES ) {
 	printf("ERROR: list overflow in list_add()\n");
@@ -67,11 +67,11 @@ void list_add(int *list, int *list_ptr, int node) {
     list[*list_ptr] = node;
     *list_ptr += 1;
 
-    /* printf("list pointer = %d  adding %d\n", *list_ptr, node); */
+    // printf("list pointer = %d  adding %d\n", *list_ptr, node);
 }
 
 
-/* fix the cw list and append to ccw_list */
+// fix the cw list and append to ccw_list
 void fix_cw_list(int *list, int list_ptr) {
     int i, j, len;
 
@@ -84,11 +84,11 @@ void fix_cw_list(int *list, int list_ptr) {
 
     i = 0;
     while ( i < list_ptr ) { 
-	/* do next strip */
+	// do next strip
 
-	/* find length */
+	// find length
 	len = 0;
-	/* scan rest of strip (until -1) */
+	// scan rest of strip (until -1)
 	while ( ((i+len) < list_ptr) && (list[i+len] != -1) ) { 
 	    // printf("len = %d item = %d\n", len, list[i+len] );
 	    len++;
@@ -96,8 +96,8 @@ void fix_cw_list(int *list, int list_ptr) {
 	// printf("          Final length = %d\n", len);
 
 	if ( (len % 2) != 0 ) {
-	    /* if length is odd, just reverse order of nodes to reverse
-	       winding */
+	    // if length is odd, just reverse order of nodes to
+	    // reverse winding
 	    if ( ccw_list_ptr ) {
 		list_add(ccw_list, &ccw_list_ptr, -1);
 	    }
@@ -106,9 +106,9 @@ void fix_cw_list(int *list, int list_ptr) {
 		list_add(ccw_list, &ccw_list_ptr, list[j]);
 	    }
 	} else {
-	    /* if length is even, reverse order of (n-1) nodes to
-	       reverse winding, and create an orphan triangle for the
-	       last "nth" node */
+	    // if length is even, reverse order of (n-1) nodes to
+	    // reverse winding, and create an orphan triangle for the
+	    // last "nth" node
 	    if ( ccw_list_ptr ) {
 		list_add(ccw_list, &ccw_list_ptr, -1);
 	    }
@@ -163,7 +163,7 @@ void dump_global_bounds( void ) {
 }
 
 
-/* dump nodes */
+// dump nodes
 void dump_nodes( void ) {
     int i;
 
@@ -175,7 +175,7 @@ void dump_nodes( void ) {
 }
 
 
-/* dump normals */
+// dump normals
 void dump_normals( void ) {
     int i;
 
@@ -187,7 +187,7 @@ void dump_normals( void ) {
 }
 
 
-/* dump faces */
+// dump faces
 void dump_faces( void ) {
     int i, n1, n2, n3;
     double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
@@ -198,7 +198,7 @@ void dump_faces( void ) {
 	n2 = faces[i][1];
 	n3 = faces[i][2];
 
-	/* calc center of face */
+	// calc center of face
 	xmin = xmax = nodes[n1][0];
 	ymin = ymax = nodes[n1][1];
 	zmin = zmax = nodes[n1][2];
@@ -221,7 +221,7 @@ void dump_faces( void ) {
 	y = (ymin + ymax) / 2.0;
 	z = (zmin + zmax) / 2.0;
 
-	/* calc bounding radius */
+	// calc bounding radius
 	radius = calc_dist(nodes[n1][0] - x, nodes[n1][1] - y, 
 			   nodes[n1][2] - z);
 
@@ -231,14 +231,14 @@ void dump_faces( void ) {
 	dist = calc_dist(nodes[n3][0] - x, nodes[n3][1] - y, nodes[n3][2] - z);
 	if ( dist > radius ) { radius = dist; }
 	
-	/* output data */
+	// output data
 	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", x, y, z, radius);
 	fprintf(out, "f %d %d %d\n", n1, n2, n3);
     }
 }
 
 
-/* dump list */
+// dump list
 void dump_list(int *list, int list_ptr) {
     double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
     int i, j, len, n;
@@ -252,7 +252,7 @@ void dump_list(int *list, int list_ptr) {
 
     i = 0;
     while ( i < list_ptr ) { 
-	/* do next strip */
+	// do next strip
 
 	if ( (i % 2) == 0 ) {
 	    fprintf(out, "\nusemtl desert1\n");
@@ -260,16 +260,16 @@ void dump_list(int *list, int list_ptr) {
 	    fprintf(out, "\nusemtl desert2\n");
 	}
 
-	/* find length of next tri strip */
+	// find length of next tri strip
 	len = 0;
-	/* scan rest of strip (until -1) */
+	// scan rest of strip (until -1)
 	while ( ((i+len) < list_ptr) && (list[i+len] != -1) ) { 
 	    // printf("len = %d item = %d\n", len, list[i+len] );
 	    len++;
 	}
 	// printf("strip length = %d\n", len);
 
-	/* calc center of face */
+	// calc center of face
 	n = list[i];
 	xmin = xmax = nodes[n][0];
 	ymin = ymax = nodes[n][1];
@@ -292,7 +292,7 @@ void dump_list(int *list, int list_ptr) {
 	z = (zmin + zmax) / 2.0;
 	// printf("center = %.2f %.2f %.2f\n", x, y, z);
 
-	/* calc bounding radius */
+	// calc bounding radius
 	n = list[i];
 	radius = calc_dist(nodes[n][0] - x, nodes[n][1] - y, nodes[n][2] - z);
 
@@ -304,13 +304,13 @@ void dump_list(int *list, int list_ptr) {
 	}
 	// printf("radius = %.2f\n", radius);
 
-	/* dump bounding sphere and header */
+	// dump bounding sphere and header
 	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", x, y, z, radius);
 	fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]);
-	/* printf("t %d %d %d\n", list[i], list[i+1], list[i+2]); */
+	// printf("t %d %d %d\n", list[i], list[i+1], list[i+2]);
 	i += 3;
 
-	/* dump rest of strip (until -1) */
+	// dump rest of strip (until -1)
 	while ( (i < list_ptr) && (list[i] != -1) ) { 
 	    fprintf(out, "q %d", list[i]);
 	    i++;
@@ -326,16 +326,15 @@ void dump_list(int *list, int list_ptr) {
 }
 
 
-/* Check the direction the current triangle faces, compared to it's
- * pregenerated normal.  Returns the dot product between the target
- * normal and actual normal.  If the dot product is close to 1.0, they
- * nearly match.  If the are close to -1.0, the are nearly
- * opposite. */
+// Check the direction the current triangle faces, compared to it's
+// pregenerated normal.  Returns the dot product between the target
+// normal and actual normal.  If the dot product is close to 1.0, they
+// nearly match.  If the are close to -1.0, the are nearly opposite.
 double check_cur_face(int n1, int n2, int n3) {
     double v1[3], v2[3], approx_normal[3], dot_prod, temp;
 
-    /* check for the proper rotation by calculating an approximate
-     * normal and seeing if it is close to the precalculated normal */
+    // check for the proper rotation by calculating an approximate
+    // normal and seeing if it is close to the precalculated normal
     v1[0] = nodes[n2][0] - nodes[n1][0];
     v1[1] = nodes[n2][1] - nodes[n1][1];
     v1[2] = nodes[n2][2] - nodes[n1][2];
@@ -347,21 +346,21 @@ double check_cur_face(int n1, int n2, int n3) {
     MAT3_NORMALIZE_VEC(approx_normal,temp);
     dot_prod = MAT3_DOT_PRODUCT(normals[n1], approx_normal);
 
-    /* not first triangle */
-    /* if ( ((dot_prod < -0.5) && !is_backwards) ||
-	 ((dot_prod >  0.5) && is_backwards) ) {
-	printf("    Approx normal = %.2f %.2f %.2f\n", approx_normal[0], 
-	       approx_normal[1], approx_normal[2]);
-	printf("    Dot product = %.4f\n", dot_prod);
-    } */
-    /* angle = acos(dot_prod); */
-    /* printf("Normal ANGLE = %.3f rads.\n", angle); */
+    // not first triangle
+    // if ( ((dot_prod < -0.5) && !is_backwards) ||
+    //     ((dot_prod >  0.5) && is_backwards) ) {
+    //     printf("    Approx normal = %.2f %.2f %.2f\n", approx_normal[0], 
+    //            approx_normal[1], approx_normal[2]);
+    //     printf("    Dot product = %.4f\n", dot_prod);
+    // }
+    // angle = acos(dot_prod);
+    // printf("Normal ANGLE = %.3f rads.\n", angle);
 
     return(dot_prod);
 }
 
 
-/* Load a .obj file */
+// Load a .obj file
 void obj_fix(char *infile, char *outfile) {
     char line[256];
     double dot_prod;
@@ -382,8 +381,8 @@ void obj_fix(char *infile, char *outfile) {
     list_init(&ccw_list_ptr);
     list_init(&cw_list_ptr);
 
-    /* I start counting at one because that is how the triangle
-       program refers to nodes and normals */
+    // I start counting at one because that is how the triangle
+    // program refers to nodes and normals
     first = 1;
     ncount = 1;
     vncount = 1;
@@ -393,21 +392,21 @@ void obj_fix(char *infile, char *outfile) {
 
     while ( fgets(line, 250, in) != NULL ) {
 	if ( line[0] == '#' ) {
-	    /* pass along the comments verbatim */
+	    // pass along the comments verbatim
 	    fprintf(out, "%s", line);
 	} else if ( strlen(line) <= 1 ) {
-	    /* don't pass along empty lines */
+	    // don't pass along empty lines
 	    // fprintf(out, "%s", line);
 	} else if ( strncmp(line, "v ", 2) == 0 ) {
-	    /* save vertex to memory and output to file */
+	    // save vertex to memory and output to file
             if ( ncount < MAXNODES ) {
-                /* printf("vertex = %s", line); */
+                // printf("vertex = %s", line);
                 sscanf(line, "v %lf %lf %lf\n", &x, &y, &z);
 		nodes[ncount][0] = x;
 		nodes[ncount][1] = y;
 		nodes[ncount][2] = z;
 
-		/* first time through set min's and max'es */
+		// first time through set min's and max'es
 		if ( ncount == 1 ) {
 		    xmin = x;
 		    xmax = x;
@@ -417,7 +416,7 @@ void obj_fix(char *infile, char *outfile) {
 		    zmax = z;
 		}
     
-		/* keep track of min/max vertex values */
+		// keep track of min/max vertex values
 		if ( x < xmin ) xmin = x;
 		if ( x > xmax ) xmax = x;
 		if ( y < ymin ) ymin = y;
@@ -433,9 +432,9 @@ void obj_fix(char *infile, char *outfile) {
                 exit(-1);
             }
 	} else if ( strncmp(line, "vn ", 3) == 0 ) {
-	    /* save vertex normals to memory and output to file */
+	    // save vertex normals to memory and output to file
             if ( vncount < MAXNODES ) {
-                /* printf("vertex normal = %s", line); */
+                // printf("vertex normal = %s", line);
                 sscanf(line, "vn %lf %lf %lf\n", 
                        &normals[vncount][0], &normals[vncount][1], 
                        &normals[vncount][2]);
@@ -447,7 +446,7 @@ void obj_fix(char *infile, char *outfile) {
                 exit(-1);
             }
 	} else if ( line[0] == 't' ) {
-	    /* starting a new triangle strip */
+	    // starting a new triangle strip
 
 	    printf("Starting a new triangle strip\n");
 
@@ -456,7 +455,7 @@ void obj_fix(char *infile, char *outfile) {
 	    printf("new tri strip = %s", line);
 	    sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
 
-	    /* special cases to handle bugs in our beloved tri striper */
+	    // special cases to handle bugs in our beloved tri striper
 	    if ( (n1 == 4) && (n2 == 2) && (n3 == 2) && (n4 == 1) ) {
 		n2 = 3;
 	    }
@@ -466,11 +465,11 @@ void obj_fix(char *infile, char *outfile) {
 
 	    dot_prod = check_cur_face(n1, n2, n3);
 	    if ( dot_prod < 0.0 ) {
-		/* this stripe is backwards (CW) */
+		// this stripe is backwards (CW)
 		is_ccw = 0;
 		printf(" -> Starting a backwards stripe\n");
 	    } else {
-		/* this stripe is normal (CCW) */
+		// this stripe is normal (CCW)
 		is_ccw = 1;
 	    }
 
@@ -501,7 +500,7 @@ void obj_fix(char *infile, char *outfile) {
 	    }
 	} else if ( line[0] == 'f' ) {
 	    if ( fcount < MAXNODES ) {
-		/* pass along the unoptimized faces verbatim */
+		// pass along the unoptimized faces verbatim
 		sscanf(line, "f %d %d %d\n", &n1, &n2, &n3);
 		faces[fcount][0] = n1;
 		faces[fcount][1] = n2;
@@ -515,10 +514,10 @@ void obj_fix(char *infile, char *outfile) {
  
 	    // fprintf(out, "%s", line);
 	} else if ( line[0] == 'q' ) {
-	    /* continue a triangle strip */
+	    // continue a triangle strip
 	    n1 = n2 = 0;
 
-	    /* printf("continued tri strip = %s ", line); */
+	    // printf("continued tri strip = %s ", line);
 	    sscanf(line, "q %d %d\n", &n1, &n2);
 
 	    if ( is_ccw ) {
@@ -539,12 +538,12 @@ void obj_fix(char *infile, char *outfile) {
 	}
     }
 
-    /* reference point is the "center" */
+    // reference point is the "center"
     refx = (xmin + xmax) / 2.0;
     refy = (ymin + ymax) / 2.0;
     refz = (zmin + zmax) / 2.0;
 
-    /* convert the cw_list to ccw add append to ccw_list */
+    // convert the cw_list to ccw add append to ccw_list
     fix_cw_list(cw_list, cw_list_ptr);
 
     dump_global_bounds();
@@ -561,57 +560,60 @@ void obj_fix(char *infile, char *outfile) {
 }
 
 
-/* $Log$
-/* Revision 1.16  1998/05/27 02:27:22  curt
-/* Commented out a couple of debugging messages.
-/*
- * Revision 1.15  1998/05/24 02:47:47  curt
- * For each strip, specify a default material property and calculate a center
- * and bounding sphere.
- *
- * Revision 1.14  1998/05/23 15:19:49  curt
- * Output more digits after the decimal place.
- *
- * Revision 1.13  1998/05/20 20:55:19  curt
- * Fixed arbitrary polygon winding problem here so all tristrips are passed
- * to runtime simulator with a consistant counter clockwise winding.
- *
- * Revision 1.12  1998/05/16 13:11:26  curt
- * Fixed an off by one error in node, normal, and face counters.
- *
- * Revision 1.11  1998/04/27 15:59:24  curt
- * Fixed an off by one error.
- *
- * Revision 1.10  1998/04/27 03:33:11  curt
- * Code now calculates a center reference points and outputs everything
- * relative to that.  This is useful in the rendering engine to keep everything
- * close to (0, 0, 0) where we can avoid many GLfloat precision problems.
- *
- * Revision 1.9  1998/04/18 04:01:03  curt
- * Now use libMath rather than having local copies of math routines.
- *
- * Revision 1.8  1998/04/08 23:19:37  curt
- * Adopted Gnu automake/autoconf system.
- *
- * Revision 1.7  1998/03/19 02:51:41  curt
- * Added special case handling to compensate for bugs in our beloved tri striper
- *
- * Revision 1.6  1998/03/03 15:36:12  curt
- * Tweaks for compiling with g++
- *
- * Revision 1.5  1998/03/03 03:37:03  curt
- * Cumulative tweaks.
- *
- * Revision 1.4  1998/01/31 00:41:25  curt
- * Made a few changes converting floats to doubles.
- *
- * Revision 1.3  1998/01/19 19:51:07  curt
- * A couple final pre-release tweaks.
- *
- * Revision 1.2  1998/01/09 23:03:12  curt
- * Restructured to split 1deg x 1deg dem's into 64 subsections.
- *
- * Revision 1.1  1997/12/08 19:28:54  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.1  1998/06/08 17:11:46  curt
+// Renamed *.[ch] to *.[ch]xx
+//
+// Revision 1.16  1998/05/27 02:27:22  curt
+// Commented out a couple of debugging messages.
+//
+// Revision 1.15  1998/05/24 02:47:47  curt
+// For each strip, specify a default material property and calculate a center
+// and bounding sphere.
+//
+// Revision 1.14  1998/05/23 15:19:49  curt
+// Output more digits after the decimal place.
+//
+// Revision 1.13  1998/05/20 20:55:19  curt
+// Fixed arbitrary polygon winding problem here so all tristrips are passed
+// to runtime simulator with a consistant counter clockwise winding.
+//
+// Revision 1.12  1998/05/16 13:11:26  curt
+// Fixed an off by one error in node, normal, and face counters.
+//
+// Revision 1.11  1998/04/27 15:59:24  curt
+// Fixed an off by one error.
+//
+// Revision 1.10  1998/04/27 03:33:11  curt
+// Code now calculates a center reference points and outputs everything
+// relative to that.  This is useful in the rendering engine to keep everything
+// close to (0, 0, 0) where we can avoid many GLfloat precision problems.
+//
+// Revision 1.9  1998/04/18 04:01:03  curt
+// Now use libMath rather than having local copies of math routines.
+//
+// Revision 1.8  1998/04/08 23:19:37  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.7  1998/03/19 02:51:41  curt
+// Added special case handling to compensate for bugs in our beloved tri striper
+//
+// Revision 1.6  1998/03/03 15:36:12  curt
+// Tweaks for compiling with g++
+//
+// Revision 1.5  1998/03/03 03:37:03  curt
+// Cumulative tweaks.
+//
+// Revision 1.4  1998/01/31 00:41:25  curt
+// Made a few changes converting floats to doubles.
+//
+// Revision 1.3  1998/01/19 19:51:07  curt
+// A couple final pre-release tweaks.
+//
+// Revision 1.2  1998/01/09 23:03:12  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.1  1997/12/08 19:28:54  curt
+// Initial revision.
+//
+
diff --git a/FixObj/obj.h b/FixObj/obj.h
deleted file mode 100644
index 4fd07f42f..000000000
--- a/FixObj/obj.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/**************************************************************************
- * obj.h -- routines to handle WaveFront .obj format files.
- *
- * Written by Curtis Olson, started October 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
-
-
-#ifndef OBJ_H
-#define OBJ_H
-
-
-#define MAXNODES 100000
-
-
-/* Load a .obj file */
-void obj_fix(char *infile, char *outfile);
-
-
-#endif /* OBJ_H */
-
-
-/* $Log$
-/* Revision 1.4  1998/03/03 15:36:13  curt
-/* Tweaks for compiling with g++
-/*
- * Revision 1.3  1998/01/31 00:41:25  curt
- * Made a few changes converting floats to doubles.
- *
- * Revision 1.2  1998/01/09 23:03:13  curt
- * Restructured to split 1deg x 1deg dem's into 64 subsections.
- *
- * Revision 1.1  1997/12/08 19:28:55  curt
- * Initial revision.
- *
- */
diff --git a/FixObj/obj.hxx b/FixObj/obj.hxx
new file mode 100644
index 000000000..59a362c8d
--- /dev/null
+++ b/FixObj/obj.hxx
@@ -0,0 +1,60 @@
+// obj.hxx -- routines to handle WaveFront .obj format files.
+//
+// Written by Curtis Olson, started October 1997.
+//
+// Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef OBJ_HXX
+#define OBJ_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#define MAXNODES 100000
+
+
+// Load a .obj file
+void obj_fix(char *infile, char *outfile);
+
+
+#endif // OBJ_HXX
+
+
+// $Log$
+// Revision 1.1  1998/06/08 17:11:46  curt
+// Renamed *.[ch] to *.[ch]xx
+//
+// Revision 1.4  1998/03/03 15:36:13  curt
+// Tweaks for compiling with g++
+//
+// Revision 1.3  1998/01/31 00:41:25  curt
+// Made a few changes converting floats to doubles.
+//
+// Revision 1.2  1998/01/09 23:03:13  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.1  1997/12/08 19:28:55  curt
+// Initial revision.
+//
+

From 0cda53d7eda6a2652011f90496dae03ae47286fd Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Jun 1998 17:18:37 +0000
Subject: [PATCH 108/283] Mods to test new Stripe fixes from Wilbur Streett.

---
 Tools/Makefile.am    |  2 +-
 Tools/process-dem.pl | 11 ++++++++---
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 9e51072b1..5c23d5bdc 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -8,7 +8,7 @@ SUBDIRS = \
 	FixNode \
 	FixObj \
 	SplitTris \
-	Stripe_u \
+	Stripe_w \
 	Tri2obj \
 	Triangle
 
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 31a4624cb..a169209ac 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -67,7 +67,7 @@ while ( $dem_file = shift(@ARGV) ) {
     if ( $do_dem2node ) {
 	dem2node() ;
     } else {
-	$subdir = "./work/Scenery/e010n080/e019n084";
+	$subdir = "./work/Scenery/w100n040/w093n045/";
 	print "WARNING:  Hardcoding subdir = $subdir\n";
     }
 
@@ -332,9 +332,10 @@ sub strips {
     foreach $file ( @FILES ) {
 	chop($file);
 	if ( $file =~ m/\.1\.obj$/ ) {
-	    $command = "Stripe_u/strips $subdir/$file";
+	    $command = "Stripe_w/strips $subdir/$file";
 	    $command = fix_command($command);
 	    print "Running '$command'\n";
+    	    # $input = <STDIN>;
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
 		print $_;
@@ -345,7 +346,8 @@ sub strips {
 	    $newfile = $file;
 	    $newfile =~ s/\.1\.obj$//;
 	    print "Copying to $subdir/$newfile.2.obj\n";
-	    open(IN, "<bands.d");
+	    # open(IN, "<bands.d");
+	    open(IN, "<stripe.objf");
 	    open(OUT, ">$subdir/$newfile.2.obj");
 	    while ( <IN> ) {
 		print OUT $_;
@@ -421,6 +423,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.21  1998/06/08 17:18:37  curt
+# Mods to test new Stripe fixes from Wilbur Streett.
+#
 # Revision 1.20  1998/06/05 18:20:24  curt
 # Added DemInfo to dump out "A" record DEM info.
 # Modified process-dem.pl to work in a temp directory and compress/copy the

From 57ce8bc91232b63584bf7b20822d596381074f8b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Jun 1998 16:55:24 +0000
Subject: [PATCH 109/283] Changed include order for <sys/types.h>

---
 FixNode/main.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/FixNode/main.cxx b/FixNode/main.cxx
index 2952d0cf8..9a3d3b32d 100644
--- a/FixNode/main.cxx
+++ b/FixNode/main.cxx
@@ -24,10 +24,10 @@
 //
 
 
+#include <sys/types.h>
 #include <dirent.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/types.h>
 
 #ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
@@ -108,6 +108,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.4  1998/06/27 16:55:24  curt
+// Changed include order for <sys/types.h>
+//
 // Revision 1.3  1998/04/26 05:02:06  curt
 // Added #ifdef HAVE_STDLIB_H
 //

From 4e4fbc21900294279ce34a54bd7433860a58c176 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 4 Jul 1998 00:47:18 +0000
Subject: [PATCH 110/283] typedef'd struct fgBUCKET.

---
 DEM/dem.cxx | 11 ++++++++---
 DEM/dem.hxx |  7 +++++--
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index b76f183b1..b00a3016d 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -518,7 +518,7 @@ double fgDEM::interpolate_altitude( double lon, double lat ) {
 
 
 // Use least squares to fit a simpler data set to dem data
-void fgDEM::fit( char *fg_root, double error, struct fgBUCKET *p ) {
+void fgDEM::fit( double error, fgBUCKET *p ) {
     double x[DEM_SIZE_1], y[DEM_SIZE_1];
     double m, b, ave_error, max_error;
     double cury, lasty;
@@ -648,7 +648,7 @@ void fgDEM::fit( char *fg_root, double error, struct fgBUCKET *p ) {
 	// printf("Please hit return: "); gets(junk);
     }
 
-    outputmesh_output_nodes(fg_root, p);
+    // outputmesh_output_nodes(fg_root, p);
 }
 
 
@@ -678,7 +678,7 @@ void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
 
 
 // Write out a node file that can be used by the "triangle" program
-void fgDEM::outputmesh_output_nodes( char *fg_root, struct fgBUCKET *p ) {
+void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
     struct stat stat_buf;
     char base_path[256], dir[256], file[256];
 #ifdef WIN32
@@ -776,10 +776,15 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, struct fgBUCKET *p ) {
 
 fgDEM::~fgDEM( void ) {
     // printf("class fgDEM DEstructor called.\n");
+    free(dem_data);
+    free(output_data);
 }
 
 
 // $Log$
+// Revision 1.8  1998/07/04 00:47:18  curt
+// typedef'd struct fgBUCKET.
+//
 // Revision 1.7  1998/06/05 18:14:39  curt
 // Abort out early when reading the "A" record if it doesn't look like
 // a proper DEM file.
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 31870b125..33eefc248 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -107,7 +107,7 @@ public:
     double interpolate_altitude( double lon, double lat );
 
     // Use least squares to fit a simpler data set to dem data
-    void fit( char *fg_root, double error, struct fgBUCKET *p );
+    void fit( double error, fgBUCKET *p );
 
     // Initialize output mesh structure
     void outputmesh_init( void );
@@ -119,7 +119,7 @@ public:
     void outputmesh_set_pt( int i, int j, double value );
 
     // Write out a node file that can be used by the "triangle" program
-    void outputmesh_output_nodes( char *fg_root, struct fgBUCKET *p );
+    void outputmesh_output_nodes( char *fg_root, fgBUCKET *p );
 
     // Destructor
     ~fgDEM( void );
@@ -130,6 +130,9 @@ public:
 
 
 // $Log$
+// Revision 1.7  1998/07/04 00:47:19  curt
+// typedef'd struct fgBUCKET.
+//
 // Revision 1.6  1998/06/05 18:14:40  curt
 // Abort out early when reading the "A" record if it doesn't look like
 // a proper DEM file.

From f019a9375796aedeb07b9d6dea230f055707362c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 4 Jul 1998 00:55:11 +0000
Subject: [PATCH 111/283] Added initial start at an Area generator.

---
 Tools/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 5c23d5bdc..e9c467985 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -1,6 +1,7 @@
 EXTRA_DIST = process-dem.pl
 
 SUBDIRS = \
+	Areas \
 	AssemTris \
 	Dem2node \
 	DemInfo \

From 2c3d44198cd50645a0701e8e3813033dbed93030 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 4 Jul 1998 00:55:39 +0000
Subject: [PATCH 112/283] typedef'd struct fgBUCKET.

---
 AssemTris/assemtris.c | 15 +++++++++------
 SplitTris/splittris.c | 13 ++++++++-----
 Tri2obj/tri2obj.c     | 13 ++++++++-----
 3 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index fcab575b6..1eaa56c5a 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -44,9 +44,9 @@ int nodecount = 0;
 static double nodes[MAX_NODES][3];
 
 
-struct fgBUCKET my_index;
-struct fgBUCKET ne_index, nw_index, sw_index, se_index;
-struct fgBUCKET north_index, south_index, east_index, west_index;
+fgBUCKET my_index;
+fgBUCKET ne_index, nw_index, sw_index, se_index;
+fgBUCKET north_index, south_index, east_index, west_index;
 
 
 /* return the file base name ( foo/bar/file.ext = file.ext ) */
@@ -462,10 +462,13 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.8  1998/06/01 17:58:19  curt
-/* Added a slight border overlap to try to minimize pixel wide gaps between
-/* tiles due to round off error.  This is not a perfect solution, but helps.
+/* Revision 1.9  1998/07/04 00:55:39  curt
+/* typedef'd struct fgBUCKET.
 /*
+ * Revision 1.8  1998/06/01 17:58:19  curt
+ * Added a slight border overlap to try to minimize pixel wide gaps between
+ * tiles due to round off error.  This is not a perfect solution, but helps.
+ *
  * Revision 1.7  1998/04/14 02:26:00  curt
  * Code reorganizations.  Added a Lib/ directory for more general libraries.
  *
diff --git a/SplitTris/splittris.c b/SplitTris/splittris.c
index c40000794..66810f225 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.c
@@ -51,8 +51,8 @@ static int tris[MAX_TRIS][3];
 
 static fgCartesianPoint3d nodes_cart[MAX_NODES];
 
-struct fgBUCKET ne_index, nw_index, sw_index, se_index;
-struct fgBUCKET north_index, south_index, east_index, west_index;
+fgBUCKET ne_index, nw_index, sw_index, se_index;
+fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
@@ -564,7 +564,7 @@ void dump_obj(char *basename, char *basepath) {
 
 int main(int argc, char **argv) {
     char basename[256], basepath[256], temp[256];
-    struct fgBUCKET p;
+    fgBUCKET p;
     long int index;
     int len;
 
@@ -616,9 +616,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.10  1998/05/02 01:54:37  curt
-/* Converting to polar3d.h routines.
+/* Revision 1.11  1998/07/04 00:56:40  curt
+/* typedef'd struct fgBUCKET.
 /*
+ * Revision 1.10  1998/05/02 01:54:37  curt
+ * Converting to polar3d.h routines.
+ *
  * Revision 1.9  1998/04/18 04:01:20  curt
  * Now use libMath rather than having local copies of math routines.
  *
diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.c
index 071c0e359..f5a1a09f1 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.c
@@ -48,9 +48,9 @@ static int tris[MAX_TRIS][3];
 
 static double normals[MAX_NODES][3];
 
-struct fgBUCKET my_index;
-struct fgBUCKET ne_index, nw_index, sw_index, se_index;
-struct fgBUCKET north_index, south_index, east_index, west_index;
+fgBUCKET my_index;
+fgBUCKET ne_index, nw_index, sw_index, se_index;
+fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
@@ -644,9 +644,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.16  1998/05/23 15:20:41  curt
-/* Output more digits after the decimal place.
+/* Revision 1.17  1998/07/04 00:56:40  curt
+/* typedef'd struct fgBUCKET.
 /*
+ * Revision 1.16  1998/05/23 15:20:41  curt
+ * Output more digits after the decimal place.
+ *
  * Revision 1.15  1998/05/02 01:54:39  curt
  * Converting to polar3d.h routines.
  *

From 14ed0c8fa8d8bfc9d34e7f24ecfbdc67d46efb77 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 8 Jul 1998 14:49:13 +0000
Subject: [PATCH 113/283] tweaks.

---
 SplitTris/Makefile.am | 5 ++++-
 Tools/process-dem.pl  | 5 ++++-
 Tri2obj/Makefile.am   | 5 ++++-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/SplitTris/Makefile.am b/SplitTris/Makefile.am
index e928787d7..be4d06c8f 100644
--- a/SplitTris/Makefile.am
+++ b/SplitTris/Makefile.am
@@ -26,7 +26,7 @@
 
 bin_PROGRAMS = splittris
 
-splittris_SOURCES = splittris.c splittris.h
+splittris_SOURCES = splittris.cxx splittris.hxx
 
 splittris_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.la \
@@ -39,6 +39,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/07/08 14:49:13  curt
+# tweaks.
+#
 # Revision 1.4  1998/04/24 00:44:06  curt
 # Added zlib support.
 #
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index a169209ac..adca9c3d3 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -40,7 +40,7 @@ $do_triangle_2 = 1;
 $do_tri2obj =    1;
 $do_strips =     1;
 $do_fixobj =     1;
-
+ 
 $do_install =    1;
 
 
@@ -423,6 +423,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.22  1998/07/08 14:49:13  curt
+# tweaks.
+#
 # Revision 1.21  1998/06/08 17:18:37  curt
 # Mods to test new Stripe fixes from Wilbur Streett.
 #
diff --git a/Tri2obj/Makefile.am b/Tri2obj/Makefile.am
index 86b10ba82..e0ea71e5b 100644
--- a/Tri2obj/Makefile.am
+++ b/Tri2obj/Makefile.am
@@ -26,7 +26,7 @@
 
 bin_PROGRAMS = tri2obj
 
-tri2obj_SOURCES = tri2obj.c tri2obj.h
+tri2obj_SOURCES = tri2obj.cxx tri2obj.hxx
 
 tri2obj_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.la \
@@ -39,6 +39,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/07/08 14:49:14  curt
+# tweaks.
+#
 # Revision 1.4  1998/04/24 00:44:07  curt
 # Added zlib support.
 #

From 4267b78a4d04be6e10c19063dadcde2504924a47 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 8 Jul 1998 14:54:52 +0000
Subject: [PATCH 114/283] renamed *.[ch] to *.[ch]xx

---
 Tri2obj/{tri2obj.c => tri2obj.cxx} | 25 ++++++++++++++-----------
 Tri2obj/{tri2obj.h => tri2obj.hxx} |  7 +++++--
 2 files changed, 19 insertions(+), 13 deletions(-)
 rename Tri2obj/{tri2obj.c => tri2obj.cxx} (97%)
 rename Tri2obj/{tri2obj.h => tri2obj.hxx} (92%)

diff --git a/Tri2obj/tri2obj.c b/Tri2obj/tri2obj.cxx
similarity index 97%
rename from Tri2obj/tri2obj.c
rename to Tri2obj/tri2obj.cxx
index f5a1a09f1..732da5c03 100644
--- a/Tri2obj/tri2obj.c
+++ b/Tri2obj/tri2obj.cxx
@@ -30,7 +30,7 @@
 #include <sys/stat.h> /* for stat() */
 #include <unistd.h>   /* for stat() */
 
-#include "tri2obj.h"
+#include "tri2obj.hxx"
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
@@ -38,12 +38,12 @@
 
 #include <Math/fg_geodesy.h>
 #include <Math/mat3.h>
-#include <Math/polar3d.h>
+#include <Math/polar3d.hxx>
 
 
 int nodecount, tricount;
 int normalcount = 0;
-static fgCartesianPoint3d nodes[MAX_NODES];
+static fgPoint3d nodes[MAX_NODES];
 static int tris[MAX_TRIS][3];
 
 static double normals[MAX_NODES][3];
@@ -54,9 +54,9 @@ fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
-fgCartesianPoint3d geod_to_cart(double geod[3]) {
-    fgCartesianPoint3d cp;
-    fgPolarPoint3d pp;
+fgPoint3d geod_to_cart(double geod[3]) {
+    fgPoint3d cp;
+    fgPoint3d pp;
     double gc_lon, gc_lat, sl_radius;
 
     /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
@@ -70,7 +70,7 @@ fgCartesianPoint3d geod_to_cart(double geod[3]) {
 
     pp.lon = gc_lon;
     pp.lat = gc_lat;
-    pp.radius = sl_radius+geod[2];
+    pp.radius = sl_radius + geod[2];
     cp = fgPolarToCart3d(pp);
     
     /* printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z); */
@@ -80,8 +80,8 @@ fgCartesianPoint3d geod_to_cart(double geod[3]) {
 
 
 /* given three points defining a triangle, calculate the normal */
-void calc_normal(fgCartesianPoint3d p1, fgCartesianPoint3d p2, 
-		 fgCartesianPoint3d p3, double normal[3])
+void calc_normal(fgPoint3d p1, fgPoint3d p2, 
+		 fgPoint3d p3, double normal[3])
 {
     double v1[3], v2[3];
     double temp;
@@ -644,9 +644,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.17  1998/07/04 00:56:40  curt
-/* typedef'd struct fgBUCKET.
+/* Revision 1.1  1998/07/08 14:54:53  curt
+/* renamed *.[ch] to *.[ch]xx
 /*
+ * Revision 1.17  1998/07/04 00:56:40  curt
+ * typedef'd struct fgBUCKET.
+ *
  * Revision 1.16  1998/05/23 15:20:41  curt
  * Output more digits after the decimal place.
  *
diff --git a/Tri2obj/tri2obj.h b/Tri2obj/tri2obj.hxx
similarity index 92%
rename from Tri2obj/tri2obj.h
rename to Tri2obj/tri2obj.hxx
index e53ae1d0d..c7a54d159 100644
--- a/Tri2obj/tri2obj.h
+++ b/Tri2obj/tri2obj.hxx
@@ -44,9 +44,12 @@ void triload(char *basename, char *basepath);
 
 
 /* $Log$
-/* Revision 1.5  1998/03/03 16:01:00  curt
-/* More c++ compile tweaks.
+/* Revision 1.1  1998/07/08 14:54:54  curt
+/* renamed *.[ch] to *.[ch]xx
 /*
+ * Revision 1.5  1998/03/03 16:01:00  curt
+ * More c++ compile tweaks.
+ *
  * Revision 1.4  1998/01/17 01:25:40  curt
  * Added support for shared normals.
  *

From 00276b769b54b1eb5d83e071ab42225676a95adb Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 8 Jul 1998 14:59:13 +0000
Subject: [PATCH 115/283] *.[ch] renamed to *.[ch]xx

---
 SplitTris/{splittris.c => splittris.cxx} | 25 +++++++++++++-----------
 SplitTris/{splittris.h => splittris.hxx} | 17 +++++++++-------
 2 files changed, 24 insertions(+), 18 deletions(-)
 rename SplitTris/{splittris.c => splittris.cxx} (97%)
 rename SplitTris/{splittris.h => splittris.hxx} (76%)

diff --git a/SplitTris/splittris.c b/SplitTris/splittris.cxx
similarity index 97%
rename from SplitTris/splittris.c
rename to SplitTris/splittris.cxx
index 66810f225..27ad59954 100644
--- a/SplitTris/splittris.c
+++ b/SplitTris/splittris.cxx
@@ -32,7 +32,7 @@
 #include <sys/stat.h> /* for stat() */
 #include <unistd.h>   /* for stat() */
 
-#include "splittris.h"
+#include "splittris.hxx"
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
@@ -40,7 +40,7 @@
 
 #include <Math/fg_geodesy.h>
 #include <Math/mat3.h>
-#include <Math/polar3d.h>
+#include <Math/polar3d.hxx>
 
 int nodecount, tricount;
 double xmin, xmax, ymin, ymax;
@@ -49,16 +49,16 @@ static double nodes_orig[MAX_NODES][3];
 static int tris[MAX_TRIS][3];
 /* static int new_tris[MAX_TRIS][3]; */
 
-static fgCartesianPoint3d nodes_cart[MAX_NODES];
+static fgPoint3d nodes_cart[MAX_NODES];
 
 fgBUCKET ne_index, nw_index, sw_index, se_index;
 fgBUCKET north_index, south_index, east_index, west_index;
 
 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
  * a cartesian point */
-fgCartesianPoint3d geod_to_cart(double geod[3]) {
-    fgCartesianPoint3d cp;
-    fgPolarPoint3d pp;
+fgPoint3d geod_to_cart(double geod[3]) {
+    fgPoint3d cp;
+    fgPoint3d pp;
     double gc_lon, gc_lat, sl_radius;
 
     /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
@@ -72,7 +72,7 @@ fgCartesianPoint3d geod_to_cart(double geod[3]) {
 
     pp.lon = gc_lon;
     pp.lat = gc_lat;
-    pp.radius = sl_radius+geod[2];
+    pp.radius = sl_radius + geod[2];
     cp = fgPolarToCart3d(pp);
     
     /* printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z); */
@@ -82,8 +82,8 @@ fgCartesianPoint3d geod_to_cart(double geod[3]) {
 
 
 /* given three points defining a triangle, calculate the normal */
-void calc_normal(fgCartesianPoint3d p1, fgCartesianPoint3d p2, 
-		 fgCartesianPoint3d p3, double normal[3])
+void calc_normal(fgPoint3d p1, fgPoint3d p2, 
+		 fgPoint3d p3, double normal[3])
 {
     double v1[3], v2[3];
     double temp;
@@ -616,9 +616,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.11  1998/07/04 00:56:40  curt
-/* typedef'd struct fgBUCKET.
+/* Revision 1.1  1998/07/08 14:59:13  curt
+/* *.[ch] renamed to *.[ch]xx
 /*
+ * Revision 1.11  1998/07/04 00:56:40  curt
+ * typedef'd struct fgBUCKET.
+ *
  * Revision 1.10  1998/05/02 01:54:37  curt
  * Converting to polar3d.h routines.
  *
diff --git a/SplitTris/splittris.h b/SplitTris/splittris.hxx
similarity index 76%
rename from SplitTris/splittris.h
rename to SplitTris/splittris.hxx
index 6ed50d672..60d6dba99 100644
--- a/SplitTris/splittris.h
+++ b/SplitTris/splittris.hxx
@@ -1,5 +1,5 @@
-/* splittris.h -- read in a .ele/.node file pair generated by the triangle 
- *                program and output edge vertices w/ normals.
+/* splittris.hxx -- read in a .ele/.node file pair generated by the triangle 
+ *                  program and output edge vertices w/ normals.
  *
  * Written by Curtis Olson, started January 1998.
  *
@@ -24,8 +24,8 @@
  */
 
 
-#ifndef SPLITTRIS_H
-#define SPLITTRIS_H
+#ifndef SPLITTRIS_HXX
+#define SPLITTRIS_HXX
 
 
 #include <stdio.h>
@@ -43,13 +43,16 @@ extern int nodecount, tricount;
 void triload(char *basename);
 
 
-#endif /* SPLITTRIS_H */
+#endif /* SPLITTRIS_HXX */
 
 
 /* $Log$
-/* Revision 1.3  1998/03/03 15:36:13  curt
-/* Tweaks for compiling with g++
+/* Revision 1.1  1998/07/08 14:59:14  curt
+/* *.[ch] renamed to *.[ch]xx
 /*
+ * Revision 1.3  1998/03/03 15:36:13  curt
+ * Tweaks for compiling with g++
+ *
  * Revision 1.2  1998/01/15 02:49:25  curt
  * Misc. housekeeping.
  *

From 0e952432f1665dc93534b2181e444be8d4e2e57b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 13 Jul 1998 15:29:49 +0000
Subject: [PATCH 116/283] Added #ifdef HAVE_CONFIG_H

---
 DEM/dem.cxx | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index b00a3016d..52612143a 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -24,6 +24,10 @@
 // (Log is kept at end of this file)
 
 
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <ctype.h>    // isspace()
 #include <math.h>     // rint()
 #include <stdio.h>
@@ -782,6 +786,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.9  1998/07/13 15:29:49  curt
+// Added #ifdef HAVE_CONFIG_H
+//
 // Revision 1.8  1998/07/04 00:47:18  curt
 // typedef'd struct fgBUCKET.
 //

From 0294f8da003c24109abad032dceb50cf002f31b9 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 13 Jul 1998 20:58:02 +0000
Subject: [PATCH 117/283] .

---
 DEM/dem.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 52612143a..57a997367 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -29,9 +29,9 @@
 #endif
 
 #include <ctype.h>    // isspace()
+#include <stdlib.h>   // atoi()
 #include <math.h>     // rint()
 #include <stdio.h>
-#include <stdlib.h>   // atoi()
 #include <string.h>
 #include <sys/stat.h> // stat()
 #include <unistd.h>   // stat()
@@ -786,6 +786,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.10  1998/07/13 20:58:02  curt
+// .
+//
 // Revision 1.9  1998/07/13 15:29:49  curt
 // Added #ifdef HAVE_CONFIG_H
 //

From c4666a4c4aa4b9485d549a1380b90d7529acc3bf Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 20 Jul 1998 12:46:11 +0000
Subject: [PATCH 118/283] When outputing to a .node file, first check for an
 optional "index.node.ex" file in case there is a .poly file to go along with
 this node file.  Include these nodes first since they are referenced by
 position from the .poly file.  This is my first pass at adding an area
 "cutout" feature to the terrain generation pipeline.

---
 DEM/dem.cxx | 60 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 53 insertions(+), 7 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 57a997367..e47906808 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -44,6 +44,8 @@
 #include <Include/fg_constants.h>
 
 
+#define MAX_EX_NODES 10000
+
 #ifdef WIN32
 #  define MKDIR(a) mkdir(a,S_IRWXU)     // I am just guessing at this flag (NHV)
 #endif // WIN32
@@ -681,10 +683,15 @@ void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
 }
 
 
-// Write out a node file that can be used by the "triangle" program
+// Write out a node file that can be used by the "triangle" program.
+// Check for an optional "index.node.ex" file in case there is a .poly
+// file to go along with this node file.  Include these nodes first
+// since they are referenced by position from the .poly file.
 void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
+    double exnodes[MAX_EX_NODES][3];
+    double junk1, junk2, junk3;
     struct stat stat_buf;
-    char base_path[256], dir[256], file[256];
+    char base_path[256], dir[256], file[256], exfile[256];
 #ifdef WIN32
     char tmp_path[256];
 #endif
@@ -692,7 +699,7 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
     FILE *fd;
     long int index;
     int colmin, colmax, rowmin, rowmax;
-    int i, j, count, result;
+    int i, j, count, excount, result;
 
     // determine dimensions
     colmin = p->x * ( (cols - 1) / 8);
@@ -744,10 +751,36 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
     index = fgBucketGenIndex(p);
     sprintf(file, "%s/%ld.node", dir, index);
 
+    // get (optional) extra node file name (in case there is matching
+    // .poly file.
+    strcpy(exfile, file);
+    strcat(exfile, ".ex");
+
+    // load extra nodes if they exist
+    excount = 0;
+    if ( (fd = fopen(exfile, "r")) != NULL ) {
+	fscanf(fd, "%d %d %d %d", &excount, &junk1, &junk2, &junk3);
+
+	if ( excount > MAX_EX_NODES - 1 ) {
+	    printf("Error, too many 'extra' nodes, increase array size\n");
+	    exit(-1);
+	} else {
+	    printf("    Expecting %d 'extra' nodes\n", excount);
+	}
+
+	for ( i = 1; i <= excount; i++ ) {
+	    fscanf(fd, "%d %lf %lf %lf\n", &junk1, 
+		   &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]);
+	    printf("(extra) %d %.2f %.2f %.2f\n", 
+		    i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
+	}
+    }
+    fclose(fd);
+
     printf("Creating node file:  %s\n", file);
     fd = fopen(file, "w");
 
-    // first count nodes to generate header
+    // first count regular nodes to generate header
     count = 0;
     for ( j = rowmin; j <= rowmax; j++ ) {
 	for ( i = colmin; i <= colmax; i++ ) {
@@ -757,10 +790,16 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
 	}
 	// printf("    count = %d\n", count);
     }
-    fprintf(fd, "%d 2 1 0\n", count);
+    fprintf(fd, "%d 2 1 0\n", count + excount);
 
-    // now write out actual node data
-    count = 1;
+    // now write out extra node data
+    for ( i = 1; i <= excount; i++ ) {
+	fprintf(fd, "%d %.2f %.2f %.2f\n", 
+		i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
+    }
+
+    // write out actual node data
+    count = excount + 1;
     for ( j = rowmin; j <= rowmax; j++ ) {
 	for ( i = colmin; i <= colmax; i++ ) {
 	    if ( output_data[i][j] > -9000.0 ) {
@@ -786,6 +825,13 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.11  1998/07/20 12:46:11  curt
+// When outputing to a .node file, first check for an optional
+// "index.node.ex" file in case there is a .poly file to go along with this
+// node file.  Include these nodes first since they are referenced by position
+// from the .poly file.  This is my first pass at adding an area "cutout"
+// feature to the terrain generation pipeline.
+//
 // Revision 1.10  1998/07/13 20:58:02  curt
 // .
 //

From 8f14bf2e84b6480ede16c5b34a284bf34dfd69cc Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 20 Jul 1998 12:54:05 +0000
Subject: [PATCH 119/283] Initial revision.

---
 Areas/Makefile | 380 +++++++++++++++++++++++++++++++++++++++++++++++++
 Areas/area.cxx | 161 +++++++++++++++++++++
 Areas/area.hxx |  57 ++++++++
 Areas/main.cxx | 130 +++++++++++++++++
 4 files changed, 728 insertions(+)
 create mode 100644 Areas/Makefile
 create mode 100644 Areas/area.cxx
 create mode 100644 Areas/area.hxx
 create mode 100644 Areas/main.cxx

diff --git a/Areas/Makefile b/Areas/Makefile
new file mode 100644
index 000000000..8df2b17e9
--- /dev/null
+++ b/Areas/Makefile
@@ -0,0 +1,380 @@
+# Generated automatically from Makefile.in by configure.
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ../..
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = /opt/X11R6/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/FlightGear
+pkglibdir = $(libdir)/FlightGear
+pkgincludedir = $(includedir)/FlightGear
+
+top_builddir = ../..
+
+ACLOCAL = aclocal
+AUTOCONF = autoconf
+AUTOMAKE = automake
+AUTOHEADER = autoheader
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+transform = s,x,x,
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = i586-pc-linux-gnulibc1
+host_triplet = i586-pc-linux-gnulibc1
+CC = gcc
+CXX = c++
+LD = /usr/bin/ld
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LN_S = ln -s
+MAINT = #M#
+MAKEINFO = /amd/wiley/export/home/curt/projects/FlightGear/missing makeinfo
+NM = /usr/bin/nm -B
+PACKAGE = FlightGear
+RANLIB = ranlib
+VERSION = 0.51
+
+bin_PROGRAMS = areas
+
+areas_SOURCES = area.cxx area.hxx main.cxx
+
+areas_LDADD = $(top_builddir)/Lib/Bucket/libBucket.la
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Include/config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = -DHAVE_CONFIG_H -I. -I$(srcdir) -I../../Include
+CPPFLAGS = -I/usr/local/include -I/usr/X11R6/include
+LDFLAGS = -L/usr/local/lib -L/usr/X11R6/lib
+LIBS = -lglut -lMesaGLU -lMesaGL -lXmu -lXt -lSM -lICE -lXi -lXext -lX11 -lm 
+X_CFLAGS =  -I/usr/X11R6/include
+X_LIBS =  -L/usr/X11R6/lib
+X_EXTRA_LIBS = 
+X_PRE_LIBS =  -lSM -lICE
+areas_OBJECTS =  area.o main.o
+areas_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
+areas_LDFLAGS = 
+CXXFLAGS = -Wall
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  README Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES =  .deps/area.P .deps/main.P
+CXXMKDEP = $(CXX) -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
+SOURCES = $(areas_SOURCES)
+OBJECTS = $(areas_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .cxx .lo .o .s
+$(srcdir)/Makefile.in: #M# Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Areas/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+areas: $(areas_OBJECTS) $(areas_DEPENDENCIES)
+	@rm -f areas
+	$(CXXLINK) $(areas_LDFLAGS) $(areas_OBJECTS) $(areas_LDADD) $(LIBS)
+.cxx.o:
+	$(CXXCOMPILE) -c $<
+.cxx.lo:
+	$(LTCXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/Areas
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Areas/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  test -f $(distdir)/$$file \
+	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	  || cp -p $$d/$$file $(distdir)/$$file; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+	-rm -rf .deps
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+
+%.o: %.cxx
+	@echo '$(CXXCOMPILE) -c $<'; \
+	$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.cxx
+	@echo '$(LTCXXCOMPILE) -c $<'; \
+	$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+	  < .deps/$(*F).p > .deps/$(*F).P
+	@-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+	$(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+	@$(NORMAL_INSTALL)
+
+install-data: 
+	@$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+	@:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+	$(mkinstalldirs)  $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean
+
+distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic clean
+	-rm -f config.status
+	-rm -f libtool
+
+maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-libtool maintainer-clean-tags \
+		maintainer-clean-depend maintainer-clean-generic \
+		distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/07/20 12:54:05  curt
+# Initial revision.
+#
+# Revision 1.2  1998/04/14 02:25:59  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
+# Revision 1.1  1998/04/08 22:54:57  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.2  1998/01/21 02:55:46  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1998/01/15 02:45:25  curt
+# Initial revision.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Areas/area.cxx b/Areas/area.cxx
new file mode 100644
index 000000000..2dabe331d
--- /dev/null
+++ b/Areas/area.cxx
@@ -0,0 +1,161 @@
+// area.c -- routines to assist with inserting "areas" into FG terrain
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#include <math.h>
+#include <stdio.h>
+
+#include <Include/fg_constants.h>
+
+#include "area.hxx"
+
+
+// calc new x, y for a rotation
+double rot_x(double x, double y, double theta) {
+    return ( x * cos(theta) + y * sin(theta) );
+}
+
+
+// calc new x, y for a rotation
+double rot_y(double x, double y, double theta) {
+    return ( -x * sin(theta) + y * cos(theta) );
+}
+
+
+// calc new lon/lat given starting lon/lat, and offset radial, and
+// distance.  NOTE: distance is specified in meters (and converted
+// internally to radians)
+point2d calc_lon_lat( point2d orig, point2d offset ) {
+    point2d result;
+
+    offset.dist *= METER_TO_NM * NM_TO_RAD;
+
+    result.lat = asin( sin(orig.lat) * cos(offset.dist) + 
+		       cos(orig.lat) * sin(offset.dist) * cos(offset.theta) );
+
+    if ( cos(result.lat) < FG_EPSILON ) {
+        result.lon = orig.lon;      // endpoint a pole
+    } else {
+        result.lon = 
+	    fmod(orig.lon - asin( sin(offset.theta) * sin(offset.dist) / 
+				  cos(result.lat) ) + FG_PI, FG_2PI) - FG_PI;
+    }
+
+    return(result);
+}
+
+
+point2d cart_to_polar_2d(point2d in) {
+    point2d result;
+    result.dist = sqrt( in.x * in.x + in.y * in.y );
+    result.theta = atan2(in.y, in.x);    
+
+    return(result);
+}
+
+
+void batch_cart_to_polar_2d(point2d *in, point2d *out, int size) {
+    int i;
+
+    for ( i = 0; i < size; i++ ) {
+	out[i] = cart_to_polar_2d( in[i] );
+    }
+}
+
+
+// given a set of 2d coordinates relative to a center point, and the
+// lon, lat of that center point, as well as a potential orientation
+// angle, generate the corresponding lon and lat of the original 2d
+// verticies.
+void make_area(point2d orig, point2d *cart, point2d *result, 
+	       int size, double angle ) {
+    point2d rad[size];
+    int i;
+
+    // convert to polar coordinates
+    batch_cart_to_polar_2d(cart, rad, size);
+    for ( i = 0; i < size; i++ ) {
+	printf("(%.2f, %.2f)\n", rad[i].dist, rad[i].theta);
+    }
+    printf("\n");
+
+    // rotate by specified angle
+    for ( i = 0; i < size; i++ ) {
+	rad[i].theta += angle;
+	while ( rad[i].theta > FG_2PI ) {
+	    rad[i].theta -= FG_2PI;
+	}
+	printf("(%.2f, %.2f)\n", rad[i].dist, rad[i].theta);
+    }
+    printf("\n");
+
+    for ( i = 0; i < size; i++ ) {
+	result[i] = calc_lon_lat(orig, rad[i]);
+	printf("(%.8f, %.8f)\n", result[i].lon, result[i].lat);
+    }
+    printf("\n");
+}
+
+
+// generate an area for a runway
+void gen_runway_area( double lon, double lat, double heading, 
+		      double length, double width,
+		      point2d *result, int *count) 
+{
+    point2d cart[4];
+    point2d orig;
+    double l, w;
+    int i;
+
+    orig.lon = lon;
+    orig.lat = lat;
+    l = (length / 2.0) + (length * 0.1);
+    w = (width / 2.0) + (width * 0.1);
+
+    // generate untransformed runway area vertices
+    cart[0].x =  l; cart[0].y =  w;
+    cart[1].x =  l; cart[1].y = -w;
+    cart[2].x = -l; cart[2].y = -w;
+    cart[3].x = -l; cart[3].y =  w;
+    for ( i = 0; i < 4; i++ ) {
+	printf("(%.2f, %.2f)\n", cart[i].x, cart[i].y);
+    }
+    printf("\n");
+
+    make_area(orig, cart, result, 4, heading);
+
+    for ( i = 0; i < 4; i++ ) {
+	printf("(%.8f, %.8f)\n", result[i].lon, result[i].lat);
+    }
+    printf("\n");
+
+    *count = 4;
+}
+
+
+// $Log$
+// Revision 1.1  1998/07/20 12:54:05  curt
+// Initial revision.
+//
+//
diff --git a/Areas/area.hxx b/Areas/area.hxx
new file mode 100644
index 000000000..584e5f6a0
--- /dev/null
+++ b/Areas/area.hxx
@@ -0,0 +1,57 @@
+// area.h -- routines to assist with inserting "areas" into FG terrain
+//
+// Written by Curtis Olson, started February 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#ifndef _AREA_H
+#define _AREA_H
+
+
+typedef struct {
+    union {
+	double x;
+	double dist;
+	double lon;
+    };
+    union {
+	double y;
+	double theta;
+	double lat;
+    };
+} point2d;
+
+
+// generate an area for a runway
+void gen_runway_area( double lon, double lat, double heading, 
+		      double length, double width,
+		      point2d *result, int *count );
+
+
+#endif // _AREA_H
+
+
+// $Log$
+// Revision 1.1  1998/07/20 12:54:05  curt
+// Initial revision.
+//
+//
diff --git a/Areas/main.cxx b/Areas/main.cxx
new file mode 100644
index 000000000..1f6d635b8
--- /dev/null
+++ b/Areas/main.cxx
@@ -0,0 +1,130 @@
+// main.c -- main loop
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "area.hxx"
+
+#include <Bucket/bucketutils.h>
+#include <Include/fg_constants.h>
+
+
+int main( int argc, char **argv ) {
+    fgBUCKET b;
+    point2d nodes[4];
+    FILE *fd;
+    char base[256], path[256], command[256], file[256], exfile[256];
+    double lon, lat, elevation, heading;
+    double length, width;
+    long int index;
+    int i, count;
+
+    if ( argc != 2 ) {
+	printf("Usage %s <work dir>\n", argv[0]);
+	exit(0);
+    }
+
+    // P13 (Globe, AZ)
+    // lon = -110.6642442;
+    // lat = 33.3528903;
+    // heading = 102.0 * DEG_TO_RAD;
+    // length = 1769;
+    // width = 23;
+
+    // KANE
+    lon = -93.2113889;
+    lat = 45.145;
+    elevation = 912 * FEET_TO_METER;
+    heading = 270.0 * DEG_TO_RAD;
+    length = 1220;
+    width = 23;
+
+    gen_runway_area( lon * DEG_TO_RAD, lat * DEG_TO_RAD, 
+		     heading, length, width, nodes, &count );
+
+    fgBucketFind(lon, lat, &b);
+    printf( "Bucket = lon,lat = %d,%d  x,y index = %d,%d\n", 
+	    b.lon, b.lat, b.x, b.y);
+
+    index = fgBucketGenIndex(&b);
+    fgBucketGenBasePath(&b, base);
+    sprintf(path, "%s/Scenery/%s", argv[1], base);
+    sprintf(command, "mkdir -p %s\n", path);
+    system(command);
+    
+    sprintf(exfile, "%s/%ld.node.ex", path, index);
+    sprintf(file, "%s/%ld.poly", path, index);
+    printf( "extra node file = %s\n", exfile);
+    printf( "poly file = %s\n", file);
+
+    // output extra nodes
+    if ( (fd = fopen(exfile, "w")) == NULL ) {
+        printf("Cannot open file: %s\n", exfile);
+        exit(-1);
+    }
+
+    fprintf(fd, "%d 2 0 0\n", count);
+    for ( i = 0; i < count; i++ ) {
+	fprintf( fd, "%d %.2f %.2f %.2f\n", i + 1, 
+		 nodes[i].lon * RAD_TO_ARCSEC, nodes[i].lat * RAD_TO_ARCSEC, 
+		 elevation);
+    }
+    fclose(fd);
+
+    // output poly
+    if ( (fd = fopen(file, "w")) == NULL ) {
+        printf("Cannot open file: %s\n", file);
+        exit(-1);
+    }
+
+    // output empty node list
+    fprintf(fd, "0 2 0 0\n");
+
+    // output segments
+    fprintf(fd, "%d 0\n", count);
+    for ( i = 0; i < count - 1; i++ ) {
+	fprintf( fd, "%d %d %d\n", i + 1, i + 1, i + 2 );
+    }
+    fprintf( fd, "%d %d %d\n", count, count, 1 );
+
+    // output hole center
+    fprintf( fd, "1\n");
+    fprintf( fd, "1 %.2f %.2f\n", lon * 3600.0, lat * 3600);
+
+    fclose(fd);
+}
+
+
+// $Log: main.c,v
+//

From 662648f3497fc682a70c6ac64b22a5801ff3837a Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 20 Jul 1998 12:54:53 +0000
Subject: [PATCH 120/283] Whoops, need to commit Makefile.am, not Makefile.

---
 Areas/Makefile    | 380 ----------------------------------------------
 Areas/Makefile.am |  53 +++++++
 2 files changed, 53 insertions(+), 380 deletions(-)
 delete mode 100644 Areas/Makefile
 create mode 100644 Areas/Makefile.am

diff --git a/Areas/Makefile b/Areas/Makefile
deleted file mode 100644
index 8df2b17e9..000000000
--- a/Areas/Makefile
+++ /dev/null
@@ -1,380 +0,0 @@
-# Generated automatically from Makefile.in by configure.
-# Makefile.in generated automatically by automake 1.2h from Makefile.am
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#---------------------------------------------------------------------------
-# Makefile
-#
-# Written by Curtis Olson, started January 1998.
-#
-# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id$
-# (Log is kept at end of this file)
-#---------------------------------------------------------------------------
-
-
-SHELL = /bin/sh
-
-srcdir = .
-top_srcdir = ../..
-prefix = /usr/local
-exec_prefix = ${prefix}
-
-bindir = ${exec_prefix}/bin
-sbindir = ${exec_prefix}/sbin
-libexecdir = ${exec_prefix}/libexec
-datadir = ${prefix}/share
-sysconfdir = ${prefix}/etc
-sharedstatedir = ${prefix}/com
-localstatedir = ${prefix}/var
-libdir = /opt/X11R6/lib
-infodir = ${prefix}/info
-mandir = ${prefix}/man
-includedir = ${prefix}/include
-oldincludedir = /usr/include
-
-DISTDIR =
-
-pkgdatadir = $(datadir)/FlightGear
-pkglibdir = $(libdir)/FlightGear
-pkgincludedir = $(includedir)/FlightGear
-
-top_builddir = ../..
-
-ACLOCAL = aclocal
-AUTOCONF = autoconf
-AUTOMAKE = automake
-AUTOHEADER = autoheader
-
-INSTALL = /usr/bin/install -c
-INSTALL_PROGRAM = ${INSTALL}
-INSTALL_DATA = ${INSTALL} -m 644
-INSTALL_SCRIPT = ${INSTALL_PROGRAM}
-transform = s,x,x,
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = i586-pc-linux-gnulibc1
-host_triplet = i586-pc-linux-gnulibc1
-CC = gcc
-CXX = c++
-LD = /usr/bin/ld
-LIBTOOL = $(SHELL) $(top_builddir)/libtool
-LN_S = ln -s
-MAINT = #M#
-MAKEINFO = /amd/wiley/export/home/curt/projects/FlightGear/missing makeinfo
-NM = /usr/bin/nm -B
-PACKAGE = FlightGear
-RANLIB = ranlib
-VERSION = 0.51
-
-bin_PROGRAMS = areas
-
-areas_SOURCES = area.cxx area.hxx main.cxx
-
-areas_LDADD = $(top_builddir)/Lib/Bucket/libBucket.la
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../../Include/config.h
-CONFIG_CLEAN_FILES = 
-PROGRAMS =  $(bin_PROGRAMS)
-
-
-DEFS = -DHAVE_CONFIG_H -I. -I$(srcdir) -I../../Include
-CPPFLAGS = -I/usr/local/include -I/usr/X11R6/include
-LDFLAGS = -L/usr/local/lib -L/usr/X11R6/lib
-LIBS = -lglut -lMesaGLU -lMesaGL -lXmu -lXt -lSM -lICE -lXi -lXext -lX11 -lm 
-X_CFLAGS =  -I/usr/X11R6/include
-X_LIBS =  -L/usr/X11R6/lib
-X_EXTRA_LIBS = 
-X_PRE_LIBS =  -lSM -lICE
-areas_OBJECTS =  area.o main.o
-areas_DEPENDENCIES =  $(top_builddir)/Lib/Bucket/libBucket.la
-areas_LDFLAGS = 
-CXXFLAGS = -Wall
-CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-CXXLINK = $(LIBTOOL) --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON =  README Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = tar
-GZIP = --best
-DEP_FILES =  .deps/area.P .deps/main.P
-CXXMKDEP = $(CXX) -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
-SOURCES = $(areas_SOURCES)
-OBJECTS = $(areas_OBJECTS)
-
-all: Makefile $(PROGRAMS)
-
-.SUFFIXES:
-.SUFFIXES: .S .c .cxx .lo .o .s
-$(srcdir)/Makefile.in: #M# Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
-	cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Areas/Makefile
-
-Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
-	cd $(top_builddir) \
-	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
-	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
-install-binPROGRAMS: $(bin_PROGRAMS)
-	@$(NORMAL_INSTALL)
-	$(mkinstalldirs) $(DESTDIR)$(bindir)
-	@list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  if test -f $$p; then \
-	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	  else :; fi; \
-	done
-
-uninstall-binPROGRAMS:
-	@$(NORMAL_UNINSTALL)
-	list='$(bin_PROGRAMS)'; for p in $$list; do \
-	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-	done
-
-.s.o:
-	$(COMPILE) -c $<
-
-.S.o:
-	$(COMPILE) -c $<
-
-mostlyclean-compile:
-	-rm -f *.o core *.core
-
-clean-compile:
-
-distclean-compile:
-	-rm -f *.tab.c
-
-maintainer-clean-compile:
-
-.s.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-.S.lo:
-	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-distclean-libtool:
-
-maintainer-clean-libtool:
-
-areas: $(areas_OBJECTS) $(areas_DEPENDENCIES)
-	@rm -f areas
-	$(CXXLINK) $(areas_LDFLAGS) $(areas_OBJECTS) $(areas_LDADD) $(LIBS)
-.cxx.o:
-	$(CXXCOMPILE) -c $<
-.cxx.lo:
-	$(LTCXXCOMPILE) -c $<
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
-	here=`pwd` && cd $(srcdir) \
-	  && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
-	tags=; \
-	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)'; \
-	unique=`for i in $$list; do echo $$i; done | \
-	  awk '    { files[$$0] = 1; } \
-	       END { for (i in files) print i; }'`; \
-	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
-	-rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = Tools/Areas
-
-distdir: $(DISTFILES)
-	here=`cd $(top_builddir) && pwd`; \
-	top_distdir=`cd $(top_distdir) && pwd`; \
-	distdir=`cd $(distdir) && pwd`; \
-	cd $(top_srcdir) \
-	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Areas/Makefile
-	@for file in $(DISTFILES); do \
-	  d=$(srcdir); \
-	  test -f $(distdir)/$$file \
-	  || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
-	  || cp -p $$d/$$file $(distdir)/$$file; \
-	done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
-
-maintainer-clean-depend:
-	-rm -rf .deps
-
-%.o: %.c
-	@echo '$(COMPILE) -c $<'; \
-	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.c
-	@echo '$(LTCOMPILE) -c $<'; \
-	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-
-%.o: %.cxx
-	@echo '$(CXXCOMPILE) -c $<'; \
-	$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).P -c $<
-
-%.lo: %.cxx
-	@echo '$(LTCXXCOMPILE) -c $<'; \
-	$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
-	@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
-	  < .deps/$(*F).p > .deps/$(*F).P
-	@-rm -f .deps/$(*F).p
-info:
-dvi:
-check: all
-	$(MAKE)
-installcheck:
-install-exec: install-binPROGRAMS
-	@$(NORMAL_INSTALL)
-
-install-data: 
-	@$(NORMAL_INSTALL)
-
-install: install-exec install-data all
-	@:
-
-uninstall: uninstall-binPROGRAMS
-
-install-strip:
-	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
-installdirs:
-	$(mkinstalldirs)  $(DATADIR)$(bindir)
-
-
-mostlyclean-generic:
-	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-	-rm -f Makefile $(DISTCLEANFILES)
-	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-mostlyclean:  mostlyclean-binPROGRAMS mostlyclean-compile \
-		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
-		mostlyclean-generic
-
-clean:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
-		clean-depend clean-generic mostlyclean
-
-distclean:  distclean-binPROGRAMS distclean-compile distclean-libtool \
-		distclean-tags distclean-depend distclean-generic clean
-	-rm -f config.status
-	-rm -f libtool
-
-maintainer-clean:  maintainer-clean-binPROGRAMS maintainer-clean-compile \
-		maintainer-clean-libtool maintainer-clean-tags \
-		maintainer-clean-depend maintainer-clean-generic \
-		distclean
-	@echo "This command is intended for maintainers to use;"
-	@echo "it deletes files that may require special tools to rebuild."
-
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile mostlyclean-libtool distclean-libtool \
-clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info dvi installcheck install-exec install-data \
-install uninstall all installdirs mostlyclean-generic distclean-generic \
-clean-generic maintainer-clean-generic clean mostlyclean distclean \
-maintainer-clean
-
-
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
-
-#---------------------------------------------------------------------------
-# $Log$
-# Revision 1.1  1998/07/20 12:54:05  curt
-# Initial revision.
-#
-# Revision 1.2  1998/04/14 02:25:59  curt
-# Code reorganizations.  Added a Lib/ directory for more general libraries.
-#
-# Revision 1.1  1998/04/08 22:54:57  curt
-# Adopted Gnu automake/autoconf system.
-#
-# Revision 1.2  1998/01/21 02:55:46  curt
-# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
-#
-# Revision 1.1  1998/01/15 02:45:25  curt
-# Initial revision.
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/Areas/Makefile.am b/Areas/Makefile.am
new file mode 100644
index 000000000..60277ea5d
--- /dev/null
+++ b/Areas/Makefile.am
@@ -0,0 +1,53 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+bin_PROGRAMS = areas
+
+areas_SOURCES = area.cxx area.hxx main.cxx
+
+areas_LDADD = $(top_builddir)/Lib/Bucket/libBucket.la
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/07/20 12:54:53  curt
+# Whoops, need to commit Makefile.am, not Makefile.
+#
+# Revision 1.2  1998/04/14 02:25:59  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
+# Revision 1.1  1998/04/08 22:54:57  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.2  1998/01/21 02:55:46  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1998/01/15 02:45:25  curt
+# Initial revision.
+#
+

From 14a58ae22bbc8789298ee6be724db24a15e250b6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 20 Jul 1998 12:55:35 +0000
Subject: [PATCH 121/283] Several tweaks to start incorporating area cutouts
 into the pipeline.

---
 Tools/process-dem.pl | 67 +++++++++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 19 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index adca9c3d3..f9d917e90 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -27,13 +27,14 @@
 
 
 $max_area = 10000;            # maximum triangle area
+$remove_tmps = 0;
 
 $| = 1;                         # flush buffers after every write
 
-$do_dem2node =   1;
-$do_triangle_1 = 1;
-$do_fixnode =    1;
-$do_splittris =  1;
+$do_dem2node =   0;
+$do_triangle_1 = 0;
+$do_fixnode =    0;
+$do_splittris =  0;
 $do_assemtris =  1;
 $do_triangle_2 = 1;
 
@@ -67,7 +68,7 @@ while ( $dem_file = shift(@ARGV) ) {
     if ( $do_dem2node ) {
 	dem2node() ;
     } else {
-	$subdir = "./work/Scenery/w100n040/w093n045/";
+	$subdir = "./work/Scenery/w100n040/w094n045";
 	print "WARNING:  Hardcoding subdir = $subdir\n";
     }
 
@@ -75,6 +76,7 @@ while ( $dem_file = shift(@ARGV) ) {
     fixnode() if ( $do_fixnode );
     splittris() if ( $do_splittris );
     assemtris() if ( $do_assemtris );
+    exit;
     triangle_2() if ( $do_triangle_2);
     tri2obj() if ( $do_tri2obj );
     strips() if ( $do_strips );
@@ -145,10 +147,18 @@ print "Subdirectory for this dem file is $subdir\n";
 sub triangle_1 {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
-	print $file;
+	# print $file;
 	chop($file);
 	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
-	    $command = "Triangle/triangle -a$max_area -q $subdir/$file";
+	    # special handling is needed if .poly file exists
+	    $fileroot = $file;
+	    $fileroot =~ s/\.node$//;
+	    print "$subdir/$fileroot\n";
+	    if ( -r "$subdir/$fileroot.poly" ) {
+		$command = "Triangle/triangle -pc -a$max_area -q5 $subdir/$fileroot";
+	    } else {
+		$command = "Triangle/triangle -c -a$max_area -q5 $subdir/$file";
+	    }
 	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
@@ -158,7 +168,9 @@ sub triangle_1 {
 	    close(OUT);
 
 	    # remove input file.node
-	    unlink("$subdir/$file");
+	    if ( $remove_tmps ) {
+		unlink("$subdir/$file");
+	    }
 	}
     }
 }
@@ -213,9 +225,11 @@ sub splittris {
 	    }
 	    close(OUT);
 
-	    unlink("$subdir/$file.node");
-	    unlink("$subdir/$file.node.orig");
-	    unlink("$subdir/$file.ele");
+	    if ( $remove_tmps ) {
+		unlink("$subdir/$file.node");
+		unlink("$subdir/$file.node.orig");
+		unlink("$subdir/$file.ele");
+	    }
 	}
     }
 }
@@ -241,7 +255,9 @@ sub assemtris {
 	    }
 	    close(OUT);
 	}
-	unlink("$subdir/$file.body");
+	if ( $remove_tmps ) {
+	    unlink("$subdir/$file.body");
+	}
     }
 }
 
@@ -278,7 +294,9 @@ sub triangle_2 {
 	    close(OUT);
 
 	    # remove input file.node
-	    unlink("$subdir/$file");
+	    if ( $remove_tmps ) {
+		unlink("$subdir/$file");
+	    }
 	}
     }
 }
@@ -310,9 +328,11 @@ sub tri2obj {
 	    }
 	    close(OUT);
 	    
-	    unlink("$subdir/$file.node");
-	    unlink("$subdir/$file.node.orig");
-	    unlink("$subdir/$file.ele");
+	    if ( $remove_tmps ) {
+		unlink("$subdir/$file.node");
+		unlink("$subdir/$file.node.orig");
+		unlink("$subdir/$file.ele");
+	    }
 	}
     }
 }
@@ -355,7 +375,9 @@ sub strips {
 	    close(IN);
 	    close(OUT);
 	    
-	    unlink("$subdir/$file");
+	    if ( $remove_tmps ) {
+		unlink("$subdir/$file");
+	    }
 	}
     }
 }
@@ -382,7 +404,9 @@ sub fixobj {
 	    }
 	    close(OUT);
 
-	    unlink("$subdir/$file");
+	    if ( $remove_tmps ) {
+		unlink("$subdir/$file");
+	    }
 	}
     }
 }
@@ -415,7 +439,9 @@ sub install {
 	    }
 	    close(OUT);
 
-	    unlink("$subdir/$file");
+	    if ( $remove_tmps ) {
+		unlink("$subdir/$file");
+	    }
 	}
     }
 }
@@ -423,6 +449,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.23  1998/07/20 12:55:35  curt
+# Several tweaks to start incorporating area cutouts into the pipeline.
+#
 # Revision 1.22  1998/07/08 14:49:13  curt
 # tweaks.
 #

From e435c551c678e97784e63d422dbac98cc0c4a721 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 21 Jul 1998 04:33:47 +0000
Subject: [PATCH 122/283] More tweaks for sub-area cutouts.

---
 Tools/process-dem.pl | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index f9d917e90..a7d3976b1 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -31,10 +31,10 @@ $remove_tmps = 0;
 
 $| = 1;                         # flush buffers after every write
 
-$do_dem2node =   0;
-$do_triangle_1 = 0;
-$do_fixnode =    0;
-$do_splittris =  0;
+$do_dem2node =   1;
+$do_triangle_1 = 1;
+$do_fixnode =    1;
+$do_splittris =  1;
 $do_assemtris =  1;
 $do_triangle_2 = 1;
 
@@ -76,7 +76,6 @@ while ( $dem_file = shift(@ARGV) ) {
     fixnode() if ( $do_fixnode );
     splittris() if ( $do_splittris );
     assemtris() if ( $do_assemtris );
-    exit;
     triangle_2() if ( $do_triangle_2);
     tri2obj() if ( $do_tri2obj );
     strips() if ( $do_strips );
@@ -244,7 +243,7 @@ sub assemtris {
     foreach $file ( @FILES ) {
 	chop($file);
 	if ( $file =~ m/\.1\.body$/ ) {
-	    $file =~ s/\.body$//;  # strip off the ".body"
+	    $file =~ s/\.1\.body$//;  # strip off the ".body"
 	
 	    $command = "AssemTris/assemtris $subdir/$file";
 	    $command = fix_command($command);
@@ -268,23 +267,29 @@ sub assemtris {
 sub triangle_2 {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
-	print $file;
+	# print $file;
 	chop($file);
 	if ( ($file =~ m/\.node$/) && ($file !~ m/\.\d\.node$/) ) {
 	    $base = $file;
 	    $base =~ s/\.node$//;
 	    print("Test for $subdir/$base.q\n");
-	    if ( -r "$subdir/$base.q" ) {
 
+	    $command = "Triangle/triangle";
+
+	    if ( -r "$subdir/$base.q" ) {
 		# if triangle hangs, we can create a filebase.q for
 		# the file it hung on.  Then, we test for that file
 		# here which causes the incremental algorithm to run
 		# (which shouldn't ever hang.)
-
-		$command = "Triangle/triangle -i $subdir/$file";
-	    } else {
-		$command = "Triangle/triangle $subdir/$file";
+		$command .= " -i";
 	    }
+
+	    if ( -r "$subdir/$base.poly" ) {
+		$command .= " -pc $subdir/$base";
+	    } else {
+		$command .= " -c $subdir/$file";
+	    }
+
 	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
@@ -449,6 +454,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.24  1998/07/21 04:33:47  curt
+# More tweaks for sub-area cutouts.
+#
 # Revision 1.23  1998/07/20 12:55:35  curt
 # Several tweaks to start incorporating area cutouts into the pipeline.
 #

From 0a8ec68f2b37acb83e255d3fab381f13620ebbf5 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 21 Jul 1998 04:34:20 +0000
Subject: [PATCH 123/283] Mods to handle extra nodes (i.e. preserve cutouts).

---
 AssemTris/assemtris.c | 124 +++++++++++++++++++++++++++++++++---------
 1 file changed, 97 insertions(+), 27 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index 1eaa56c5a..ed42f8087 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -33,15 +33,14 @@
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
-// #include <Math/fg_geodesy.h>
-// #include <Math/mat3.h>
-// #include <Math/polar.h>
 #include <Bucket/bucketutils.h>
 
 
 int nodecount = 0;
+int excount = 0;
 
 static double nodes[MAX_NODES][3];
+static double exnodes[MAX_NODES][3];
 
 
 fgBUCKET my_index;
@@ -81,6 +80,54 @@ void extract_path(char *in, char *base) {
 }
 
 
+/* check to see if specified node is in the extra list */
+int is_extra_node(double *n) {
+    int i;
+
+    for ( i = 1; i <= excount; i++ ) {
+	// we only check lon/lat in case the height got fooled with
+	// along the way
+	if ( (fabs(n[0] - exnodes[i][0]) < FG_EPSILON) &&
+	     (fabs(n[1] - exnodes[i][1]) < FG_EPSILON) ) {
+	    return(1);
+	}
+    }
+
+    return(0);
+}
+
+/* Read all the extra nodes.  These typically define inner areas to
+   exclude from triangulations.  There will be a .poly file that
+   refers to these by position number which assumes all the extra
+   nodes come first in the generated .node file. */
+void read_extra_nodes(char *exfile) {
+    FILE *fd;
+    int i, junk1, junk2, junk3;
+
+    // load extra nodes if they exist
+    excount = 0;
+    if ( (fd = fopen(exfile, "r")) != NULL ) {
+	printf("Found and 'extra' node file = %s\n", exfile);
+	fscanf(fd, "%d %d %d %d", &excount, &junk1, &junk2, &junk3);
+
+	if ( excount > MAX_NODES - 1 ) {
+	    printf("Error, too many 'extra' nodes, increase array size\n");
+	    exit(-1);
+	} else {
+	    printf("    Expecting %d 'extra' nodes\n", excount);
+	}
+
+	for ( i = 1; i <= excount; i++ ) {
+	    fscanf(fd, "%d %lf %lf %lf\n", &junk1, 
+		   &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]);
+	    printf("(extra) %d %.2f %.2f %.2f\n", 
+		    i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
+	}
+    }
+    fclose(fd);
+}
+
+
 /* check if a file exists */
 int file_exists(char *file) {
     struct stat stat_buf;
@@ -315,22 +362,28 @@ FILE *my_open(char *basename, char *basepath, char *ext) {
    precision problems.  1 arcsec == about 100 feet so 0.01 arcsec ==
    about 1 foot */
 void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
+    double n[3];
     char line[256];
 
     while ( fgets(line, 250, fp) != NULL ) {
 	if ( strncmp(line, "gdn ", 4) == 0 ) {
-	    sscanf(line, "gdn %lf %lf %lf\n", &nodes[nodecount][0], 
-		   &nodes[nodecount][1], &nodes[nodecount][2]);
+	    sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]);
 
-	    nodes[nodecount][0] += offset_lon;
-	    nodes[nodecount][1] += offset_lat;
+	    if ( ! is_extra_node(n) ) {
+		nodes[nodecount][0] = n[0] + offset_lon;
+		nodes[nodecount][1] = n[1] + offset_lat;
+		nodes[nodecount][2] = n[2];
 
-	    /*
-	    printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
-		   nodes[nodecount][0], nodes[nodecount][1], 
-		   nodes[nodecount][2], line);
-		   */
-	    nodecount++;
+		/*
+		  printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
+		      nodes[nodecount][0], nodes[nodecount][1], 
+		      nodes[nodecount][2], line);
+		      */
+
+		nodecount++;
+	    } else {
+		printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]);
+	    }
 	}
     }
 }
@@ -339,8 +392,14 @@ void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
 /* load in nodes from the various split and shared pieces to
  * reconstruct a tile */
 void build_node_list(char *basename, char *basepath) {
+    char exfile[256];
     FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
 
+    // load extra nodes if they exist
+    strcpy(exfile, basename);
+    strcat(exfile, ".node.ex");
+    read_extra_nodes(exfile);
+
     ne = my_open(basename, basepath, ".ne");
     read_nodes(ne, 0.1, 0.1);
     fclose(ne);
@@ -382,29 +441,35 @@ void build_node_list(char *basename, char *basepath) {
 /* dump in WaveFront .obj format */
 void dump_nodes(char *basename) {
     char file[256];
-    FILE *fp;
-    int i, len;
+    FILE *fd;
+    int i;
 
     /* generate output file name */
     strcpy(file, basename);
-    len = strlen(file);
-    file[len-2] = '\0';
+    // len = strlen(file);
+    // file[len-2] = '\0';
     strcat(file, ".node");
     
     /* dump vertices */
     printf("Creating node file:  %s\n", file);
     printf("  writing vertices in .node format.\n");
-    fp = fopen(file, "w");
+    fd = fopen(file, "w");
 
-    fprintf(fp, "%d 2 1 0\n", nodecount);
+    fprintf(fd, "%d 2 1 0\n", excount + nodecount);
+
+    // now write out extra node data
+    for ( i = 1; i <= excount; i++ ) {
+	fprintf(fd, "%d %.2f %.2f %.2f 0\n", 
+		i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
+    }
 
     /* now write out actual node data */
     for ( i = 0; i < nodecount; i++ ) {
-	fprintf(fp, "%d %.2f %.2f %.2f 0\n", i + 1,
+	fprintf(fd, "%d %.2f %.2f %.2f 0\n", excount + i + 1,
 	       nodes[i][0], nodes[i][1], nodes[i][2]);
     }
 
-    fclose(fp);
+    fclose(fd);
 }
 
 
@@ -413,7 +478,9 @@ int main(int argc, char **argv) {
     long int tmp_index;
     int len;
 
+    // derive base name
     strcpy(basename, argv[1]);
+    len = strlen(basename);
 
     /* find the base path of the file */
     extract_path(basename, basepath);
@@ -423,10 +490,10 @@ int main(int argc, char **argv) {
 
     /* find the index of the current file */
     extract_file(basename, temp);
-    len = strlen(temp);
-    if ( len >= 2 ) {
-	temp[len-2] = '\0';
-    }
+    // len = strlen(temp);
+    // if ( len >= 2 ) {
+    //    temp[len-2] = '\0';
+    // }
     tmp_index = atoi(temp);
     printf("%ld\n", tmp_index);
     fgBucketParseIndex(tmp_index, &my_index);
@@ -462,9 +529,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.9  1998/07/04 00:55:39  curt
-/* typedef'd struct fgBUCKET.
+/* Revision 1.10  1998/07/21 04:34:20  curt
+/* Mods to handle extra nodes (i.e. preserve cutouts).
 /*
+ * Revision 1.9  1998/07/04 00:55:39  curt
+ * typedef'd struct fgBUCKET.
+ *
  * Revision 1.8  1998/06/01 17:58:19  curt
  * Added a slight border overlap to try to minimize pixel wide gaps between
  * tiles due to round off error.  This is not a perfect solution, but helps.

From d8c9c07659151c572d8cfe6b903124b37c3b4f59 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 22 Jul 1998 21:46:09 +0000
Subject: [PATCH 124/283] minor tweaks.

---
 Tools/process-dem.pl | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index a7d3976b1..2f9f72be9 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -68,7 +68,7 @@ while ( $dem_file = shift(@ARGV) ) {
     if ( $do_dem2node ) {
 	dem2node() ;
     } else {
-	$subdir = "./work/Scenery/w100n040/w094n045";
+	$subdir = "./work/Scenery/w120n030/w111n033";
 	print "WARNING:  Hardcoding subdir = $subdir\n";
     }
 
@@ -153,11 +153,11 @@ sub triangle_1 {
 	    $fileroot = $file;
 	    $fileroot =~ s/\.node$//;
 	    print "$subdir/$fileroot\n";
+	    $command = "Triangle/triangle";
 	    if ( -r "$subdir/$fileroot.poly" ) {
-		$command = "Triangle/triangle -pc -a$max_area -q5 $subdir/$fileroot";
-	    } else {
-		$command = "Triangle/triangle -c -a$max_area -q5 $subdir/$file";
+		$command = " -pc";
 	    }
+	    $command .= " -a$max_area -q10 $subdir/$file";
 	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
@@ -185,7 +185,7 @@ sub fixnode {
     $command = "FixNode/fixnode $dem_file $subdir";
     $command = fix_command($command);
     print "Running '$command'\n";
-    open(OUT, "$command |");
+    open(OUT, "$command |") || die "cannot run command\n";
     while ( <OUT> ) {
 	print $_;
     }
@@ -287,7 +287,7 @@ sub triangle_2 {
 	    if ( -r "$subdir/$base.poly" ) {
 		$command .= " -pc $subdir/$base";
 	    } else {
-		$command .= " -c $subdir/$file";
+		$command .= " $subdir/$file";
 	    }
 
 	    $command = fix_command($command);
@@ -454,6 +454,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.25  1998/07/22 21:46:09  curt
+# minor tweaks.
+#
 # Revision 1.24  1998/07/21 04:33:47  curt
 # More tweaks for sub-area cutouts.
 #

From 8a690c205815a1e6913ac563cfb9bda6ff66e76d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 22 Jul 1998 21:46:40 +0000
Subject: [PATCH 125/283] Fixed a bug that was triggering a seg fault.

---
 FixNode/fixnode.cxx | 13 +++++++------
 FixNode/fixnode.hxx |  7 ++++---
 FixNode/main.cxx    | 10 +++++++---
 3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/FixNode/fixnode.cxx b/FixNode/fixnode.cxx
index b4408fbe6..86e6ac8cd 100644
--- a/FixNode/fixnode.cxx
+++ b/FixNode/fixnode.cxx
@@ -33,9 +33,7 @@
 
 
 /* load the node information */
-void fixnodes( char *filename, fgDEM dem, 
-	       float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
-	       double nodes[MAX_NODES][3] )
+void fixnodes( char *filename, fgDEM *dem, double nodes[MAX_NODES][3] )
 {
     char toname[256];
     FILE *fd;
@@ -53,7 +51,7 @@ void fixnodes( char *filename, fgDEM dem,
 	       nodes[i][1], nodes[i][2]); */
 
 	nodes[i][2] = 
-	    dem.interpolate_altitude(nodes[i][0], nodes[i][1]);
+	    dem->interpolate_altitude(nodes[i][0], nodes[i][1]);
 
 	/* printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
 	       nodes[i][1], nodes[i][2]); */
@@ -80,9 +78,12 @@ void fixnodes( char *filename, fgDEM dem,
 
 
 /* $Log$
-/* Revision 1.2  1998/04/14 02:26:03  curt
-/* Code reorganizations.  Added a Lib/ directory for more general libraries.
+/* Revision 1.3  1998/07/22 21:46:40  curt
+/* Fixed a bug that was triggering a seg fault.
 /*
+ * Revision 1.2  1998/04/14 02:26:03  curt
+ * Code reorganizations.  Added a Lib/ directory for more general libraries.
+ *
  * Revision 1.1  1998/04/08 23:05:56  curt
  * Adopted Gnu automake/autoconf system.
  *
diff --git a/FixNode/fixnode.hxx b/FixNode/fixnode.hxx
index 370e136a5..236875fab 100644
--- a/FixNode/fixnode.hxx
+++ b/FixNode/fixnode.hxx
@@ -37,15 +37,16 @@
 
 
 // load the node information
-void fixnodes( char *basename, fgDEM dem, 
-	       float dem_data[DEM_SIZE_1][DEM_SIZE_1], 
-	       double nodes[MAX_NODES][3] );
+void fixnodes( char *basename, fgDEM *dem, double nodes[MAX_NODES][3] );
 
 
 #endif // _FIXNODE_H
 
 
 // $Log$
+// Revision 1.2  1998/07/22 21:46:41  curt
+// Fixed a bug that was triggering a seg fault.
+//
 // Revision 1.1  1998/04/08 23:05:56  curt
 // Adopted Gnu automake/autoconf system.
 //
diff --git a/FixNode/main.cxx b/FixNode/main.cxx
index 9a3d3b32d..92441ec8e 100644
--- a/FixNode/main.cxx
+++ b/FixNode/main.cxx
@@ -40,8 +40,7 @@
 
 
 // Storage for the original DEM data which is used to interpolate z values
-static fgDEM dem;
-static float dem_data[DEM_SIZE_1][DEM_SIZE_1];
+fgDEM dem;
 
 // Node list
 static double nodes[MAX_NODES][3];
@@ -76,7 +75,7 @@ void process_files(char *root_path) {
 		// load the input data files
 		triload(file_path, nodes);
 
-		fixnodes(file_path, dem, dem_data, nodes);
+		fixnodes(file_path, &dem, nodes);
 	    }
 	}
     }
@@ -92,6 +91,8 @@ int main(int argc, char **argv) {
 	exit(-1);
     }
 
+    printf("Starting fixnode\n");
+
     strcpy(demfile, argv[1]);
     strcpy(root_path, argv[2]);
 
@@ -108,6 +109,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.5  1998/07/22 21:46:41  curt
+// Fixed a bug that was triggering a seg fault.
+//
 // Revision 1.4  1998/06/27 16:55:24  curt
 // Changed include order for <sys/types.h>
 //

From d14e4174972977db6b0edc4105a35721c3705b43 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 30 Jul 1998 23:42:19 +0000
Subject: [PATCH 126/283] Removed zlib support.

---
 DEM/Makefile.am | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/DEM/Makefile.am b/DEM/Makefile.am
index aeb7ecf2c..ec72f2e38 100644
--- a/DEM/Makefile.am
+++ b/DEM/Makefile.am
@@ -1,8 +1,6 @@
-libdir  = ${exec_prefix}/lib
+noinst_LIBRARIES = libDEM.a
 
-lib_LTLIBRARIES = libDEM.la
-
-libDEM_la_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
+libDEM_a_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 

From 801ba133bda2a0330505d40ca1184f8dff12ddd6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 30 Jul 1998 23:49:18 +0000
Subject: [PATCH 127/283] Removed libtool support.

---
 Areas/Makefile.am     |  5 ++++-
 AssemTris/Makefile.am |  5 ++++-
 DemInfo/Makefile.am   |  9 ++++++---
 FixNode/Makefile.am   |  9 ++++++---
 FixObj/Makefile.am    |  9 ++++++---
 SplitTris/Makefile.am | 11 +++++++----
 Tri2obj/Makefile.am   | 11 +++++++----
 7 files changed, 40 insertions(+), 19 deletions(-)

diff --git a/Areas/Makefile.am b/Areas/Makefile.am
index 60277ea5d..0ee77fcf0 100644
--- a/Areas/Makefile.am
+++ b/Areas/Makefile.am
@@ -28,13 +28,16 @@ bin_PROGRAMS = areas
 
 areas_SOURCES = area.cxx area.hxx main.cxx
 
-areas_LDADD = $(top_builddir)/Lib/Bucket/libBucket.la
+areas_LDADD = $(top_builddir)/Lib/Bucket/libBucket.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/07/30 23:49:18  curt
+# Removed libtool support.
+#
 # Revision 1.1  1998/07/20 12:54:53  curt
 # Whoops, need to commit Makefile.am, not Makefile.
 #
diff --git a/AssemTris/Makefile.am b/AssemTris/Makefile.am
index 190b0ec5a..f1cb9f24e 100644
--- a/AssemTris/Makefile.am
+++ b/AssemTris/Makefile.am
@@ -29,13 +29,16 @@ bin_PROGRAMS = assemtris
 assemtris_SOURCES = assemtris.c assemtris.h
 
 assemtris_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la
+	$(top_builddir)/Lib/Bucket/libBucket.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/07/30 23:49:23  curt
+# Removed libtool support.
+#
 # Revision 1.2  1998/04/14 02:25:59  curt
 # Code reorganizations.  Added a Lib/ directory for more general libraries.
 #
diff --git a/DemInfo/Makefile.am b/DemInfo/Makefile.am
index 4bfa93f57..0ec8323d0 100644
--- a/DemInfo/Makefile.am
+++ b/DemInfo/Makefile.am
@@ -30,9 +30,9 @@ deminfo_SOURCES = \
 	deminfo.cxx
 
 deminfo_LDADD = \
-	$(top_builddir)/Lib/DEM/libDEM.la \
-	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/zlib/libz.la
+	$(top_builddir)/Lib/DEM/libDEM.a \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
@@ -44,6 +44,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/07/30 23:49:24  curt
+# Removed libtool support.
+#
 # Revision 1.1  1998/06/04 19:18:04  curt
 # Initial revision.
 #
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index 04d7e2094..b44b9b6d7 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -32,9 +32,9 @@ fixnode_SOURCES = \
 	triload.cxx triload.hxx
 
 fixnode_LDADD = \
-	$(top_builddir)/Lib/DEM/libDEM.la \
-        $(top_builddir)/Lib/Bucket/libBucket.la \
-        $(top_builddir)/Lib/zlib/libz.la
+	$(top_builddir)/Lib/DEM/libDEM.a \
+        $(top_builddir)/Lib/Bucket/libBucket.a \
+        $(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
@@ -46,6 +46,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/07/30 23:49:24  curt
+# Removed libtool support.
+#
 # Revision 1.3  1998/04/18 04:02:54  curt
 # Added zlib support in placed and other misc. tweaks.
 #
diff --git a/FixObj/Makefile.am b/FixObj/Makefile.am
index 0f7f16710..bafcf879c 100644
--- a/FixObj/Makefile.am
+++ b/FixObj/Makefile.am
@@ -29,15 +29,18 @@ bin_PROGRAMS = fixobj
 fixobj_SOURCES = main.cxx obj.cxx obj.hxx
 
 fixobj_LDADD = \
-	$(top_builddir)/Lib/Math/libMath.la \
-	$(top_builddir)/Lib/Debug/libDebug.la \
-	$(top_builddir)/Lib/zlib/libz.la
+	$(top_builddir)/Lib/Math/libMath.a \
+	$(top_builddir)/Lib/Debug/libDebug.a \
+	$(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1998/07/30 23:49:25  curt
+# Removed libtool support.
+#
 # Revision 1.5  1998/06/08 17:11:44  curt
 # Renamed *.[ch] to *.[ch]xx
 #
diff --git a/SplitTris/Makefile.am b/SplitTris/Makefile.am
index be4d06c8f..f43a3081f 100644
--- a/SplitTris/Makefile.am
+++ b/SplitTris/Makefile.am
@@ -29,16 +29,19 @@ bin_PROGRAMS = splittris
 splittris_SOURCES = splittris.cxx splittris.hxx
 
 splittris_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la \
-        $(top_builddir)/Lib/Debug/libDebug.la \
-        $(top_builddir)/Lib/zlib/libz.la
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/Math/libMath.a \
+        $(top_builddir)/Lib/Debug/libDebug.a \
+        $(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1998/07/30 23:49:26  curt
+# Removed libtool support.
+#
 # Revision 1.5  1998/07/08 14:49:13  curt
 # tweaks.
 #
diff --git a/Tri2obj/Makefile.am b/Tri2obj/Makefile.am
index e0ea71e5b..6c57a638d 100644
--- a/Tri2obj/Makefile.am
+++ b/Tri2obj/Makefile.am
@@ -29,16 +29,19 @@ bin_PROGRAMS = tri2obj
 tri2obj_SOURCES = tri2obj.cxx tri2obj.hxx
 
 tri2obj_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.la \
-	$(top_builddir)/Lib/Math/libMath.la \
-        $(top_builddir)/Lib/Debug/libDebug.la \
-        $(top_builddir)/Lib/zlib/libz.la
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/Math/libMath.a \
+        $(top_builddir)/Lib/Debug/libDebug.a \
+        $(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1998/07/30 23:49:26  curt
+# Removed libtool support.
+#
 # Revision 1.5  1998/07/08 14:49:14  curt
 # tweaks.
 #

From 533f072899e763cb647e45f268959c9d6a4c69fb Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 31 Jul 1998 18:27:36 +0000
Subject: [PATCH 128/283] Initial revision.

---
 Stripe_w/Makefile.am    |   26 +
 Stripe_w/add.c          |  384 +++++++++
 Stripe_w/add.h          |   31 +
 Stripe_w/bands.c        |  560 +++++++++++++
 Stripe_w/common.c       |  810 +++++++++++++++++++
 Stripe_w/common.h       |   42 +
 Stripe_w/extend.h       |   17 +
 Stripe_w/free.c         |  112 +++
 Stripe_w/free.h         |   22 +
 Stripe_w/global.h       |   44 ++
 Stripe_w/init.c         |  217 +++++
 Stripe_w/init.h         |   30 +
 Stripe_w/local.c        |  119 +++
 Stripe_w/local.h        |   20 +
 Stripe_w/newpolve.c     | 1659 +++++++++++++++++++++++++++++++++++++++
 Stripe_w/options.c      |  181 +++++
 Stripe_w/options.h      |   17 +
 Stripe_w/output.c       |  579 ++++++++++++++
 Stripe_w/output.h       |   34 +
 Stripe_w/outputex.c     |  514 ++++++++++++
 Stripe_w/outputex.h     |   31 +
 Stripe_w/partial.c      |  668 ++++++++++++++++
 Stripe_w/partial.h      |   20 +
 Stripe_w/polverts.h     |  108 +++
 Stripe_w/polyvertsex.h  |   34 +
 Stripe_w/queue.c        |  226 ++++++
 Stripe_w/queue.h        |  283 +++++++
 Stripe_w/sgi_triang.c   |  628 +++++++++++++++
 Stripe_w/sgi_triangex.c |  582 ++++++++++++++
 Stripe_w/struct.c       |  549 +++++++++++++
 Stripe_w/structex.c     |  553 +++++++++++++
 Stripe_w/sturcts.h      |   36 +
 Stripe_w/sturctsex.h    |   33 +
 Stripe_w/ties.c         |  304 +++++++
 Stripe_w/ties.h         |   15 +
 Stripe_w/triangulate.h  |   27 +
 Stripe_w/triangulatex.h |   28 +
 Stripe_w/util.c         |  272 +++++++
 Stripe_w/util.h         |   24 +
 39 files changed, 9839 insertions(+)
 create mode 100644 Stripe_w/Makefile.am
 create mode 100644 Stripe_w/add.c
 create mode 100644 Stripe_w/add.h
 create mode 100644 Stripe_w/bands.c
 create mode 100644 Stripe_w/common.c
 create mode 100644 Stripe_w/common.h
 create mode 100644 Stripe_w/extend.h
 create mode 100644 Stripe_w/free.c
 create mode 100644 Stripe_w/free.h
 create mode 100644 Stripe_w/global.h
 create mode 100644 Stripe_w/init.c
 create mode 100644 Stripe_w/init.h
 create mode 100644 Stripe_w/local.c
 create mode 100644 Stripe_w/local.h
 create mode 100644 Stripe_w/newpolve.c
 create mode 100644 Stripe_w/options.c
 create mode 100644 Stripe_w/options.h
 create mode 100644 Stripe_w/output.c
 create mode 100644 Stripe_w/output.h
 create mode 100644 Stripe_w/outputex.c
 create mode 100644 Stripe_w/outputex.h
 create mode 100644 Stripe_w/partial.c
 create mode 100644 Stripe_w/partial.h
 create mode 100644 Stripe_w/polverts.h
 create mode 100644 Stripe_w/polyvertsex.h
 create mode 100644 Stripe_w/queue.c
 create mode 100644 Stripe_w/queue.h
 create mode 100644 Stripe_w/sgi_triang.c
 create mode 100644 Stripe_w/sgi_triangex.c
 create mode 100644 Stripe_w/struct.c
 create mode 100644 Stripe_w/structex.c
 create mode 100644 Stripe_w/sturcts.h
 create mode 100644 Stripe_w/sturctsex.h
 create mode 100644 Stripe_w/ties.c
 create mode 100644 Stripe_w/ties.h
 create mode 100644 Stripe_w/triangulate.h
 create mode 100644 Stripe_w/triangulatex.h
 create mode 100644 Stripe_w/util.c
 create mode 100644 Stripe_w/util.h

diff --git a/Stripe_w/Makefile.am b/Stripe_w/Makefile.am
new file mode 100644
index 000000000..d3dbaab29
--- /dev/null
+++ b/Stripe_w/Makefile.am
@@ -0,0 +1,26 @@
+bin_PROGRAMS = strips
+
+strips_SOURCES = \
+	add.c add.h \
+	bands.c \
+	common.c common.h \
+	extend.h \
+	free.c free.h \
+	global.h \
+	init.c init.h \
+	local.c local.h \
+	newpolve.c \
+	options.c options.h \
+	output.c output.h \
+	outputex.c outputex.h \
+	partial.c partial.h \
+	polverts.h polyvertsex.h \
+	queue.c queue.h \
+	sgi_triang.c sgi_triangex.c \
+	struct.c \
+	structex.c \
+	sturcts.h sturctsex.h \
+	ties.c ties.h \
+	triangulate.h triangulatex.h \
+	util.c util.h
+
diff --git a/Stripe_w/add.c b/Stripe_w/add.c
new file mode 100644
index 000000000..ef6e673d8
--- /dev/null
+++ b/Stripe_w/add.c
@@ -0,0 +1,384 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: add.c
+     This file contains the procedure code that will add information
+     to our data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "global.h"
+#include "queue.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "ties.h"
+#include "outputex.h"
+#include "options.h"
+#include "local.h"
+
+BOOL new_vertex(double difference, int id1,int id2,
+                struct vert_struct *n)
+{
+  /*   Is the difference between id1 and id2 (2 normal vertices that
+       mapped to the same vertex) greater than the
+       threshold that was specified?
+  */
+  struct vert_struct *pn1,*pn2;
+  double dot_product;
+  double distance1, distance2,distance;
+  double rad;
+  char arg1[100];
+  char arg2[100];
+
+  pn1 = n + id1;
+  pn2 = n + id2;
+ 
+  dot_product = ((pn1->x) * (pn2->x)) +
+                ((pn1->y) * (pn2->y)) +
+                ((pn1->z) * (pn2->z));
+  /*   Get the absolute value */
+  if (dot_product < 0)
+    dot_product = dot_product * -1;
+
+  distance1 = sqrt( (pn1->x * pn1->x) +
+                    (pn1->y * pn1->y) +
+                    (pn1->z * pn1->z) );
+  distance2 = sqrt( (pn2->x * pn2->x) +
+                    (pn2->y * pn2->y) +
+                    (pn2->z * pn2->z) );
+  distance = distance1 * distance2;
+
+  rad = acos((double)dot_product/(double)distance);
+  /* convert to degrees */
+  rad = (180 * rad)/PI;
+    
+  if ( rad <= difference)
+    return FALSE;
+     
+  /*   double checking because of imprecision with floating
+       point acos function
+  */
+  sprintf( arg1,"%.5f", rad );
+  sprintf( arg2,"%.5f", difference );
+  if ( strcmp( arg1, arg2 ) <=0 )
+    return( FALSE );
+  if ( rad <= difference)
+    return FALSE;
+  else 
+    return TRUE;
+}
+
+BOOL Check_VN(int vertex,int normal, struct vert_added *added)
+{
+  /*   Check to see if we already added this vertex and normal */
+  register int x,n;
+
+  n = (added+vertex)->num;
+  for (x = 0; x < n; x++)
+  {
+    if (*((added+vertex)->normal+x) == normal)
+      return TRUE;
+  }
+  return FALSE;
+}
+
+BOOL norm_array(int id, int vertex, double normal_difference,
+                struct vert_struct *n, int num_vert)
+{
+  static int last;
+  static struct vert_added *added;
+  register int x;
+  static BOOL first = TRUE;
+
+  if (first)
+  {
+    /*   This is the first time that we are in here, so we will allocate
+         a structure that will save the vertices that we added, so that we
+         do not add the same thing twice
+    */
+    first = FALSE;
+    added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert);
+    /*   The number of vertices added for each vertex must be initialized to
+         zero
+    */
+    for (x = 0; x < num_vert; x++)
+      (added+x)->num = 0;
+  }
+
+  if (vertex)
+    /*   Set the pointer to the vertex, we will be calling again with the
+         normal to fill it with
+    */
+    last = id;
+  else
+  {    
+    /*   Fill the pointer with the id of the normal */
+    if (*(vert_norms + last) == 0)
+      *(vert_norms + last) = id;
+    else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360))
+    {
+      /*   difference is big enough, we need to create a new vertex */
+      if (new_vertex(normal_difference,id,*(vert_norms + last),n))
+      {
+        /*   First check to see if we added this vertex and normal already */
+        if (Check_VN(last,id,added))
+          return FALSE;
+        /*   OK, create the new vertex, and have its id = the number of vertices
+             and its normal what we have here
+        */
+        vert_norms = realloc(vert_norms, sizeof(int) * (num_vert + 1));
+        if (!vert_norms)
+        {
+          printf("Allocation error - aborting\n");
+          exit(1);
+        }
+        *(vert_norms + num_vert) = id;
+        /*   We created a new vertex, now put it in our added structure so
+             we do not add the same thing twice
+        */
+        (added+last)->num = (added+last)->num + 1;
+        if ((added+last)->num == 1)
+        {
+          /*   First time */
+          (added+last)->normal =  (int *) malloc (sizeof (int ) * 1);
+          *((added+last)->normal) =  id;
+        }
+        else
+        {
+          /*   Not the first time, reallocate space */
+          (added+last)->normal = realloc((added+last)->normal,sizeof(int) * (added+last)->num);
+          *((added+last)->normal+((added+last)->num-1)) = id;
+        }
+        return TRUE;
+      }
+    }
+  }
+  return FALSE;
+}
+
+void add_texture(int id,BOOL vertex)
+{
+  /*   Save the texture with its vertex for future use when outputting */
+  static int last;
+
+  if (vertex)
+    last = id;
+  else
+    *(vert_texture+last) = id;
+}
+
+int	add_vert_id(int id, int	index_count)
+{
+  register int x;
+
+  /*   Test if degenerate, if so do not add degenerate vertex */
+  for (x = 1; x < index_count ; x++)
+  {
+    if (ids[x] == id)
+      return 0;
+  }
+  ids[index_count] = id;
+  return 1;
+}
+
+void	add_norm_id(int id, int index_count)
+{
+	norms[index_count] = id;
+}
+
+void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+		int norms[STRIP_MAX])
+{
+  PF_FACES pfNode;
+  int	*pTempInt;
+  int *pnorms;
+  F_EDGES **pTempVertptr;
+  int	*pTempmarked, *pTempwalked;
+  register int	y,count = 0;
+	
+	/*   Add a new face into our face data structure */
+
+  pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
+  if ( pfNode )
+  {
+    pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); 
+		pfNode->marked  = (int*)malloc(sizeof(int) * (vert_count));
+		pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
+	}
+	pTempInt =pfNode->pPolygon;
+	pnorms = pfNode->pNorms;
+  pTempmarked = pfNode->marked;
+	pTempwalked = pfNode->walked;
+	pTempVertptr = pfNode->VertandId;
+	pfNode->nPolSize = vert_count;
+	pfNode->seen = -1;
+  pfNode->seen2 = -1;
+	for (y=1;y<=vert_count;y++)
+	{
+		*(pTempInt + count) = ids[y];
+		*(pnorms + count) = norms[y];
+    *(pTempmarked + count) = FALSE;
+	  *(pTempwalked + count) =  -1;
+		*(pTempVertptr+count) = NULL;
+		count++;
+	}
+	AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
+}	
+
+	
+void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+	      int norms[STRIP_MAX])
+{
+  PF_FACES pfNode;
+  int	*pTempInt;
+  int *pnorms;
+  F_EDGES **pTempVertptr;
+  int	*pTempmarked, *pTempwalked;
+  register int	y,count = 0;
+	
+	/*   Copy a face node into a new node, used after the global algorithm
+       is run, so that we can save whatever is left into a new structure
+  */
+     
+  pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
+  if ( pfNode )
+  {
+    pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); 
+		pfNode->marked  = (int*)malloc(sizeof(int) * (vert_count));
+		pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
+	}
+	pTempInt =pfNode->pPolygon;
+	pnorms = pfNode->pNorms;
+  pTempmarked = pfNode->marked;
+	pTempwalked = pfNode->walked;
+	pTempVertptr = pfNode->VertandId;
+	pfNode->nPolSize = vert_count;
+	pfNode->seen = -1;
+  pfNode->seen2 = -1;
+	for (y=0;y<vert_count;y++)
+	{
+		*(pTempInt + count) = ids[y];
+		*(pnorms + count) = norms[y];
+    *(pTempmarked + count) = FALSE;
+		*(pTempwalked + count) =  -1;
+		*(pTempVertptr+count) = NULL;
+		count++;
+	}
+	AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
+}	
+	
+void Add_Edge(int v1,int v2)
+{
+  PF_EDGES temp  = NULL;
+  ListHead *pListHead;
+  BOOL flag = TRUE;
+  register int t,count = 0;
+	
+	/*   Add a new edge into the edge data structure */
+  if (v1 > v2)
+	{
+		t  = v1;
+		v1 = v2;
+		v2 = t;
+	}
+	
+  pListHead = PolEdges[v1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+	if (temp == NULL)
+  {
+    printf("Have the wrong edge \n:");
+    exit(1);
+  }
+	
+	while (flag)
+	{
+		if (v2 == temp->edge[0])
+      return;
+    else
+    	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,++count);
+	}                	
+}
+
+void Add_AdjEdge(int v1,int v2,int fnum,int index1 )
+{
+  PF_EDGES temp  = NULL;
+  PF_FACES temp2 = NULL;
+  PF_EDGES pfNode;
+  ListHead *pListHead;
+  ListHead *pListFace;
+  BOOL 	flag = TRUE;
+  register int	count = 0;
+  register int	t,v3 = -1;
+	
+	if (v1 > v2)
+	{
+		t  = v1;
+		v1 = v2;
+		v2 = t;
+	}
+	pListFace  = PolFaces[fnum];
+	temp2 = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+	pListHead = PolEdges[v1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+	if (temp == NULL)
+		flag = FALSE;
+	count++;
+	while (flag)
+	{
+		if (v2 == temp->edge[0])
+		{
+      /*   If greater than 2 polygons adjacent to an edge, then we will
+           only save the first 2 that we found. We will have a small performance
+           hit, but this does not happen often.
+      */
+      if (temp->edge[2] == -1)
+        temp->edge[2] = fnum;
+      else
+        v3 = temp->edge[2];
+      flag = FALSE;
+		}
+		else
+		{
+			temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+			count++;
+			if (temp == NULL)
+				flag = FALSE;
+		}
+	}
+                
+	/*   Did not find it */
+  if (temp == NULL)
+	{
+		pfNode = (PF_EDGES) malloc(sizeof(F_EDGES) );
+    if ( pfNode )
+    {
+      pfNode->edge[0] = v2;
+			pfNode->edge[1] = fnum;
+	    pfNode->edge[2] =  v3;
+			AddTail( PolEdges[v1], (PLISTINFO) pfNode );
+    }
+		else
+    {
+      printf("Out of memory!\n");
+      exit(1);
+    }
+		
+    *(temp2->VertandId+index1) = pfNode;
+	}
+	else
+	  *(temp2->VertandId+index1) =  temp;
+}
diff --git a/Stripe_w/add.h b/Stripe_w/add.h
new file mode 100644
index 000000000..fb37f729a
--- /dev/null
+++ b/Stripe_w/add.h
@@ -0,0 +1,31 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: add.h
+-----------------------------------------------------------------------*/
+
+#include "global.h"
+
+BOOL new_vertex(double difference, int id1,int id2,
+                struct vert_struct *n);
+BOOL Check_VN(int vertex,int normal, struct vert_added *added);
+BOOL norm_array(int id, int vertex, double normal_difference,
+                struct vert_struct *n, int num_vert);
+void add_texture(int id,BOOL vertex);
+int	add_vert_id(int id, int	index_count);
+void	add_norm_id(int id, int index_count);
+void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+		int norms[STRIP_MAX]);
+void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+	      int norms[STRIP_MAX]);
+void Add_Edge(int v1,int v2);
+void Add_AdjEdge(int v1,int v2,int fnum,int index1 );
+
+
+
diff --git a/Stripe_w/bands.c b/Stripe_w/bands.c
new file mode 100644
index 000000000..981c13255
--- /dev/null
+++ b/Stripe_w/bands.c
@@ -0,0 +1,560 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: bands.c
+     This file contains the main procedure code that will read in the
+     object and then call the routines that produce the triangle strips.
+*/
+/*---------------------------------------------------------------------*/
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+  
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "global.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "ties.h"
+#include "outputex.h"
+#include "options.h"
+#include "local.h"
+#include "init.h"
+#include "free.h"
+#include "add.h"
+
+/*   TIMING for Windows */
+#ifdef WIN32
+#include <sys/timeb.h>
+#include <time.h>
+/*   TIMING for UNIX */
+#else
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/times.h>
+extern long times( );
+long elapsed()
+{
+  static long total = 0;
+  long cpu_time, dummy;
+  struct tms buffer;
+  times(&buffer);
+  dummy    = buffer.tms_utime  + buffer.tms_stime +
+             buffer.tms_cutime + buffer.tms_cstime;
+  cpu_time = ((dummy - total) * 1000) / HZ;
+  total    = dummy;
+  return(cpu_time);
+}
+#endif
+
+
+int     norms[STRIP_MAX];
+int     *vert_norms;
+int     *vert_texture;
+
+
+void get_time()
+{
+  /*   For timing */
+#ifdef WIN32
+  struct timeb timebuffer;
+  char *timeline;
+#else
+  long timer;
+#endif
+
+
+#ifdef WIN32
+  ftime( &timebuffer );
+  timeline = ctime( & ( timebuffer.time ) );
+  printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );
+#else
+  timer = elapsed();
+  printf("The time is %ld\n",timer);
+#endif
+}
+
+/*
+** 
+     Here the main program begins. It will start by loading in a .obj file
+     then it will convert the polygonal model into triangle strips.
+**  
+*/
+
+int main (int argc,char *argv[])
+{
+  char	*fname,*all,buff[255], *ptr, *ptr2;
+	FILE	*file, *bands;
+	int face_id=0;
+  int vert_count=0;
+  int loop=0;
+  int num=0;
+  int num2=0;
+
+	float center[3];
+  int temp[STRIP_MAX],vertex,strips, swaps,tempi,cost,triangles;
+  int f,t,tr,g;
+  char *file_open;
+	int	num_vert	= 0,
+		num_faces	= 0,
+		num_nvert	= 0,
+		num_edges	= 0,
+    num_texture = 0,
+    num_tris = 0;
+  double fra = 0.0;
+  BOOL texture, normal, normal_and_texture,quads = FALSE;
+
+  /*   Options variables */
+  double norm_difference;
+
+	/*   Structures for the object */
+  struct vert_struct	*vertices	= NULL,
+    *nvertices	= NULL,
+		*pvertices	= NULL,
+		*pnvertices	= NULL;
+
+  get_time();
+
+  /*   File that will contain the triangle strip data */
+  bands = fopen("stripe.objf","w");
+
+  /*
+	Scan the file once to find out the number of vertices,
+	vertice normals, and faces so we can set up some memory
+	structures 
+	*/
+	/* Interpret the options specified */
+	norm_difference = get_options(argc,argv,&f,&t,&tr,&g);
+  if (f == BINARY)
+    file_open = "rb";
+  else
+    file_open = "r";
+
+	fname = argv[argc-1];
+
+  printf ("File: %s\n",fname);
+	printf ("Scanning...%s ",file_open);
+
+	    
+  /*   File can be in binary for faster reading */
+  if (file = fopen (fname,file_open))
+	{
+	  while (!feof (file))
+		{
+			/*   Read a line */
+      if (f == BINARY)
+        fread (buff,sizeof(char) * 255,1, file);
+			else
+        fgets (buff, sizeof(char) * 255, file);
+      num++;
+      
+      printf("%d\r",num);
+
+      
+      /*   At a vertex */
+      if (*buff == 'v')
+			{
+				/*   At a normal */
+        if (*(buff+1)=='n')
+					num_nvert++;
+				else if (*(buff+1)=='t')
+          num_texture++;
+        /*   At a regular vertex */
+        else
+				  num_vert++;
+			}
+			/*   At a face */
+      else if (*buff == 'f')
+			{  
+        num_faces++;
+			  strtok(buff, " ");
+			  tempi = 0;
+			  while (strtok(NULL, " ") != NULL) tempi++;
+			  num_tris += tempi - 2;
+      }
+		}
+		fclose (file);
+  }
+	else
+  {
+    printf("Error in the file name\n");
+    exit(1);
+  }
+	
+  printf("%s pass 1\n",fname);
+	
+	/* Allocate structures for the information */
+	Start_Face_Struct(num_faces);
+	vertices = (struct vert_struct *)
+			malloc (sizeof (struct vert_struct) * num_vert);
+
+	if (num_nvert > 0) {
+    nvertices = (struct vert_struct *)
+		malloc (sizeof (struct vert_struct) * num_nvert);
+    vert_norms = (int *) malloc (sizeof (int) * num_vert);
+    /*   
+    Initialize entries to zero, in case there are 2 hits
+    to the same vertex we will know it - used for determining
+    the normal difference
+    */
+    init_vert_norms(num_vert);
+  } else {
+		nvertices = NULL;
+  }
+
+  if (num_texture > 0) {
+    vert_texture = (int *) malloc (sizeof(int) * num_vert);
+    init_vert_texture(num_vert);
+  }
+     
+	/*
+  Set up the temporary 'p' pointers 
+  */
+	pvertices = vertices;
+	pnvertices = nvertices;
+
+	/* Load the object into memory */
+	/*printf (" Loading...");*/
+ 
+   fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname);
+ 
+  /*  File will be put in a list for faster execution if file is in binary */   
+  if (file = fopen(fname,file_open)) {
+    if (f == BINARY) {
+      all = (char *) malloc (sizeof(char) * 255 * num);
+      fread(all,sizeof(char) * 255 * num, 1, file);
+      ptr = all;
+    } else {
+      ptr = (char *) malloc (sizeof(char) * 255 * num);
+    }
+  }
+
+   
+  while (num > 0) {
+    num--;
+
+    printf("%d\r",num);
+
+		if (f == ASCII) {
+      fgets (ptr, sizeof(char) * 255, file);
+    } else {
+      ptr = ptr + 255;
+    }
+
+    /* Load in vertices/normals */
+		if (*ptr == 'v') {
+			if (*(ptr+1)=='n') {
+				sscanf (ptr+3,"%lf%lf%lf",
+					&(pnvertices->x),
+					&(pnvertices->y),
+					&(pnvertices->z));
+	   			fprintf(bands,"vn %f %f %f\n",
+					pnvertices->x,pnvertices->y,pnvertices->z); 
+     			++pnvertices;
+			} else if (*(ptr+1)=='t') {
+				sscanf (ptr+3,"%f%f%f",&center[0],&center[1],&center[2]);
+	   		fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]); 
+      } else {
+				sscanf (ptr+2,"%lf%lf%lf",
+					&(pvertices->x), 
+					&(pvertices->y), 
+					&(pvertices->z));
+     			fprintf(bands,"v %f %f %f\n",
+					pvertices->x,pvertices->y,pvertices->z); 
+				++pvertices;
+      }
+		} else if (*ptr == 'f') {
+			/* Read in faces */
+			num2 = 0;
+			face_id++;
+      ptr2 = ptr+1;
+      normal = FALSE; texture = FALSE, normal_and_texture = FALSE;
+      while (*ptr2) {
+			  if (*ptr2 >='0' && *ptr2 <='9') {
+				  num2++;
+				  ++ptr2;
+				  while (*ptr2 && (*ptr2!=' ' && *ptr2!='/')) {
+					  ptr2++;
+          }
+          /*   There are normals in this line */
+          if (*ptr2 == '/') {
+            if (*(ptr2+1) == '/') {
+              normal = TRUE;
+            } else {
+              texture = TRUE;
+            }
+			    } else if (*ptr2 == ' ') {
+            if ((num2 == 3) && (texture)) {
+              normal_and_texture = TRUE;
+            }
+          }
+        } else {
+				  ++ptr2;
+        }
+			}
+
+      ptr2 = ptr+1;
+			
+      /* 
+      loop on the number of numbers in this line of face data 
+      */
+			vert_count = 0;
+								
+			for (loop=0;loop<num2;loop++) {
+				/* skip the whitespace */
+				while (*ptr2<'0' || *ptr2>'9') {
+          if (*ptr2 == '-') {
+            break;
+          }
+          ptr2++;
+        }
+				vertex = atoi(ptr2)-1;
+        if (vertex < 0) {
+          vertex = num_vert + vertex;
+          *ptr2 = ' ';
+          ptr2++;
+        }
+        /*
+        If there are either normals or textures with the vertices
+        in this file, the data alternates so we must read it this way 
+        */
+				if ( (normal) && (!normal_and_texture)) {
+					if (loop%2) {
+            add_norm_id(vertex,vert_count);
+            /*
+            Test here to see if we added a new vertex, since the
+            vertex has more than one normal and the 2 normals are greater
+            than the threshold specified
+            */
+            if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
+              /*
+              Add a new vertex and change the
+              id of the vertex that we just read to the id of the new
+              vertex that we just added
+              */
+              /*
+              Put it in the output file, note the added vertices will
+              be after the normals and separated from the rest of the 
+              vertices. Will not affect our viewer
+              */
+              fprintf(bands,"v %f %f %f\n",
+                (vertices + temp[vert_count - 1])->x,
+                (vertices + temp[vert_count - 1])->y,
+                (vertices + temp[vert_count - 1])->z); 
+              num_vert++;
+              temp[vert_count - 1] = num_vert - 1;
+              if (!(add_vert_id(num_vert - 1,vert_count))) {
+                vert_count--;
+              }
+            }
+          } else {
+					  /* the vertex */
+						temp[vert_count] = vertex ;
+						vert_count++;
+            if (!(add_vert_id(vertex,vert_count))) {
+                vert_count--;
+            }
+            norm_array(vertex,1,norm_difference,nvertices,num_vert);
+					}
+        } else if (normal_and_texture) {                      
+          /* Else there are vertices and textures with the data */
+          if( !((loop+1)%3)) {
+            add_norm_id(vertex,vert_count);
+            /*
+            Test here to see if we added a new vertex, since the
+            vertex has more than one normal and the 2 normals are greater
+            than the threshold specified
+            */
+            if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
+              /*
+              Add a new vertex and change the
+              id of the vertex that we just read to the id of the new
+              vertex that we just added
+              */
+              /*
+              Put it in the output file, note the added vertices will
+              be after the normals and separated from the rest of the 
+              vertices. Will not affect our viewer
+              */
+              fprintf(bands,"v %f %f %f\n",
+                (vertices + temp[vert_count - 1])->x,
+                (vertices + temp[vert_count - 1])->y,
+                (vertices + temp[vert_count - 1])->z); 
+              num_vert++;
+              temp[vert_count - 1] = num_vert - 1;
+              if (!(add_vert_id(num_vert - 1,vert_count))) {
+                vert_count--;
+              }
+            }
+          } else if ((loop == 0) || (*(ptr2-1) == ' ')) {
+            /*   the vertex */
+            temp[vert_count] = vertex ;
+            vert_count++;
+            if (vert_count == 4) {
+              quads = TRUE;
+            }
+            if (!(add_vert_id(vertex,vert_count))) {
+              vert_count--;
+            }
+            add_texture(vertex,TRUE);
+            norm_array(vertex,1,norm_difference,nvertices,num_vert);
+					} else {
+            /*   The texture */
+            add_texture(vertex,FALSE);
+          }
+        } else if ( texture ) {
+					/*   the vertex */
+          if (!(loop%2)) {
+						temp[vert_count] = vertex ;
+						vert_count++;
+            if (vert_count == 4)
+              quads = TRUE;
+            add_texture(vertex,TRUE);
+            if (!(add_vert_id(vertex,vert_count)))
+              vert_count--;
+            norm_array(vertex,1,norm_difference,nvertices,num_vert);
+					} else {
+            /*   texture */
+            add_texture(vertex,FALSE);
+          }
+        } else {
+				  /*** no nvertices ***/
+					temp[vert_count] = vertex ;
+					vert_count++;
+          if (vert_count == 4)
+            quads = TRUE;
+          if (!(add_vert_id(vertex,vert_count)))
+            vert_count--;
+				}
+				while (*ptr2>='0' && *ptr2<='9')
+					ptr2++;
+      }
+			/* Done with the polygon */
+			num_edges += vert_count;
+			/* add it to face structure */
+			if (vert_count >= 3)
+        AddNewFace(ids,vert_count,face_id,norms);
+      else
+        face_id--;
+      if (vert_count == 4)
+        quads = TRUE;
+    }
+    else if ((g == TRUE) && (face_id > 0)
+         && ((*ptr == 'g') || (*ptr  == 's') || (*ptr == 'm') || (*ptr == 'o')))
+    {
+      /*
+      The user specified that the strips will be contained in each group
+      from the data file, so we just finished a group and will find the
+      triangle strips in it.
+      */
+      Start_Edge_Struct(num_vert);
+	    Find_Adjacencies(face_id);
+	    if (quads)
+      {
+        Init_Table_SGI();
+	      Build_SGI_Table(num_vert,face_id);
+        /* Code for lengths of walks in each direction */
+	      /* Save_Walks(face_id,TRUE); */
+	      Save_Walks(face_id);
+
+        /* Code for finding the bands */
+	      Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
+
+        /*
+        Remove the faces that we did  so that we can
+        run the strip code on the rest of the faces that are left
+        */
+        if (cost != 0)
+        {
+          printf("Total %d triangles with %d cost\n",triangles,cost);
+          Save_Rest(&face_id);
+          printf("We saved %d .... now doing the local algorithm\n",face_id);
+          fprintf(bands,"\n#local\n");
+	        End_Edge_Struct(num_vert);
+          Start_Edge_Struct(num_vert);
+	        Find_Adjacencies(face_id);
+        }
+      }
+	       
+      SGI_Strip(num_vert,face_id,bands,t,tr);
+
+      /* Get the total cost */
+      Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
+
+      End_Face_Struct(num_faces);
+      End_Edge_Struct(num_vert);
+      cost = 0;
+      face_id = 0;
+      quads = FALSE;
+      Start_Face_Struct(num_faces-face_id);
+      num_faces = num_faces - face_id;
+      Free_Strips();
+    }
+  }
+               
+  /*   Done reading in all the information into data structures */
+  num_faces = face_id;
+  fclose (file);
+  
+  printf("Input Done.\n\n");
+
+  free(vertices);
+  free(nvertices);
+
+  printf ("Vertices:	%d\nNormals:	%d\nFaces:		%d\n",num_vert,num_nvert,num_faces);
+
+  Start_Edge_Struct(num_vert);
+  Find_Adjacencies(num_faces);
+
+  /* Initialize it */
+  Init_Table_SGI();
+  /* Build it */
+  Build_SGI_Table(num_vert,num_faces);
+
+  InitStripTable();
+
+  if (quads) {
+    /* Code for lengths of walks in each direction */
+          /* Save_Walks(num_faces,TRUE); */
+	  Save_Walks(num_faces);
+	  
+    /* Code for finding the bands */
+	  Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
+    /*printf("Total %d triangles with %d cost\n",triangles,cost);*/
+
+    /*  
+    Remove the faces that we did  so that we can
+    run the strip code on the rest of the faces that are left
+    */
+    Save_Rest(&num_faces);
+    /*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/
+    fprintf(bands,"\n#local\n");
+	  End_Edge_Struct(num_vert);
+    Start_Edge_Struct(num_vert);
+	  Find_Adjacencies(num_faces);
+  }
+	       
+  SGI_Strip(num_vert,num_faces,bands,t,tr);
+
+  /*   Get the total cost */
+  Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
+
+  End_Face_Struct(num_faces);
+  End_Edge_Struct(num_vert);
+  fclose(bands);
+
+  get_time();
+
+  return(0);
+}
+
diff --git a/Stripe_w/common.c b/Stripe_w/common.c
new file mode 100644
index 000000000..ca836e19f
--- /dev/null
+++ b/Stripe_w/common.c
@@ -0,0 +1,810 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: common.c
+     This file contains common code used in both the local and global algorithm
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "extend.h"
+#include "output.h"
+#include "triangulate.h"
+#include "util.h"
+#include "add.h"
+
+int  Old_Adj(int face_id)
+{
+	/*	Find the bucket that the face_id is currently in,
+		because maybe we will be deleting it. 
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y;
+	
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	size = temp->nPolSize;
+	if (Done(face_id,size,&y) == NULL)
+	{
+		printf("There is an error in finding the face\n");
+		exit(0);
+	}
+	return y;
+}
+
+int Number_Adj(int id1, int id2, int curr_id)
+{
+	/*	Given edge whose endpoints are specified by id1 and id2,
+		determine how many polygons share this edge and return that
+		number minus one (since we do not want to include the polygon
+		that the caller has already).
+	*/
+
+	int size,y,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	BOOL there= FALSE;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	new edge that was created might not be here */
+		return 0;
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	This edge was not there in the original, which
+				mean that we created it in the partial triangulation.
+				So it is adjacent to nothing.
+			*/
+			return 0;
+	}
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return 0;
+	else
+	{
+		/*	It was adjacent to another polygon, but maybe we did this
+			polygon already, and it was done partially so that this edge
+			could have been done
+		*/
+		if (curr_id != temp->edge[1])
+		{
+			/*	Did we use this polygon already?and it was deleted
+				completely from the structure
+			*/
+			pListHead = PolFaces[temp->edge[1]];
+			temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+			if (Done(temp->edge[1],temp2->nPolSize,&size) == NULL)
+				return 0;
+		}
+		else
+		{
+			pListHead = PolFaces[temp->edge[2]];
+			temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+			if (Done(temp->edge[2],temp2->nPolSize,&size)== NULL)
+				return 0;
+		}
+
+		/*	Now we have to check whether it was partially done, before
+			we can say definitely if it is adjacent.
+			Check each edge of the face and tally the number of adjacent
+			polygons to this face. 
+		*/	      		
+		if ( temp2 != NULL )
+		{
+			/*	Size of the polygon */
+			size = temp2->nPolSize;
+			for (y = 0; y< size; y++)
+			{
+				/*	If we are doing partial triangulation, we must check
+					to see whether the edge is still there in the polygon,
+					since we might have done a portion of the polygon
+					and saved the rest for later.
+				*/
+				if (y != (size-1))
+				{
+					if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+						|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+						/*	edge is still there we are ok */
+						there = TRUE;
+				}
+				else
+				{
+					if( ((id1 == *(temp2->pPolygon)) && (id2 == *(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+						there = TRUE;
+				}
+			}
+		}
+		
+		if (there )
+			return 1;
+		return 0;
+	}
+}
+
+int Min_Adj(int id)
+{
+	/*	Used for the lookahead to break ties. It will
+		return the minimum adjacency found at this face.
+	*/
+	int y,numverts,t,x=60;
+	PF_FACES temp=NULL;
+	ListHead *pListHead;
+
+	/*	If polygon was used then we can't use this face */
+	if (Done(id,59,&y) == NULL)
+		return 60;
+		
+	/*	It was not used already */
+	pListHead = PolFaces[id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+     if ( temp != NULL )
+	{
+		numverts = temp->nPolSize;
+		for (y = 0; y< numverts; y++)
+		{
+			if (y != (numverts-1))
+				t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id);
+			else
+				t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id);
+			if (t < x)
+				x = t;
+		}
+	}
+	if (x == -1)
+	{
+		printf("Error in the look\n");
+		exit(0);
+	}
+	return x;
+}
+
+
+
+void Edge_Least(int *index,int *new1,int *new2,int face_id,int size)
+{
+    /*   We had a polygon without an input edge and now we re going to pick one
+         of the edges with the least number of adjacencies to be the input
+         edge
+    */
+    register int x,value,smallest=60;
+
+    for (x = 0; x<size; x++)
+    {
+        if (x != (size -1) )
+            value = Number_Adj(*(index+x),*(index+x+1),face_id);
+        else 
+            value = Number_Adj(*(index),*(index+size-1),face_id);
+        if (value < smallest)
+        {
+            smallest = value;
+            if (x != (size -1))
+            {
+                *new1 = *(index+x);
+                *new2 = *(index+x+1);
+            }
+            else
+            {
+                *new1 = *(index);
+                *new2 = *(index+size-1);
+            }
+        }
+    }
+    if ((smallest == 60) || (smallest < 0))
+    {
+        printf("There is an error in getting the least edge\n");
+        exit(0);
+    }
+}
+
+
+void Check_In_Polygon(int face_id, int *min, int size)
+{
+    /*  Check to see the adjacencies by going into a polygon that has
+        greater than 4 sides.
+    */
+    
+    ListHead *pListHead;
+    PF_FACES temp;
+    int y,id1,id2,id3,x=0,z=0;
+    int saved[2];
+    int big_saved[60];
+
+    pListHead = PolFaces[face_id];
+    temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+
+    /*   Get the input edge that we came in on */
+    Last_Edge(&id1,&id2,&id3,0);
+
+    /*  Find the number of adjacencies to the edges that are adjacent
+        to the input edge.
+    */
+    for (y=0; y< size; y++)
+    {
+        if (y != (size-1))
+        {
+            if (((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3))
+                || ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+                big_saved[z++] = saved[x-1];
+            }
+            else
+                big_saved[z++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+        }
+        else
+        {
+            if (((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) != id3))
+                || ((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+                big_saved[z++] = saved[x-1];
+            }
+            else
+                big_saved[z++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+        }
+    }
+    /*  There was an input edge */
+    if (x == 2)
+    {
+        if (saved[0] < saved[1])
+            /*  Count the polygon that we will be cutting as another adjacency*/
+            *min = saved[0] + 1;
+        else
+            *min = saved[1] + 1;
+    }
+    /*  There was not an input edge */
+    else
+    {
+        if (z != size)
+        {
+            printf("There is an error with the z %d %d\n",size,z);
+            exit(0);
+        }
+        *min = 60;
+        for (x = 0; x < size; x++)
+        {
+            if (*min > big_saved[x])
+                *min = big_saved[x];
+        }
+    }
+}
+
+
+void New_Face (int face_id, int v1, int v2, int v3)
+{
+	/*	We want to change the face that was face_id, we will
+		change it to a triangle, since the rest of the polygon
+		was already outputtted
+	*/
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	pListHead = PolFaces[face_id];
+     temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0);
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+	{
+		/*	Size of the polygon */
+		if (temp->nPolSize != 4)
+		{
+			printf("There is a miscalculation in the partial\n");
+			exit (0);
+		}
+		temp->nPolSize = 3;
+		*(temp->pPolygon) = v1;
+		*(temp->pPolygon+1) = v2;
+		*(temp->pPolygon+2) = v3;
+	}
+}
+
+void New_Size_Face (int face_id)
+{
+	/*	We want to change the face that was face_id, we will
+		change it to a triangle, since the rest of the polygon
+		was already outputtted
+	*/
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+		(temp->nPolSize)--;
+	else
+		printf("There is an error in updating the size\n");
+}
+
+
+
+void  Check_In_Quad(int face_id,int *min)
+{
+     /*   Check to see what the adjacencies are for the polygons that
+          are inside the quad, ie the 2 triangles that we can form.
+     */
+    ListHead *pListHead;
+    int y,id1,id2,id3,x=0;
+    int saved[4];
+    PF_FACES temp;
+    register int size = 4;
+
+    pListHead = PolFaces[face_id];
+    temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+     /*   Get the input edge that we came in on */
+    Last_Edge(&id1,&id2,&id3,0);
+	
+    /*    Now find the adjacencies for the inside triangles */
+    for (y = 0; y< size; y++)
+	{
+         /*     Will not do this if the edge is the input edge */
+         if (y != (size-1))
+         {
+              if ((((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) == id3))) ||
+             (((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) == id2))))
+                    saved[x++] = -1;
+              else
+              {
+                   if (x == 4)
+                   {
+                        printf("There is an error in the check in quad \n");
+                        exit(0);
+                   }
+                   /*    Save the number of Adjacent Polygons to this edge */
+                   saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+              }
+         }
+		else if ((((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) == id3))) ||
+             (((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) == id2))) )
+             saved[x++] = -1;
+        else
+        {
+               if (x == 4)
+               {
+                    printf("There is an error in the check in quad \n");
+                    exit(0);
+               }
+               /*    Save the number of Adjacent Polygons to this edge */
+               saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+
+        }
+    }
+    if (x != 4)
+    {
+         printf("Did not enter all the values %d \n",x);
+         exit(0);
+    }
+    
+    *min = 10;
+    for (x=0; x<4; x++)
+    {
+         if (x!= 3)
+         {
+              if ((saved[x] != -1) && (saved[x+1] != -1) && 
+                   ((saved[x] + saved[x+1]) < *min))
+                   *min = saved[x] + saved[x+1];
+         }
+         else
+         {
+              if ((saved[0] != -1) && (saved[x] != -1) &&
+                   ((saved[x] + saved[0]) < *min))
+                   *min = saved[0] + saved[x];
+         }
+    }
+}
+
+
+
+int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3)
+{
+    /*  Return the vertex adjacent to either input1 or input2 that
+        is adjacent to the least number of polygons on the edge that
+        is shared with either input1 or input2.
+    */
+    register int x=0,y;
+    int saved[2];
+    int edges[2][1];
+
+    for (y = 0; y < size; y++)
+    {
+        if (y != (size-1))
+        {
+            if (((*(index+y) == id2) && (*(index+y+1) != id3))
+                || ((*(index+y) == id3) && (*(index+y+1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id);
+                edges[x-1][0] = *(index+y+1);
+            }
+            else if (y != 0)
+            {
+                if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) ||
+                    ( (*(index+y) == id3) && (*(index+y-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id);
+                    edges[x-1][0] = *(index+y-1);
+                }
+            }
+            else if (y == 0)
+            {
+                if (( (*(index) == id2) && (*(index+size-1) != id3) ) ||
+                    ( (*(index) == id3) && (*(index+size-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
+                    edges[x-1][0] = *(index+size-1);
+                }
+            }
+
+        }
+        else
+        {
+            if (((*(index+size-1) == id2) && (*(index) != id3))
+                || ((*(index+size-1) == id3) && (*(index) != id2)))
+            {
+                saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
+                edges[x-1][0] = *(index);
+            }
+
+            if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) ||
+                    ( (*(index+size-1) == id3) && (*(index+y-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id);
+                    edges[x-1][0] = *(index+y-1);
+                }
+        }
+    }
+    if ((x != 2))
+    {
+        printf("There is an error in getting the input edge %d \n",x);
+        exit(0);
+    }
+    if (saved[0] < saved[1])
+        return edges[0][0];
+    else
+        return edges[1][0];
+
+}
+
+void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,int size,
+                    int face_id)
+{
+    /*  We had a polygon without an input edge and now we are going to pick one
+        as the input edge. The last triangle was id1,id2,id3, we will try to
+        get an edge to have something in common with one of those vertices, otherwise
+        we will pick the edge with the least number of adjacencies.
+    */
+
+    register int x;
+    int saved[3];
+
+    saved[0] = -1;
+    saved[1] = -1;
+    saved[2] = -1;
+    
+    /*  Go through the edges to see if there is one in common with one
+        of the vertices of the last triangle that we had, preferably id2 or
+        id3 since those are the last 2 things in the stack of size 2.
+    */
+    for (x=0; x< size; x++)
+    {
+        if (*(index+x) == id1)
+        {
+            if (x != (size-1))
+                saved[0] = *(index+x+1);
+            else
+                saved[0] = *(index);
+        }
+
+        if (*(index+x) == id2)
+        {
+            if (x != (size-1))
+                saved[1] = *(index+x+1);
+            else
+                saved[1] = *(index);
+        }
+        
+        if (*(index+x) == id3)
+        {
+            if (x != (size -1))
+                saved[2] = *(index+x+1);
+            else
+                saved[2] = *(index);
+        }
+    }
+    /*  Now see what we saved */
+    if (saved[2] != -1)
+    {
+        *new1 = id3;
+        *new2 = saved[2];
+        return;
+    }
+    else if (saved[1] != -1)
+    {
+        *new1 = id2;
+        *new2 = saved[1];
+        return;
+    }
+    else if (saved[0] != -1)
+    {
+        *new1 = id1;
+        *new2 = saved[0];
+        return;
+    }
+    /*  We did not find anything so get the edge with the least number of adjacencies */
+    Edge_Least(index,new1,new2,face_id,size);
+
+}
+
+int Find_Face(int current_face, int id1, int id2, int *bucket)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face.
+	*/
+	register int size,y,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	int next_face;
+	BOOL there = FALSE;
+
+    
+    /*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     /*  The input edge was a new edge */
+     if (temp == NULL)
+        return -1;
+        
+     while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          /*  The input edge was a new edge */
+          if (temp == NULL)
+            return -1;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return -1;
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. 
+	*/
+	pListHead = PolFaces[next_face];
+	temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+		
+     /*	See if the face was already deleted, and where
+              it is if it was not
+     */
+		
+     if (Done(next_face,59,bucket) == NULL)
+        return -1;
+
+     /*  Make sure the edge is still in this polygon, and that it is not
+         done
+     */
+		/*	Size of the polygon */
+		size = temp2->nPolSize;
+		for (y = 0; y< size; y++)
+		{
+			/*	Make sure that the edge is still in the
+				polygon and was not deleted, because if the edge was
+				deleted, then we used it already.
+			*/
+			if (y != (size-1))
+			{
+				if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+					|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{		
+				if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+		if (!there)
+			/*	Edge already used and deleted from the polygon*/
+			return -1;
+         else
+            return next_face;
+}
+
+BOOL Look_Up(int id1,int id2,int face_id)
+{
+	/*	See if the endpoints of the edge specified by id1 and id2
+		are adjacent to the face with face_id 
+	*/
+	register int count = 0;
+	PF_EDGES temp  = NULL;
+	ListHead *pListHead;
+		
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	Was a new edge that we created */
+		return 0;
+	
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	Was a new edge that we created */
+			return 0;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id))
+	{
+		/*	Edge was adjacent to face, make sure that edge is 
+			still there
+		*/
+		if (Exist(face_id,id1,id2))
+			return 1;
+		else
+			return 0;
+	}
+	else
+		return 0;
+}
+
+
+void Add_Id_Strips(int id, int where)
+{
+     /*    Just save the triangle for later  */
+     P_STRIPS pfNode;
+
+	pfNode = (P_STRIPS) malloc(sizeof(Strips) );
+	if ( pfNode )
+	{
+	     pfNode->face_id = id;
+	     if (where == 1)
+     		 AddTail(strips[0],(PLISTINFO) pfNode);
+	     /* We are backtracking in the strip */
+	     else
+		 AddHead(strips[0],(PLISTINFO) pfNode);
+	}
+	else
+	{
+	     printf("There is not enough memory to allocate for the strips\n");
+	     exit(0);
+	}
+}
+
+
+int Num_Adj(int id1, int id2)
+{
+	/*   Given edge whose endpoints are specified by id1 and id2,
+		determine how many polygons share this edge and return that
+		number minus one (since we do not want to include the polygon
+		that the caller has already).
+	*/
+
+	PF_EDGES temp = NULL;
+	ListHead *pListHead;
+	register count=-1;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+	{
+		printf("There is an error in the creation of the table \n");
+		exit(0);
+	}
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+	     if (temp == NULL)
+		{
+			printf("There is an error in the creation of the table\n");
+			exit(0);
+		}
+	}
+	/*      Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return 0;
+	return 1;
+}
+
+
+void Add_Sgi_Adj(int bucket,int face_id)
+{
+	/*   This routine will add the face to the proper bucket,
+		depending on how many faces are adjacent to it (what the
+		value bucket should be).
+	*/
+	P_ADJACENCIES pfNode;
+
+	pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+     if ( pfNode )
+     {
+		pfNode->face_id = face_id;
+	     AddHead(array[bucket],(PLISTINFO) pfNode);
+	}
+	else
+	{
+		printf("Out of memory for the SGI adj list!\n");
+		exit(0);
+	}
+}
+
+void Find_Adjacencies(int num_faces)
+{
+     register int	x,y;
+     register int	numverts;
+     PF_FACES temp=NULL;
+     ListHead *pListHead;
+
+	/*   Fill in the adjacencies data structure for all the faces */
+     for (x=0;x<num_faces;x++)
+	{
+        	pListHead = PolFaces[x];
+		temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+     	if ( temp != NULL )
+		{
+			numverts = temp->nPolSize;
+			if (numverts != 1)
+               {
+                    for (y = 0; y< numverts; y++)
+			     {
+				     if (y != (numverts-1))
+					     Add_AdjEdge(*(temp->pPolygon+y),*(temp->pPolygon+y+1),x,y);
+			
+				     else 
+					     Add_AdjEdge(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),x,numverts-1);
+			
+                    }
+               }
+			temp = NULL;
+		}
+	}
+}
+
+
diff --git a/Stripe_w/common.h b/Stripe_w/common.h
new file mode 100644
index 000000000..aca19824b
--- /dev/null
+++ b/Stripe_w/common.h
@@ -0,0 +1,42 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: common.h
+-----------------------------------------------------------------------*/
+
+void Add_AdjEdge(int v1,int v2,int fnum,int index1 );
+void Find_Adjacencies(int num_faces);
+void Add_Sgi_Adj(int bucket,int face_id);
+int Num_Adj(int id1, int id2);
+void Add_Id_Strips(int id, int where);
+BOOL Look_Up(int id1,int id2,int face_id);
+int Number_Adj(int id1, int id2, int curr_id);
+int  Old_Adj(int face_id);
+int Min_Adj(int id);
+int Find_Face(int current_face, int id1, int id2, int *bucket);
+void Edge_Least(int *index,int *new1,int *new2,int face_id,int size);
+void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,
+		    int size, int face_id);
+int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3);
+void Check_In_Polygon(int face_id, int *min, int size);
+void  Check_In_Quad(int face_id,int *min);
+void New_Size_Face (int face_id);
+void New_Face (int face_id, int v1, int v2, int v3);
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Stripe_w/extend.h b/Stripe_w/extend.h
new file mode 100644
index 000000000..78c135e3a
--- /dev/null
+++ b/Stripe_w/extend.h
@@ -0,0 +1,17 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: extend.h
+-----------------------------------------------------------------------*/
+
+int Bottom_Left();
+int Top_Left();
+void Start_Edge();
+
+
diff --git a/Stripe_w/free.c b/Stripe_w/free.c
new file mode 100644
index 000000000..ad655fcf7
--- /dev/null
+++ b/Stripe_w/free.c
@@ -0,0 +1,112 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: free.c
+     This file contains the code used to free the data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "polverts.h"
+
+ListHead *array[60];
+int     id_array[60];
+ListHead *strips[1];
+ListHead *all_strips[100000]; /*  Assume max 100000 strips */
+
+void ParseAndFreeList( ListHead *pListHead )
+{
+    register int c,num;
+	  
+    /*    Freeing a linked list */
+    num = NumOnList(pListHead);
+    for (c = 0; c< num; c++)
+	     RemHead(pListHead);
+} 
+
+void FreePolygonNode( PF_VERTS pfVerts)
+{
+	/*   Free a vertex node */
+     if ( pfVerts->pPolygon )
+		free( pfVerts->pPolygon );
+	free( pfVerts );
+
+}
+ 
+void Free_Strips()
+{
+    /*    Free strips data structure */
+    if (strips[0] == NULL)
+         return;
+    else
+         ParseAndFreeList(strips[0]);
+}
+
+void FreeFaceNode( PF_FACES pfFaces)
+{
+	/*   Free face node */
+     if ( pfFaces->pPolygon )
+                free( pfFaces->pPolygon );
+        free( pfFaces );
+}
+
+
+void FreeFaceTable(int nSize)
+{
+     register int nIndex;
+
+     for ( nIndex=0; nIndex < nSize; nIndex++ )
+     { 
+    		if ( PolFaces[nIndex] != NULL ) 
+             ParseAndFreeList( PolFaces[nIndex] );
+     }
+     free( PolFaces );
+}
+
+void FreeEdgeTable(int nSize)
+{
+        register int nIndex;
+
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                if ( PolEdges[nIndex] != NULL )
+                        ParseAndFreeList( PolEdges[nIndex] );
+        }
+        free( PolEdges );
+}
+
+
+void Free_All_Strips()
+{
+
+	ListHead *pListHead;
+	register int y;
+
+	for (y =0; ; y++)
+	{
+		pListHead = all_strips[y];
+		if (pListHead == NULL)
+			return;
+		else
+			ParseAndFreeList(all_strips[y]);
+	}
+}
+
+void End_Face_Struct(int numfaces)
+{
+     FreeFaceTable(numfaces);
+}
+
+void End_Edge_Struct(int numverts)
+{
+     FreeEdgeTable(numverts);
+}	
+
+
diff --git a/Stripe_w/free.h b/Stripe_w/free.h
new file mode 100644
index 000000000..4c1d055c6
--- /dev/null
+++ b/Stripe_w/free.h
@@ -0,0 +1,22 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: free.h
+-----------------------------------------------------------------------*/
+
+void Free_All_Strips();
+void ParseAndFreeList( ListHead *pListHead );
+void FreePolygonNode( PF_VERTS pfVerts);
+void Free_Strips();
+void FreeFaceTable(int nSize);
+void FreeEdgeTable(int nSize);
+void End_Face_Struct(int numfaces);
+void End_Edge_Struct(int numverts);
+
+
diff --git a/Stripe_w/global.h b/Stripe_w/global.h
new file mode 100644
index 000000000..3538f82f4
--- /dev/null
+++ b/Stripe_w/global.h
@@ -0,0 +1,44 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: global.h
+-----------------------------------------------------------------------*/
+
+#ifndef _GLOBAL_H
+#define _GLOBAL_H
+
+
+#define   VRDATA		double
+#define   STRIP_MAX            60
+	
+#define	TRUE	      	1
+#define	FALSE		0
+
+#ifndef PI
+#define   PI	     	3.1415926573
+#endif
+
+#define   ATOI(C)        (C -'0')
+#define   X              0
+#define   Y              1
+#define   Z              2
+#define   EVEN(x)       (((x) & 1) == 0)
+#define   MAX_BAND      10000
+
+struct vert_struct {
+	VRDATA	x, y, z;	/* point coordinates */
+};
+
+extern int     ids[STRIP_MAX];
+extern int     norms[STRIP_MAX];
+extern int     *vert_norms;
+extern int     *vert_texture;
+
+
+#endif _GLOBAL_H
diff --git a/Stripe_w/init.c b/Stripe_w/init.c
new file mode 100644
index 000000000..2e0f25885
--- /dev/null
+++ b/Stripe_w/init.c
@@ -0,0 +1,217 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: init.c
+     This file contains the initialization of data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "polverts.h"
+
+void init_vert_norms(int num_vert)
+{
+     /*   Initialize vertex/normal array to have all zeros to
+          start with.
+     */
+     register int x;
+
+     for (x = 0; x < num_vert; x++)
+          *(vert_norms + x) = 0;
+}
+
+void init_vert_texture(int num_vert)
+{
+     /*   Initialize vertex/normal array to have all zeros to
+          start with.
+     */
+     register int x;
+
+     for (x = 0; x < num_vert; x++)
+          *(vert_texture + x) = 0;
+}
+
+BOOL InitVertTable( int nSize )
+{
+     register int nIndex;
+
+	/*   Initialize the vertex table */
+     PolVerts = (ListHead**) malloc(sizeof(ListHead*) * nSize ); 
+	if ( PolVerts )
+	{
+		for ( nIndex=0; nIndex < nSize; nIndex++ )
+		{
+			PolVerts[nIndex] = NULL;
+		}
+		return( TRUE );	
+	}
+	return( FALSE );
+}  
+
+BOOL InitFaceTable( int nSize )
+{
+        register int nIndex;
+
+        /*     Initialize the face table */
+        PolFaces = (ListHead**) malloc(sizeof(ListHead*) * nSize ); 
+        if ( PolFaces )
+        {
+                for ( nIndex=0; nIndex < nSize; nIndex++ )
+                {
+                        PolFaces[nIndex] = NULL;
+                }
+                return( TRUE );
+        }
+        return( FALSE );
+} 
+
+BOOL InitEdgeTable( int nSize )
+{
+        register int nIndex;
+
+        /*     Initialize the edge table */
+        PolEdges = (ListHead**) malloc(sizeof(ListHead*) * nSize );
+        if ( PolEdges )
+        {
+                for ( nIndex=0; nIndex < nSize; nIndex++ )
+                {
+                        PolEdges[nIndex] = NULL;
+                }
+                return( TRUE );
+        }
+        return( FALSE );
+}
+
+
+void InitStripTable(  )
+{
+
+     PLISTHEAD pListHead;
+
+     /*   Initialize the strip table */
+     pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+	if ( pListHead )
+     {
+		InitList( pListHead );
+		strips[0] = pListHead;
+	}
+     else
+	{
+	     printf("Out of memory !\n");
+		exit(0);
+	}
+
+}
+
+void Init_Table_SGI()
+{
+	PLISTHEAD pListHead;
+	int max_adj = 60;
+	register int x;
+	
+	/*   This routine will initialize the table that will
+		have the faces sorted by the number of adjacent polygons
+		to it.
+	*/
+
+	for (x=0; x< max_adj; x++)
+	{
+		/* We are allowing the max number of sides of a polygon
+       to be max_adj.
+		*/                      
+		pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+		if ( pListHead )
+	  {
+		  InitList( pListHead );
+			array[x] = pListHead;
+		}
+    else
+		{
+		  printf("Out of memory !\n");
+			exit(0);
+		}
+	}
+}
+
+void BuildVertTable( int nSize )
+{
+  register int nIndex;
+  PLISTHEAD pListHead;
+	
+	for ( nIndex=0; nIndex < nSize; nIndex++ )
+	{
+		pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+		if ( pListHead )
+    {
+			InitList( pListHead );
+			PolVerts[nIndex] = pListHead;
+		}
+    else
+      return;	
+		
+	}
+}
+   
+
+void BuildFaceTable( int nSize )
+{
+        register int nIndex;
+        PLISTHEAD pListHead;
+        
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+                if ( pListHead )
+                {
+                        InitList( pListHead );
+                        PolFaces[nIndex] = pListHead;
+                }
+                else
+                        return; 
+                
+        }
+}
+   
+void BuildEdgeTable( int nSize )
+{
+        register int nIndex;
+        PLISTHEAD pListHead;
+
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+                if ( pListHead )
+                {
+                        InitList( pListHead );
+                        PolEdges[nIndex] = pListHead;
+                }
+                else
+                        return;
+        }
+}
+
+void Start_Face_Struct(int numfaces)
+{
+	if (InitFaceTable(numfaces))
+	{
+		BuildFaceTable(numfaces);
+	}
+}
+
+void Start_Edge_Struct(int numverts)
+{
+        if (InitEdgeTable(numverts))
+        {
+                BuildEdgeTable(numverts);
+        }
+}
+
+
diff --git a/Stripe_w/init.h b/Stripe_w/init.h
new file mode 100644
index 000000000..fe9a05fd7
--- /dev/null
+++ b/Stripe_w/init.h
@@ -0,0 +1,30 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: init.h
+-----------------------------------------------------------------------*/
+
+void init_vert_norms(int num_vert);
+void init_vert_texture(int num_vert);
+BOOL InitVertTable( int nSize );
+BOOL InitFaceTable( int nSize );
+BOOL InitEdgeTable( int nSize );
+void InitStripTable(  );
+void Init_Table_SGI();
+void BuildVertTable( int nSize );
+void BuildFaceTable( int nSize );
+void BuildEdgeTable( int nSize );
+void Start_Face_Struct(int numfaces);
+void Start_Edge_Struct(int numverts);
+
+
+
+
+
+
diff --git a/Stripe_w/local.c b/Stripe_w/local.c
new file mode 100644
index 000000000..3f3e69da1
--- /dev/null
+++ b/Stripe_w/local.c
@@ -0,0 +1,119 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: local.c
+     This file contains the code that initializes the data structures for
+     the local algorithm, and starts the local algorithm going.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "polverts.h"
+#include "local.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "common.h"
+#include "outputex.h"
+#include "util.h"
+#include "init.h"
+
+void Find_StripsEx(FILE *output, FILE *strip,int *ties, int tie, 
+		   int triangulate, int swaps, int *next_id)
+{
+	/*	This routine will peel off the strips from the model */
+
+	ListHead *pListHead;
+	P_ADJACENCIES temp = NULL;
+	register int max,bucket=0;
+	BOOL whole_flag = TRUE;
+     int dummy = 0;
+	
+	/* Set the last known input edge to be null */
+  Last_Edge(&dummy,&dummy,&dummy,1);
+    
+  /* Search for lowest adjacency polygon and output strips */
+	while (whole_flag)
+	{
+		bucket = -1;
+		/* Search for polygons in increasing number of adjacencies */
+		while (bucket < 59)
+		{
+			bucket++;
+			pListHead = array[bucket];
+			max = NumOnList(pListHead);
+			if (max > 0)
+			{
+				temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0);
+				if (temp == NULL)
+				{
+					printf("Error in the buckets%d %d %d\n",bucket,max,0);
+					exit(0);
+				}
+				Polygon_OutputEx(temp,temp->face_id,bucket,pListHead,
+	       				       output,strip,ties,tie,triangulate,swaps,next_id,1);
+				/* Try to extend backwards, if the starting polygon in the
+           strip had 2 or more adjacencies to begin with
+        */
+        if (bucket >= 2)
+          Extend_BackwardsEx(temp->face_id,output,strip,ties,tie,triangulate,swaps,next_id);
+        break;  
+			}
+		}
+		/*	Went through the whole structure, it is empty and we are done.
+		*/
+		if ((bucket == 59) && (max == 0))
+			whole_flag = FALSE;
+        
+    /*  We just finished a strip, send dummy data to signal the end
+        of the strip so that we can output it.
+    */
+    else
+    {
+      Output_TriEx(-1,-2,-3,output,-1,-10,1);
+      Last_Edge(&dummy,&dummy,&dummy,1);
+    }
+  }
+}
+
+
+void SGI_Strip(int num_verts,int num_faces,FILE *output,
+			   int ties,int triangulate)
+               
+{
+	FILE *strip;
+  int next_id = -1,t=0;
+
+  strip = fopen("output.d","w");
+  /* We are going to output and find triangle strips
+   	 according the the method that SGI uses, ie always
+		 choosing as the next triangle in our strip the triangle
+		 that has the least number of adjacencies. We do not have
+		 all triangles and will be triangulating on the fly those
+		 polygons that have more than 3 sides.
+	*/
+
+	/*	Build a table that has all the polygons sorted by the number
+		of polygons adjacent to it.
+	*/
+	/*	Initialize it */
+	Init_Table_SGI();
+	/*	Build it */
+	Build_SGI_Table(num_verts,num_faces);
+
+	/*    We will have a structure to hold all the strips, until
+        outputted.
+  */
+  InitStripTable();
+  /* Now we have the structure built to find the polygons according
+		 to the number of adjacencies. Now use the SGI Method to find
+		 strips according to the adjacencies
+	*/
+  Find_StripsEx(output,strip,&t,ties,triangulate,ON,&next_id);
+}
diff --git a/Stripe_w/local.h b/Stripe_w/local.h
new file mode 100644
index 000000000..df5256f6a
--- /dev/null
+++ b/Stripe_w/local.h
@@ -0,0 +1,20 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:local.h
+-----------------------------------------------------------------------*/
+
+void Local_Polygon_Output();
+void Local_Output_Tri();
+int Different();
+void Local_Non_Blind_Triangulate();
+void Local_Blind_Triangulate();
+void Local_Triangulate_Polygon();
+void SGI_Strip(int num_verts,int num_faces,FILE *output,
+	       int ties,int triangulate);
diff --git a/Stripe_w/newpolve.c b/Stripe_w/newpolve.c
new file mode 100644
index 000000000..6267bbc42
--- /dev/null
+++ b/Stripe_w/newpolve.c
@@ -0,0 +1,1659 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: newpolve.c
+     This routine contains the bulk of the code that will find the
+     patches of quads in the data model
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "extend.h"
+#include "output.h"
+#include "triangulate.h"
+#include "common.h"
+#include "util.h"
+#include "global.h"        
+#include "init.h"
+#include "add.h"
+
+ListHead **PolVerts;
+ListHead **PolFaces;
+ListHead **PolEdges;
+int length;
+BOOL resetting = FALSE;
+int     ids[STRIP_MAX];
+int 	added_quad = 0;
+BOOL reversed = FALSE;
+int patch = 0;
+extern int *vn;
+extern int *vt;
+
+int Calculate_Walks(int lastvert,int y, PF_FACES temp2)
+{
+	/* Find the length of the walk */
+	
+	int previous_edge1, previous_edge2;
+	register int nextvert,numverts,counter,walk=0;
+	BOOL flag;
+	F_EDGES *node;
+     ListHead *pListHead;
+     static int seen = 0;
+     
+	/* Find the edge that we are currently on */
+	if (y != 3)
+	{
+		previous_edge1 = *(temp2->pPolygon +y);
+		previous_edge2 = *(temp2->pPolygon + y + 1);
+	}
+	else
+	{
+		previous_edge1 = *(temp2->pPolygon +y);
+		previous_edge2 = *(temp2->pPolygon);
+	}
+
+	temp2->seen = seen;
+     counter = y;
+
+     /*Find the adjacent face to this edge */
+	node = *(temp2->VertandId+y);			
+	if (node->edge[2] != lastvert)
+        nextvert = node->edge[2];
+     else
+        nextvert = node->edge[1];
+					
+	/* Keep walking in this direction until we cannot do so */
+	while ((nextvert != lastvert) && (nextvert != -1))
+	{
+		walk++;
+		pListHead = PolFaces[nextvert];
+		temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		numverts = temp2->nPolSize;
+		if ((numverts != 4) || (temp2->seen == seen))
+		{
+			walk--;
+			nextvert = -1;
+		}
+		else
+		{
+			temp2->seen = seen;
+               /* Find edge that is not adjacent to the previous one */
+			counter = 0;
+			flag = TRUE;
+			while ((counter < 3) && (flag))
+			{
+				if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+					(*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+					((*(temp2->pPolygon+counter) == previous_edge2) || 
+					(*(temp2->pPolygon+counter+1) == previous_edge1)) )
+					counter++;		
+				else
+					flag = FALSE;	
+			}
+	     	/* Get the IDs of the next edge */
+		     if (counter < 3)
+		     {
+			     previous_edge1 = *(temp2->pPolygon + counter);
+			     previous_edge2 = *(temp2->pPolygon + counter + 1);
+		     }
+		     else
+		     {
+                    previous_edge1 = *(temp2->pPolygon + counter);
+                    previous_edge2 = *(temp2->pPolygon);
+		     }
+	
+		     node = *(temp2->VertandId + counter);
+		     if (node->edge[1] == nextvert)
+			     nextvert = node->edge[2];
+		     else
+			     nextvert = node->edge[1];
+		}
+	}
+     seen++;
+	return walk;
+}
+
+
+BOOL Check_Right(int last_seen,PF_FACES temp2,int y,int face_id)
+{
+	/* Check when we last saw the face to the right of the current
+	   one. We want to have seen it just before we started this strip
+	*/
+
+	F_EDGES *node;
+	ListHead *pListHead;
+	register int nextvert,oldy;
+	PF_FACES t;
+	
+     oldy = y;
+	if (y != 3)
+		y = y+1;
+	else
+		y = 0;
+	node = *(temp2->VertandId + y);
+	if (face_id == node->edge[1])
+		nextvert = node->edge[2];
+	else
+		nextvert = node->edge[1];
+	
+     if (nextvert == -1)
+          return FALSE;
+     
+     pListHead = PolFaces[nextvert];
+	t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+	if (t->seen != (last_seen - 1))
+	{
+		 /* maybe because of the numbering, we are not
+		    on the right orientation, so we have to check the
+		    opposite one to be sure 
+           */
+		if (oldy != 0)
+			y = oldy-1;
+		else
+			y = 3;
+		node = *(temp2->VertandId + y);
+		if (face_id == node->edge[1])
+			nextvert = node->edge[2];
+		else
+			nextvert = node->edge[1];
+		if (nextvert == -1)
+               return FALSE;
+          pListHead = PolFaces[nextvert];
+		t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		if (t->seen != (last_seen - 1))
+		 	return FALSE;
+	}
+	return TRUE;
+}
+
+
+int Update_and_Test(PF_FACES temp2,int y,BOOL first,int distance,int lastvert, int val)
+{
+	     
+        static int last_seen = 17;
+        int previous_edge1, previous_edge2;
+        register int original_distance,nextvert,numverts,counter;
+        BOOL flag;
+        F_EDGES *node;
+        ListHead *pListHead;
+                                                        
+        original_distance = distance;
+        /* Find the edge that we are currently on */
+        if (y != 3)
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon + y + 1);
+        }
+        else
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon);
+        }
+
+        temp2->seen = val;
+        temp2->seen2 = val;
+		
+        node = *(temp2->VertandId+y);                   
+        if (lastvert != node->edge[2])
+			nextvert = node->edge[2];
+	   else
+			nextvert = node->edge[1];
+                                        
+        /* Keep walking in this direction until we cannot do so  or
+		we go to distance */
+        while ((distance > 0)  && (nextvert != lastvert) && (nextvert != -1))
+        {
+                distance--;
+			           
+                pListHead = PolFaces[nextvert];
+                temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+                temp2->seen = val;
+				
+                if (temp2->seen2 == val)
+                {
+                     last_seen++;
+                     return (original_distance - distance);
+                }
+                
+                temp2->seen2 = val;
+                
+                numverts = temp2->nPolSize;
+                                
+	     	 if (numverts != 4)
+          	     nextvert = -1;
+		
+                else if ((!first) && (!(Check_Right(last_seen,temp2,y,nextvert))))
+                {
+                    last_seen++;
+                    return (original_distance - distance);
+                }
+		      else
+                {
+                        /* Find edge that is not adjacent to the previous one */
+                        counter = 0;
+                        flag = TRUE;
+                        while ((counter < 3) && (flag))
+                        {
+                                if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                        ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                        counter++;
+                                else
+                                        flag = FALSE;
+                        }
+                        /* Get the IDs of the next edge */
+                        if (counter < 3)
+                        {
+                              previous_edge1 = *(temp2->pPolygon + counter);
+                              previous_edge2 = *(temp2->pPolygon + counter + 1);
+                        }
+                        else
+                        {
+                              previous_edge1 = *(temp2->pPolygon + counter);
+                              previous_edge2 = *(temp2->pPolygon);
+                        }
+                        if      ( ((*(temp2->walked+counter) == -1) && 
+                                (*(temp2->walked+counter+2) == -1)))
+                        {
+                                printf("There is an error in the walks!\n");
+                                printf("1Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter+2));
+                                exit(0);
+                        }
+                        else
+                        {
+                                if      ((*(temp2->walked+counter) == -1) && 
+                                        (*(temp2->walked+counter-2) ==  -1))
+                                {
+                                        printf("There is an error in the walks!\n");
+                                        printf("2Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter-2));
+                                        exit(0);
+                                }
+                        }
+                        node = *(temp2->VertandId + counter);
+                        y = counter;
+		              if (node->edge[1] == nextvert)
+                              nextvert = node->edge[2];
+                        else
+                              nextvert = node->edge[1];
+             }
+    }
+	
+    last_seen++;
+
+    if  (distance != 0)  
+    {
+		if (((nextvert == -1) || (nextvert == lastvert)) && (distance != 1))
+			return (original_distance - distance);
+    }
+    return original_distance;
+}
+
+
+int Test_Adj(PF_FACES temp2,int x,int north,int distance,int lastvert, int value)
+{
+	/* if first time, then just update the last seen field */
+	if (x==1)
+		return(Update_and_Test(temp2,north,TRUE,distance,lastvert,value));
+	/* else we have to check if we are adjacent to the last strip */
+	else
+		return(Update_and_Test(temp2,north,FALSE,distance,lastvert,value));
+}
+  
+void Get_Band_Walk(PF_FACES temp2,int face_id,int *dir1,int *dir2, 
+					int orientation,int cutoff_length)
+{
+	int previous_edge1, previous_edge2;
+	F_EDGES *node;
+	ListHead *pListHead;
+	register int walk = 0, nextvert,numverts,counter;
+	BOOL flag;
+	
+	/*	Get the largest band that will include this face, starting
+		from orientation. Save the values of the largest band
+		(either north and south together, or east and west together)
+		in the direction variables.
+	*/
+	/* Find the edge that we are currently on */
+     if (orientation != 3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation);
+                previous_edge2 = *(temp2->pPolygon + orientation + 1);
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+		
+     if (orientation == 0)
+     {
+			 if (*dir1 > *(temp2->walked + 1))
+				*dir1 = *(temp2->walked + 1);
+			 if (*dir2 > *(temp2->walked + 3))
+				*dir2 = *(temp2->walked + 3);
+	}
+	else if (orientation == 3)
+	{
+			if (*dir1 > *(temp2->walked + orientation - 3))
+			     *dir1 = *(temp2->walked + orientation - 3) ;
+			if (*dir2 > *(temp2->walked + orientation -1 ))
+				*dir2 = *(temp2->walked + orientation - 1);
+	}
+	else
+	{
+			if (*dir1 > *(temp2->walked + orientation - 1))
+				*dir1 = *(temp2->walked + orientation -1) ;
+			if (*dir2 > *(temp2->walked+ orientation + 1))
+				*dir2 = *(temp2->walked + orientation + 1);
+	}
+        
+     /*	if we know already that we can't extend the
+        	band from this face, we do not need to do the walk
+     */
+     if ((*dir1 != 0) && (*dir2 != 0))
+     {
+		/* Find the adjacent face to this edge */
+        	node = *(temp2->VertandId+orientation);                   
+        	if (face_id == node->edge[1])
+			nextvert = node->edge[2];
+        	else 
+			nextvert = node->edge[1];
+	}
+     else
+        	nextvert = -1; /* leave w/o walking */                                
+	
+	/* Keep walking in this direction until we cannot do so */
+     while ((nextvert != face_id) && (nextvert != -1))
+     {
+            walk++;
+            pListHead = PolFaces[nextvert];
+            temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+            numverts = temp2->nPolSize;
+            if ((numverts != 4)	|| (walk > cutoff_length))
+                   nextvert = -1;
+            else
+            {
+	  		  /* Find edge that is not adjacent to the previous one */
+                 counter = 0;
+                 flag = TRUE;
+                 while ((counter < 3) && (flag))
+                 {
+                           if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                     counter++;
+                           else
+                                flag = FALSE;
+                 }
+                 /* Get the IDs of the next edge */
+                 if (counter < 3)
+                 {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon + counter + 1);
+                 }
+                 else
+                 {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon);
+                 }
+                
+			  /* 	find out how far we can extend in the 2 directions
+					along this new face in the walk
+			  */
+			  if (counter == 0)
+			  {
+					if (*dir1 > *(temp2->walked + 1))
+						*dir1 = *(temp2->walked + 1);
+					if (*dir2 > *(temp2->walked + 3))
+						*dir2 = *(temp2->walked + 3);
+			  }
+			  else if (counter == 3)
+			  {
+					if (*dir1 > *(temp2->walked + counter - 3))
+						*dir1 = *(temp2->walked + counter - 3) ;
+					if (*dir2 > *(temp2->walked + counter -1 ))
+						*dir2 = *(temp2->walked + counter -1);
+			  }
+			  else
+			  {
+					if (*dir1 > *(temp2->walked + counter - 1))
+						*dir1 = *(temp2->walked + counter -1) ;
+					if (*dir2 > *(temp2->walked + counter + 1))
+						*dir2 = *(temp2->walked + counter + 1);
+			  }
+        
+        	      /*	if we know already that we can't extend the
+        	     	band from this face, we do not need to do the walk
+        	      */
+	        	 if ((*dir1 == 0) || (*dir2 == 0))
+                	nextvert = -1;
+                if (nextvert != -1)
+                {
+                	node = *(temp2->VertandId + counter);
+                	if (node->edge[1] == nextvert)
+                        nextvert = node->edge[2];
+                	else
+                        nextvert = node->edge[1];
+                }
+
+           }
+        }
+}
+
+
+
+
+int Find_Max(PF_FACES temp2,int lastvert,int north,int left,
+			int *lastminup,int *lastminleft)
+{
+	int temp,walk,counter,minup,x,band_value;
+	int previous_edge1, previous_edge2;
+	F_EDGES	*node;
+	ListHead *pListHead;
+	BOOL flag;	
+	static int last_seen = 0;
+	register int smallest_so_far,nextvert,max=-1;
+	        
+     *lastminup = MAX_BAND;
+	*lastminleft = 1;
+
+     if (left == 3)
+	{
+          previous_edge1 = *(temp2->pPolygon + left);
+          previous_edge2 = *(temp2->pPolygon);
+	}
+                
+	else
+	{
+          previous_edge1 = *(temp2->pPolygon + left + 1);
+          previous_edge2 = *(temp2->pPolygon + left);
+	}
+
+	temp2->seen = last_seen;
+     walk = *(temp2->walked + left);
+
+     for (x=1;x<=(walk+1); x++)
+	{
+		/*   test to see if we have a true band
+		     that is, are they adjacent to each other
+		*/
+        
+         minup = *(temp2->walked + north) + 1;
+
+	    /*	if we are at the very first face, then we do not
+	    	     have to check the adjacent faces going up
+	    	     and our north distance is the distance of this face's
+			north direction. 
+	    */
+         if (x == 1) 
+	    {
+			*lastminup = minup;
+			minup = Test_Adj(temp2,x,north,*lastminup,lastvert,last_seen);
+			*lastminup = minup;
+               smallest_so_far = minup;	
+         }
+		
+	
+	    /* find the largest band that we can have */
+	    if (minup < (*lastminup))
+	    {
+			/*	see if we really can go up all the way 
+				temp should by less than our equal to minup
+				if it is less, then one of the faces was not
+				adjacent to those next to it and the band height
+				will be smaller
+			*/
+			temp = Test_Adj(temp2,x,north,minup,lastvert,last_seen);
+			if (temp > minup)
+			{
+				printf("There is an error in the test adj\n");
+				exit(0);
+			}
+			minup = temp;
+			band_value = x * minup;
+			if (minup < smallest_so_far)
+			{
+				if (band_value > max)
+               	{
+					smallest_so_far = minup;
+					*lastminup = minup;
+					*lastminleft = x;
+                         max = band_value;
+                    }
+				else
+					smallest_so_far = minup;
+			}
+			else
+			{
+				band_value = x * smallest_so_far;
+     	          if (band_value > max)
+                    {
+                	     *lastminup = smallest_so_far;
+                         *lastminleft = x;
+                         max = band_value;
+                    }
+			}
+		}
+		else
+		{
+			if (x != 1)
+               {
+                    temp = Test_Adj(temp2,x,north,smallest_so_far,lastvert,last_seen);
+			     if (temp > smallest_so_far)
+			     {
+				    printf("There is an error in the test adj\n");
+				    exit(0);
+			     }
+			    smallest_so_far = temp;
+               }
+               band_value = x * smallest_so_far; 
+			if (band_value > max)
+			{
+				*lastminup = smallest_so_far;
+				*lastminleft = x;
+				max = band_value;
+			}
+		}
+		if ( x != (walk + 1))
+		{
+			node = *(temp2->VertandId+left);
+			if (lastvert == node->edge[1])
+				nextvert = node->edge[2];
+			else
+				nextvert = node->edge[1];
+
+               lastvert = nextvert;
+               
+               if (nextvert == -1)
+                    return max;
+               
+               pListHead = PolFaces[nextvert];
+			temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
+			
+               /* if we have visited this face before, then there is an error */
+               if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
+				(*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
+				|| (temp2->nPolSize !=4) || (temp2->seen == last_seen))
+			{
+
+                    if (lastvert == node->edge[1])
+                         nextvert = node->edge[2];
+                    else
+                         nextvert = node->edge[1];
+                    if (nextvert == -1)
+                         return max;
+                    lastvert = nextvert;
+                    /*   Last attempt to get the face ... */
+                    pListHead = PolFaces[nextvert];
+     			temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
+                    if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
+				     (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
+				     || (temp2->nPolSize !=4) || (temp2->seen == last_seen))
+                         return max;    /*   The polygon was not saved with the edge, not
+                                             enough room. We will get the walk when we come
+                                             to that polygon later.
+                                        */
+			}
+			/*else
+			{*/
+				counter = 0;
+				flag = TRUE;
+				temp2->seen = last_seen;
+
+                    while ((counter < 3) && (flag))
+			     {
+
+                         if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                        ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                        counter++;
+				     else
+                                        flag = FALSE;
+                    }
+               /*}*/
+		
+               /* Get the IDs of the next edge */
+               left = counter;
+		     north = left+1;
+               if (left ==3)
+			     north = 0;	
+		     if (counter < 3)
+               {
+                        previous_edge1 = *(temp2->pPolygon + counter + 1);
+                        previous_edge2 = *(temp2->pPolygon + counter);
+               }
+               else
+               {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon);
+               }
+
+          } 
+
+}
+last_seen++;
+return max;
+}
+
+void Mark_Face(PF_FACES temp2, int color1, int color2,
+				int color3, FILE *output_file, BOOL end, int *edge1, int *edge2, 
+                    int *face_id, int norms, int texture)
+{
+     static int last_quad[4];
+     int x,y,z=0;
+     int saved[2];
+     static int output1, output2,last_id;
+     BOOL cptexture = FALSE;
+
+     /*   Are we done with the patch? If so return the last edge that
+          we will come out on, and that will be the edge that we will
+          start to extend upon.
+     */
+
+     if (end)
+     {
+          *edge1 = output1;
+          *edge2 = output2;
+          *face_id = last_id;
+          return;
+     }
+
+     cptexture = texture;
+     last_id = *face_id;
+	*(temp2->walked) = -1;
+	*(temp2->walked+1) = -1;
+	*(temp2->walked+2) = -1;
+	*(temp2->walked+3) = -1;
+	added_quad++;
+	temp2->nPolSize = 1;
+
+     if (patch == 0)
+     {
+          /*   At the first quad in the strip -- save it */
+          last_quad[0] = *(temp2->pPolygon);
+          last_quad[1] = *(temp2->pPolygon+1);
+          last_quad[2] = *(temp2->pPolygon+2);
+          last_quad[3] = *(temp2->pPolygon+3);
+          patch++;
+     }
+     else
+     {
+          /*   Now we have a triangle to output, find the edge in common */
+          for (x=0; x < 4 ;x++)
+          {
+              for (y=0; y< 4; y++)
+              {
+                   if (last_quad[x] == *(temp2->pPolygon+y))
+                   {
+                        saved[z++] = last_quad[x];               
+                        if (z > 2)
+                        {
+                             /*    This means that there was a non convex or
+                                   an overlapping polygon
+                             */
+                             z--;
+                             break;
+                        }
+                   }                             
+              }
+          }
+          
+          if (z != 2)
+          {
+               printf("Z is not 2 %d \n",patch);
+               printf("4 %d %d %d %d %d %d %d\n",*(temp2->pPolygon),
+				*(temp2->pPolygon+1),*(temp2->pPolygon+2),*(temp2->pPolygon+3),
+				color1,color2,color3);
+               printf("%d %d %d %d\n",last_quad[0],last_quad[1],last_quad[2],last_quad[3]);
+               exit(1);
+          }
+          
+          if (patch == 1)
+          {
+               /*   First one to output, there was no output edge */
+               patch++;
+               x = Adjacent(saved[0],saved[1],last_quad,4);
+               y = Adjacent(saved[1],saved[0],last_quad,4);
+               
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) || ((vt[saved[1]])==0)))
+                    cptexture = FALSE;
+
+               if ((!norms) && (!cptexture))
+               {
+                    fprintf(output_file,"\nt %d %d %d ",x+1,y+1,saved[1]+1);
+                    fprintf(output_file,"%d ",saved[0]+1);
+               }
+               else if ((norms) && (!cptexture))
+               {
+                    fprintf(output_file,"\nt %d//%d %d//%d %d//%d ",x+1,vn[x] +1,
+                                                                    y+1,vn[y] +1,
+                                                                    saved[1]+1,vn[saved[1]]+1);
+                    fprintf(output_file,"%d//%d ",saved[0]+1,vn[saved[0]]+1);
+               }
+               else if ((cptexture) && (!norms))
+               {
+                    fprintf(output_file,"\nt %d/%d %d/%d %d/%d ",x+1,vt[x] +1,
+                                                                    y+1,vt[y] +1,
+                                                                    saved[1]+1,vt[saved[1]]+1);
+                    fprintf(output_file,"%d//%d ",saved[0]+1,vt[saved[0]]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"\nt %d/%d/%d %d/%d/%d %d/%d/%d ",x+1,vt[x]+1,vn[x] +1,
+                                                                    y+1,vt[y]+1,vn[y] +1,
+                                                                    saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1);
+                    fprintf(output_file,"%d/%d/%d ",saved[0]+1,vt[saved[0]]+1,vn[saved[0]]+1);
+               }
+
+               x = Adjacent(saved[0],saved[1],temp2->pPolygon,4);
+               y = Adjacent(saved[1],saved[0],temp2->pPolygon,4);
+
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( (vt[x] == 0) || (vt[y]==0)))
+               {
+                    if (cptexture)
+                         fprintf(output_file,"\nq ");
+                    cptexture = FALSE;
+               }
+               if ((!norms) && (!cptexture))
+               {
+                    fprintf(output_file,"%d ",x+1);
+                    fprintf(output_file,"%d ",y+1);
+               }
+               else if ((norms) && (!cptexture))
+               {
+                    fprintf(output_file,"%d//%d ",x+1,vn[x]+1);
+                    fprintf(output_file,"%d//%d ",y+1,vn[y]+1);
+               }
+               else if ((cptexture) && (!norms))
+               {
+                    fprintf(output_file,"%d/%d ",x+1,vt[x]+1);
+                    fprintf(output_file,"%d/%d ",y+1,vt[y]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"%d/%d/%d ",x+1,vt[x]+1,vn[x]+1);
+                    fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1);
+               }
+
+               output1 = x;
+               output2 = y;
+          }
+          
+          else 
+          {
+               x = Adjacent(output2,output1,temp2->pPolygon,4);
+               y = Adjacent(output1,output2,temp2->pPolygon,4);
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) ))
+                    texture = FALSE;
+
+               if ((!norms) && (!texture))
+               {
+                    fprintf(output_file,"\nq %d ",x+1);
+                    fprintf(output_file,"%d ",y+1);
+               }
+               else if ((norms) && (!texture))
+               {
+                    fprintf(output_file,"\nq %d//%d ",x+1,vn[x]+1);
+                    fprintf(output_file,"%d//%d ",y+1,vn[y]+1);
+               }
+               else if ((texture) && (!norms))
+               {
+                    fprintf(output_file,"\nq %d/%d ",x+1,vt[x]+1);
+                    fprintf(output_file,"%d/%d ",y+1,vt[y]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"\nq %d/%d/%d ",x+1,vt[x]+1,vn[x]+1);
+                    fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1);
+               }
+               
+               output1 = x;
+               output2 = y;
+          }
+          
+          last_quad[0] = *(temp2->pPolygon);
+          last_quad[1] = *(temp2->pPolygon+1);
+          last_quad[2] = *(temp2->pPolygon+2);
+          last_quad[3] = *(temp2->pPolygon+3);
+     }
+}
+
+void Fast_Reset(int x)
+{
+	register int y,numverts;
+	register int front_walk, back_walk;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+     pListHead = PolFaces[x];
+	temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+	numverts = temp->nPolSize;
+     
+     front_walk = 0; 
+     back_walk = 0;          
+     resetting = TRUE;
+          
+     /* we are doing this only for quads */
+	if (numverts == 4)
+	{
+			/* 	for each face not seen yet, do North and South together
+				and East and West together
+			*/
+			for (y=0;y<2;y++)
+			{
+				/* Check if the opposite sides were seen already */
+	     		/* Find walk for the first edge */
+				front_walk = Calculate_Walks(x,y,temp);
+				/* Find walk in the opposite direction */
+				back_walk = Calculate_Walks(x,y+2,temp);
+				/* 	Now put into the data structure the numbers that
+		          	we have found
+				*/
+                    Assign_Walk(x,temp,front_walk,y,back_walk);
+				Assign_Walk(x,temp,back_walk,y+2,front_walk);
+			}
+	}
+     resetting = FALSE;
+}
+
+
+void Reset_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation,
+		int last_left,FILE *output_file,int color1,int color2,int color3,
+		BOOL start)
+{
+	int previous_edge1,previous_edge2;
+	F_EDGES *node;
+	ListHead *pListHead;
+	int f,t,nextvert,counter;
+     BOOL flag;
+
+ 
+     /*   Reset walks on faces, since we just found a patch */
+     if (orientation !=3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation+1);
+                previous_edge2 = *(temp2->pPolygon + orientation );
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+
+	/* only if we are going left, otherwise there will be -1 there */
+	/*Find the adjacent face to this edge */
+        
+     for (t = 0; t <=3 ; t++)
+     {
+             node = *(temp2->VertandId+t);
+              
+             if (face_id == node->edge[1])
+                f = node->edge[2];
+             else
+               f = node->edge[1];
+       
+             if (f != -1)
+                  Fast_Reset(f);
+        }
+
+        node = *(temp2->VertandId+orientation);
+        if (face_id == node->edge[1])
+             nextvert = node->edge[2];
+        else
+             nextvert = node->edge[1];
+
+	while ((last_left--) > 1)
+	{
+               
+          if (start)
+               Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE);		
+        
+          face_id = nextvert;
+          pListHead = PolFaces[nextvert];                
+          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+          if ((temp2->nPolSize != 4) && (temp2->nPolSize != 1))
+          {
+             /*   There is more than 2 polygons on the edge, and we could have
+                  gotten the wrong one
+             */
+             if (nextvert != node->edge[1])
+                  nextvert = node->edge[1];
+             else
+                  nextvert = node->edge[2];
+             pListHead = PolFaces[nextvert];          
+             temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+             node = *(temp2->VertandId+orientation);
+          }
+
+                
+         if (!start)
+         {
+             for (t = 0; t <=3 ; t++)
+             {
+                    node = *(temp2->VertandId+t);
+              
+                    if (face_id == node->edge[1])
+                         f = node->edge[2];
+                    else
+                         f = node->edge[1];
+          
+                    if (f != -1)
+                         Fast_Reset(f);
+             }
+        }
+
+
+        counter = 0;
+	   flag = TRUE;
+	   while ((counter < 3) && (flag))
+        {
+             if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                  ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                   counter++;
+             else
+                  flag = FALSE;
+        }
+
+        /* Get the IDs of the next edge */
+        if (counter < 3)
+        {
+             previous_edge1 = *(temp2->pPolygon + counter+1);
+             previous_edge2 = *(temp2->pPolygon + counter);
+        }
+        else
+        {
+             previous_edge1 = *(temp2->pPolygon + counter);
+             previous_edge2 = *(temp2->pPolygon);
+        }
+        orientation = counter;
+
+        node = *(temp2->VertandId + counter);
+	   if (node->edge[1] == nextvert)
+			nextvert = node->edge[2];
+	   else
+			nextvert = node->edge[1];
+
+        if (!reversed)
+        {
+               if (counter != 3)
+			     north = counter +1;
+		     else
+			     north = 0;
+        }
+        else
+        {
+               if (counter != 0)
+                    north = counter -1;
+               else
+                    north = 3;
+    
+        }
+     }
+if (start)
+	Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE);
+else if (nextvert != -1)       
+     Fast_Reset(nextvert);
+
+}
+
+
+int Peel_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation,
+		int last_left,FILE *output_file,int color1,int color2,int color3,
+		BOOL start, int *swaps_added, int norms, int texture)
+{
+	int end1,end2,last_id,s=0,walk = 0;
+	int previous_edge1,previous_edge2;
+	static int last_seen = 1000;
+	F_EDGES *node;
+	ListHead *pListHead;
+	int nextvert,numverts,counter,dummy,tris=0;
+     BOOL flag;
+
+     /*   Peel the patch from the model.
+          We will try and extend off the end of each strip in the patch. We will return the
+          number of triangles completed by this extension only, and the number of swaps
+          in the extension only.
+     */	
+     patch = 0;
+     
+     if (orientation !=3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation+1);
+                previous_edge2 = *(temp2->pPolygon + orientation );
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+
+
+     walk = *(temp2->walked + orientation);
+	
+     /* only if we are going left, otherwise there will be -1 there */
+	if ((start) && ((walk+1) < last_left))
+	{
+		printf("There is an error in the left %d %d\n",walk,last_left);
+		exit(0);
+	}
+	
+     /* Find the adjacent face to this edge */
+     node = *(temp2->VertandId+orientation);
+     if (face_id == node->edge[1])
+          nextvert = node->edge[2];
+     else
+          nextvert = node->edge[1];
+	temp2->seen = last_seen;
+
+
+	while ((last_left--) > 1)
+	{
+ 		if (start)
+             tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,
+                              color1,color2,color3,FALSE,swaps_added,norms,texture);		    
+          else
+             Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);
+		
+
+          pListHead = PolFaces[nextvert];      
+          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+          numverts = temp2->nPolSize;
+	
+          if ((numverts != 4) || (temp2->seen == last_seen) 
+			||  (nextvert == -1))
+          {
+  	
+             /*   There is more than 2 polygons on the edge, and we could have
+                  gotten the wrong one
+             */
+             if (nextvert != node->edge[1])
+                  nextvert = node->edge[1];
+             else
+                  nextvert = node->edge[2];
+             pListHead = PolFaces[nextvert];
+             temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+             numverts = temp2->nPolSize;
+             if ((numverts != 4) || (temp2->seen == last_seen) )
+             {
+                  printf("Peel 2 %d\n",numverts);
+                  exit(1);
+             }
+        }
+
+        face_id = nextvert;
+        temp2->seen = last_seen;
+                
+        counter = 0;
+        flag = TRUE;
+	   while ((counter < 3) && (flag))
+        {
+             if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                  ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                   counter++;
+             else
+                  flag = FALSE;
+        }
+        /* Get the IDs of the next edge */
+        if (counter < 3)
+        {
+             previous_edge1 = *(temp2->pPolygon + counter+1);
+             previous_edge2 = *(temp2->pPolygon + counter);
+        }
+        else
+        {
+             previous_edge1 = *(temp2->pPolygon + counter);
+             previous_edge2 = *(temp2->pPolygon);
+        }
+        orientation = counter;
+		              
+	   node = *(temp2->VertandId + counter);
+	   if (node->edge[1] == nextvert)
+			nextvert = node->edge[2];
+	   else
+			nextvert = node->edge[1];
+
+	   if (!reversed)
+        {
+               if (counter != 3)
+			     north = counter +1;
+		     else
+			     north = 0;
+        }
+        else
+        {
+               if (counter != 0)
+                    north = counter -1;
+               else
+                    north = 3;
+        }
+}
+
+if (start)
+	tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,
+                        color1,color2,color3,FALSE,swaps_added,norms,texture);	
+else
+     Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);/* do the last face */
+
+last_seen++;
+
+/*    Get the edge that we came out on the last strip of the patch */
+Mark_Face(NULL,0,0,0,output_file,TRUE,&end1,&end2,&last_id,norms,texture);
+tris += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+*swaps_added = *swaps_added + s;
+return tris;
+}
+
+
+
+void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, 
+                int *cost, int *tri, int norms, int *vert_norms, int texture, int *vert_texture)
+{
+
+	register int x,y,max1,max2,numverts,face_id,flag,maximum = 25;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+	int color1 = 0, color2 = 100, color3 = 255;
+	int larger,smaller;
+	int north_length1,last_north,left_length1,last_left,north_length2,left_length2;
+  int total_tri = 0, total_swaps = 0,last_id;
+  int end1, end2,s=0;
+  register int cutoff = 20;
+    
+  /* Code that will find the patches. "Cutoff" will be
+     the cutoff of the area of the patches that we will be allowing. After
+     we reach this cutoff length, then we will run the local algorithm on the
+     remaining faces.
+  */
+
+	/* For each faces that is left find the largest possible band that we can
+		 have with the remaining faces. Note that we will only be finding patches
+     consisting of quads.
+	*/
+
+  vn = vert_norms;
+  vt = vert_texture;
+  y=1;
+  *bands = 0;
+
+  while ((maximum >= cutoff))
+  {
+	  y++;
+    maximum = -1;
+	  for (x=0; x<numfaces; x++)
+	  { 
+      /*   Used to produce the triangle strips */
+ 
+      /* for each face, get the face */
+		  pListHead = PolFaces[x];
+		  temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		  numverts = temp->nPolSize;
+		  
+      /* we are doing this only for quads */
+		  if (numverts == 4)
+		  {
+			  /* We want a face that is has not been used yet,
+           since we know that that face must be part of
+				   a band. Then we will find the largest band that
+				   the face may be contained in
+			  */
+			  
+        /*  Doing the north and the left */
+			  if ((*(temp->walked) != -1) && (*(temp->walked+3) != -1))
+				  max1 = Find_Max(temp,x,0,3,&north_length1,&left_length1);
+			  if ((*(temp->walked+1) != -1) && (*(temp->walked+2) != -1))
+				  max2 = Find_Max(temp,x,2,1,&north_length2,&left_length2);
+			  if ((max1 != (north_length1 * left_length1)) ||
+			      (max2 != (north_length2 * left_length2)))
+			  {
+				  printf("Max1 %d, %d %d	Max2 %d, %d %d\n",max1,north_length1,left_length1,max2,north_length2,left_length2);
+				  exit(0);
+			  }
+                
+                    
+        if ((max1 > max2) && (max1 > maximum))
+			  {
+          maximum = max1;
+          face_id = x;
+          flag = 1; 
+          last_north = north_length1;
+          last_left = left_length1;
+          /* so we know we saved max1 */
+			  }
+			  else if ((max2 > maximum) )
+			  {
+          maximum = max2;
+          face_id = x;
+          flag = 2; 
+          last_north = north_length2;
+          last_left = left_length2;
+          /* so we know we saved max2 */
+        }
+      }
+    }
+    if ((maximum < cutoff) && (*bands == 0))
+      return;
+    pListHead = PolFaces[face_id];
+    temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);	
+    /*   There are no patches that we found in this pass */
+    if (maximum == -1)
+      break;
+    printf("The maximum is  face %d area %d: lengths %d %d\n",face_id,maximum,last_north,last_left);
+    if (maximum == 16)
+      printf("Fran");
+
+    if (last_north > last_left)
+    {
+      larger = last_north;
+      smaller = last_left;
+    }
+    else
+    {
+      larger = last_left;
+      smaller = last_north;
+    }
+
+    length = larger;
+
+    if (flag == 1)
+    {
+	    if (last_north > last_left) /*     go north sequentially */
+      {
+        total_tri += Peel_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+        Reset_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE);
+        total_swaps += s;
+      }
+      else
+      {
+        reversed = TRUE;
+        total_tri += Peel_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+        Reset_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE);
+        reversed = FALSE;
+        total_swaps += s;
+      }
+
+
+      /*    Get the edge that we came out on the last strip of the patch */
+      Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
+      total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+      total_swaps += s;
+
+    }
+    else
+    {
+       if (last_north > last_left)
+       {
+            total_tri += Peel_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture); 
+            Reset_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE); 
+            total_swaps += s;
+       }
+       else
+       {
+            reversed = TRUE;
+            total_tri += Peel_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+            Reset_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE);
+            reversed = FALSE;
+            total_swaps += s;
+       }
+
+       /*    Get the edge that we came out on on the patch */
+      Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
+      total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+      total_swaps += s;
+    }
+
+    /* Now compute the cost of transmitting this band, is equal to 
+       going across the larger portion sequentially,
+       and swapping 3 times per other dimension
+    */
+
+    total_tri += (maximum * 2);
+    *bands = *bands + smaller;
+  }
+
+  printf("We transmitted %d triangles,using %d swaps and %d strips\n",total_tri,total_swaps, *bands);
+  printf("COST %d\n",total_tri + total_swaps + *bands + *bands);
+
+  *cost = total_tri + total_swaps + *bands + *bands;
+  *tri = total_tri;
+  added_quad = added_quad * 4;
+  *swaps = total_swaps;
+}
+
+ 
+void Save_Rest(int *numfaces)
+{
+    /*  Put the polygons that are left into a data structure so that we can run the
+        stripping code on it.
+    */
+    register int x,y=0,numverts;
+    ListHead *pListHead;
+    PF_FACES temp=NULL;
+
+    for (x=0; x<*numfaces; x++)
+    { 
+			/* for each face, get the face */
+			pListHead = PolFaces[x];
+			temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+			numverts = temp->nPolSize;
+               /*  If we did not do the face before add it to data structure with new 
+                   face id number
+               */
+               if (numverts != 1)
+               {
+                   CopyFace(temp->pPolygon,numverts,y+1,temp->pNorms);
+                   y++;
+               }
+               /*   Used it, so remove it */
+               else
+                    RemoveList(pListHead,(PLISTINFO) temp);
+
+    }
+    *numfaces = y;
+}
+
+void Assign_Walk(int lastvert,PF_FACES temp2, int front_walk,int y,
+				int back_walk)
+{
+/*      Go back and do the walk again, but this time save the lengths inside
+        the data structure.
+        y was the starting edge number for the front_walk length
+        back_walk is the length of the walk along the opposite edge
+ */
+        int previous_edge1, previous_edge2;
+        register int walk = 0,nextvert,numverts,counter;
+        BOOL flag;
+        F_EDGES *node;
+        ListHead *pListHead;
+        static int seen = 0;
+        static BOOL first = TRUE;         
+        BOOL wrap = FALSE, set = FALSE;
+             
+        /*     In the "Fast_Reset" resetting will be true */
+        if ((resetting) && (first))
+        {
+             seen = 0;
+             first = FALSE;
+        }
+
+        seen++;
+        /*     Had a band who could be a cycle  */
+        if (front_walk == back_walk)
+             wrap = TRUE;
+             
+        /* Find the edge that we are currently on */
+        if (y != 3)
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon + y + 1);
+        }
+        else
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon);
+        }
+
+        /* Assign the lengths */
+	   if (y < 2) 
+	   {
+                *(temp2->walked+y) = front_walk--;
+         		 *(temp2->walked+y+2) = back_walk++;
+    	   }
+	   else
+	   {				
+               *(temp2->walked+y) = front_walk--;
+              	*(temp2->walked+y-2) = back_walk++;
+  	   }
+
+	   /*Find the adjacent face to this edge */
+        node = *(temp2->VertandId+y);                   
+
+        if (node->edge[2] != lastvert)
+          nextvert = node->edge[2];
+        else
+          nextvert = node->edge[1];
+                                       
+        temp2->seen3 = seen;
+        
+        /* Keep walking in this direction until we cannot do so */
+        while ((nextvert != lastvert) && (nextvert != -1) && (front_walk >= 0))
+        {
+		     walk++;
+               pListHead = PolFaces[nextvert];
+               
+               temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+               numverts = temp2->nPolSize;
+               if ((numverts != 4))
+               {
+                    nextvert = -1;
+                    /* Don't include this face in the walk */
+                    walk--;
+               }
+               else
+               {
+                    /* Find edge that is not adjacent to the previous one */
+                    counter = 0;
+                    flag = TRUE;
+                    while ((counter < 3) && (flag))
+                    {
+                         if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                               (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                              ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                               (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                              counter++;
+                         else
+                              flag = FALSE;
+                    }
+                    /* Get the IDs of the next edge */
+                    if (counter < 3)
+                    {
+                         previous_edge1 = *(temp2->pPolygon + counter);
+                         previous_edge2 = *(temp2->pPolygon + counter + 1);
+                    }
+                    else
+                    {
+                         previous_edge1 = *(temp2->pPolygon + counter);
+                         previous_edge2 = *(temp2->pPolygon);
+                    }
+               
+
+		          /*      Put in the walk lengths */
+		          if (counter < 2)
+		          {
+                        if (((*(temp2->walked + counter) >= 0)
+			          || (*(temp2->walked +counter + 2) >= 0)))
+			          {
+				          if ((resetting == FALSE) && ((temp2->seen3) != (seen-1)))
+				          {
+					          /*   If there are more than 2 polygons adjacent
+                                        to an edge then we can be trying to assign more than
+                                        once. We will save the smaller one
+                                   */
+                                   temp2->seen3 = seen;
+                                   if ( (*(temp2->walked+counter) <= front_walk) &&
+                                        (*(temp2->walked+counter+2) <= back_walk) )
+                                        return;
+                                   if (*(temp2->walked+counter) > front_walk)
+                                       *(temp2->walked+counter) = front_walk--;
+                                   else
+                                        front_walk--;
+                                   if (*(temp2->walked+counter+2) > back_walk)
+                                       *(temp2->walked+counter+2) = back_walk++;
+                                   else
+                                        back_walk++;
+				          }
+				          else if (resetting == FALSE)
+				          {
+					          /* if there was a cycle then all lengths are the same */
+					          walk--;
+					          back_walk--;
+					          front_walk++;
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                              else if (((temp2->seen3 == (seen-1))
+                                   && (wrap) && (walk == 1)) || (set))
+                              {
+					          /* if there was a cycle then all lengths are the same */
+					          set = TRUE;
+                                   walk--;
+					          back_walk--;
+					          front_walk++;
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                              else
+                              {
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                        } /* if was > 0 */	
+                        else
+                        {
+                             temp2->seen3 = seen;
+                             *(temp2->walked+counter) = front_walk--;
+                             *(temp2->walked+counter+2) = back_walk++;
+                        }
+                    }
+		
+               else
+               {
+                    if (((*(temp2->walked + counter) >= 0 )
+                        || (*(temp2->walked +counter - 2) >= 0)) )
+                    {
+                         if ((temp2->seen3 != (seen-1))  && (resetting == FALSE))
+                         {
+                              /*   If there are more than 2 polygons adjacent
+                                   to an edge then we can be trying to assign more than
+                                   once. We will save the smaller one
+                              */
+                              temp2->seen3 = seen;
+                              if ( (*(temp2->walked+counter) <= front_walk) &&
+                                   (*(temp2->walked+counter-2) <= back_walk) )
+                                   return;
+                              if (*(temp2->walked+counter) > front_walk)
+                                   *(temp2->walked+counter) = front_walk--;
+                              else
+                                   front_walk--;
+                              if (*(temp2->walked+counter-2) > back_walk)
+                                   *(temp2->walked+counter-2) = back_walk++;
+                              else
+                                   back_walk++;
+                        	}
+				     else if (resetting == FALSE)
+	     			{
+     					walk--;
+		     			back_walk--;
+			     		front_walk++;
+	                         temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+                         else if (((temp2->seen3 == (seen-1)) && (walk == 1) && (wrap))
+                              || (set))
+                         {
+					     /* if there was a cycle then all lengths are the same */
+					     set = TRUE;
+                              walk--;
+					     back_walk--;
+					     front_walk++;
+                              temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+                         else
+                         {
+                              temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+     			}
+                    else
+                    {
+                         temp2->seen3 = seen;
+                         *(temp2->walked+counter) = front_walk--;
+                         *(temp2->walked+counter-2) = back_walk++;
+                    }
+		                
+  		     } 
+		     if (nextvert != -1)
+		     {
+			     node = *(temp2->VertandId + counter);
+                	if (node->edge[1] == nextvert)
+                        	nextvert = node->edge[2];
+                	else
+                        	nextvert = node->edge[1];
+               }
+		
+     }
+}
+if ((EVEN(seen)) )
+     seen+=2;
+}
+
+void Save_Walks(int numfaces)
+{
+	int x,y,numverts;
+	int front_walk, back_walk;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	for (x=0; x<numfaces; x++)
+	{ 
+		/* for each face, get the face */
+		pListHead = PolFaces[x];
+		temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+		numverts = temp->nPolSize;
+		front_walk = 0; 
+          back_walk = 0;
+
+          /* we are finding patches only for quads */
+		if (numverts == 4)
+		{
+			/* 	for each face not seen yet, do North and South together
+				and East and West together
+			*/
+			for (y=0;y<2;y++)
+			{
+				/*   Check if the opposite sides were seen already from another
+                         starting face, if they were then there is no need to do the walk again
+                    */
+
+				if 	( ((*(temp->walked+y) == -1) &&
+					(*(temp->walked+y+2) == -1) ))
+				{
+					/* Find walk for the first edge */
+					front_walk = Calculate_Walks(x,y,temp);
+					/* Find walk in the opposite direction */
+					back_walk = Calculate_Walks(x,y+2,temp);
+					/* 	Now put into the data structure the numbers that
+						we have found
+					*/
+                         Assign_Walk(x,temp,front_walk,y,back_walk);
+					Assign_Walk(x,temp,back_walk,y+2,front_walk);
+	     		}
+			}
+		}
+	}
+}
+
+
diff --git a/Stripe_w/options.c b/Stripe_w/options.c
new file mode 100644
index 000000000..cbc9d4e15
--- /dev/null
+++ b/Stripe_w/options.c
@@ -0,0 +1,181 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: options.c
+     This file contains routines that are used to determine the options
+     that were specified by the user
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "options.h"
+#include "global.h"
+
+int power_10(int power)
+{
+	/*	Raise 10 to the power */
+	register int i,p;
+
+	p = 1;
+	for (i = 1; i <= power; ++i)
+		p = p * 10;
+	return p;
+}
+
+float power_negative(int power)
+{
+     /*   Raise 10 to the negative power */
+
+     register int i;
+     float p;
+     
+     p = (float)1;
+     for (i = 1; i<=power; i++)
+          p = p * (float).1;
+     return p;
+}
+
+float convert_array(int num[],int stack_size)
+{
+	/* Convert an array of characters to an integer */
+	
+	register int counter,c;
+	float temp =(float)0.0;
+
+	for (c=(stack_size-1), counter = 0; c>=0; c--, counter++)
+     {
+          if (num[c] == -1)
+          /*   We are at the decimal point, convert to decimal
+               less than 1
+          */
+          {
+               counter = -1;
+               temp = power_negative(stack_size - c - 1) * temp;
+          }
+          else 
+               temp += power_10(counter) * num[c];
+     }
+			
+	return(temp);
+}
+
+double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group)
+{
+     char c;
+     int count = 0;
+     int buffer[STRIP_MAX];
+     int next = 0;
+     /*    tie variable */
+     enum tie_options tie = SEQUENTIAL;
+     /*   triangulation variable */
+     enum triangulation_options triangulate = PARTIAL;
+     /*   normal difference variable (in degrees) */
+     float norm_difference = (float)360.0;
+     /*   file-type variable */
+     enum file_options file_type = ASCII;
+
+     /*      User has the wrong number of options */
+	if ((argc > 5) || (argc < 2))
+	{
+		printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] file_name\n");
+		exit(0);
+	}
+	
+     /* Interpret the options specified */
+	while (--argc > 0 && (*++argv)[0] == '-')
+     {
+          /*   At the next option that was specified */
+          next = 1;
+          while (c = *++argv[0])
+			switch (c)
+		{
+				case 'f': 
+					/*      Use the first polygon we see. */
+                         tie = FIRST;
+					break;
+				
+				case 'r':
+					/*      Randomly choose the next polygon */
+                         tie = RANDOM;
+					break;
+
+				case 'a':
+					/*      Alternate direction in choosing the next polygon */
+                         tie = ALTERNATE;
+					break;
+
+				case 'l':
+					/*      Use lookahead to choose the next polygon */
+                         tie = LOOK;
+					break;
+
+				case 'q':
+					/*  Try to reduce swaps */
+                         tie = SEQUENTIAL;
+					break;
+
+				case 'p':
+					/*      Use partial triangulation of polygons */
+                         triangulate = PARTIAL;
+					break;
+
+				case 'w':
+					/*      Use whole triangulation of polygons */
+                         triangulate = WHOLE;
+					break;
+
+                    case 'b':
+                         /*      Input file is in binary */
+                         file_type = BINARY;
+                         break;
+
+                    case 'g':
+                         /*   Strips will be grouped according to the groups in 
+                              the data file. We will have to restrict strips to be
+                              in the grouping of the data file.
+                         */
+                         *group = 1;
+  		    
+                         /*	Get each the value of the integer */
+                         /*	We have an integer */
+                    default:
+                         if ((c >= '0') && (c <= '9'))
+                         {
+                              /*   More than one normal difference specified, use the last one */
+                              if (next == 1)
+                              {
+                                   count = 0;
+                                   next = 0;
+                              }
+                              buffer[count++] = ATOI(c);
+                         }
+                              /*   At the decimal point */
+                         else if (c == '.')
+                         {
+                              /*   More than one normal difference specified, use the last one */
+                              if (next == 1)
+                              {
+                                   count = 0;
+                                   next = 0;
+                              }
+                              buffer[count++] = -1;
+                         }
+                         else 
+                              break;
+		}
+     }
+     /*   Convert the buffer of characters to a floating pt integer */
+     if (count != 0) 
+          norm_difference = convert_array(buffer,count);
+     *f = file_type;
+     *t = tie;
+     *tr = triangulate;
+     return norm_difference;
+}
diff --git a/Stripe_w/options.h b/Stripe_w/options.h
new file mode 100644
index 000000000..34c10bcc1
--- /dev/null
+++ b/Stripe_w/options.h
@@ -0,0 +1,17 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: options.h
+-----------------------------------------------------------------------*/
+
+double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group);
+enum file_options {ASCII,BINARY};
+enum tie_options {FIRST, RANDOM, ALTERNATE, LOOK, SEQUENTIAL};
+enum triangulation_options {PARTIAL,WHOLE};
+     
diff --git a/Stripe_w/output.c b/Stripe_w/output.c
new file mode 100644
index 000000000..16eb6abe6
--- /dev/null
+++ b/Stripe_w/output.c
@@ -0,0 +1,579 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: output.c
+     This file contains routines that are finding and outputting the
+     strips from the local algorithm
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "partial.h"
+#include "sturcts.h"
+#include "ties.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+#include "free.h"
+
+int *vn;
+int *vt;
+int norm;
+int text;
+
+int Finished(int *swap, FILE *output, BOOL global)
+{
+  /* We have finished all the triangles, now is time to output to
+     the data file. In the strips data structure, every three ids
+     is a triangle. Now we see whether we can swap, or make a new strip
+     or continue the strip, and output the data accordingly to the
+     data file. 
+  */
+  int num,x,vertex1,vertex2;
+  ListHead *pListHead;
+  int id[2],other1,other2,index = 0,a,b,c;
+  P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6;
+  BOOL cptexture;
+  *swap =0;
+   
+  cptexture = text;
+  pListHead = strips[0];
+  if (pListHead == NULL)
+    return 0;
+
+  num = NumOnList(pListHead);
+  // WILBUR
+  // printf ("There are %d triangles in the extend\n",num/3);
+
+  /* Go through the list triangle by triangle */
+	temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
+	temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
+	temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
+	
+  /* Next triangle for lookahead */
+  temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3);
+	  
+
+  /*    There is only one polygon in the strip */
+  if (temp4 == NULL)
+  {
+    /* Data might be mixed and we do not have textures for some of the vertices */
+    if ((text) &&  (vt[temp3->face_id] == 0))
+      cptexture = FALSE;
+    if ((norm) && (!cptexture))
+      fprintf(output,"%d//%d %d//%d %d//%d",temp3->face_id+1,vn[temp3->face_id]+1,
+                temp2->face_id+1,vn[temp2->face_id]+1,
+                temp1->face_id+1,vn[temp1->face_id]+1);
+    else if ((cptexture) && (!norm))
+      fprintf(output,"%d/%d %d/%d %d/%d",temp3->face_id+1,vt[temp3->face_id]+1,
+                temp2->face_id+1,vt[temp2->face_id]+1,
+                temp1->face_id+1,vt[temp1->face_id]+1);
+    else if ((cptexture)&& (norm))
+      fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d",temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1,
+                temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1,
+                temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1);
+    else 
+      fprintf(output,"%d %d %d",temp3->face_id+1,temp2->face_id+1,temp1->face_id+1);
+    Free_Strips();
+	  return 1;
+	}
+	  
+	/* We have a real strip */
+	temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4);
+	temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5);
+	  
+	if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL))
+	{
+	  printf("There is an error in the output of the triangles\n");
+	  exit(0);
+	}
+
+	/* Find the vertex in the first triangle that is not in the second */
+	vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id,temp4->face_id,temp5->face_id,temp6->face_id,&other1,&other2);
+	/* Find the vertex in the second triangle that is not in the first */
+	vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
+
+	/* Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle */
+  temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6);
+	temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7);
+	temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8);
+       
+  if (temp1 != NULL)
+    other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a);
+	   
+	id[index] = vertex1; index = !index;
+	id[index] = other1; index = !index;
+	id[index] = other2; index = !index;
+
+	a = temp4->face_id; 
+	b = temp5->face_id; 
+	c = temp6->face_id;
+
+  /* If we need to rearrange the first sequence because otherwise
+     there would have been a swap.
+  */
+
+  if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0))
+    cptexture = FALSE;
+  if ((norm) && (!cptexture))
+    fprintf(output,"%d//%d %d//%d %d//%d ",vertex1+1,vn[vertex1]+1,
+               other1+1,vn[other1]+1,other2+1,vn[other2]+1);
+  else if ((cptexture) && (!norm))
+    fprintf(output,"%d/%d %d/%d %d/%d ",vertex1+1,vt[vertex1]+1,
+               other1+1,vt[other1]+1,other2+1,vt[other2]+1);
+  else if ((cptexture) && (norm))
+    fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d ",vertex1+1,vt[vertex1]+1,vn[vertex1]+1,
+              other1+1,vt[other1]+1,vn[other1]+1,other2+1,vt[other2]+1,vn[other2]+1);
+  else {
+    fprintf(output,"%d %d %d ",vertex1+1,other1+1,other2+1);
+  }
+
+  // original line
+  // for (x = 6; x < num ; x = x+3)
+  // Wilbur modified line
+  for (x = 6; x < num ; x = x+3)
+	{
+    /* Get the next triangle */
+	  temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x);
+	  temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+1);
+	  temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+2);
+
+    /* Error checking */
+	  if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c)))
+	  {
+		  /* If we used partial we might have a break in the middle of a strip */
+		  fprintf(output,"\nt ");
+	    /* Find the vertex in the first triangle that is not in the second */
+	    vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
+	    /* Find the vertex in the second triangle that is not in the first */
+	    vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
+	   
+	    id[index] = vertex1; index = !index;
+	    id[index] = other1; index = !index;
+	    id[index] = other2; index = !index;
+	  }
+
+	  if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL))
+	  {
+		  printf("There is an error in the triangle list \n");
+		  exit(0);
+	  }
+         
+    if ((id[0] == id[1]) || (id[0] == vertex2))
+      continue;
+
+    if ( (member(id[index],temp1->face_id,temp2->face_id,temp3->face_id)) )
+    {
+      if ((text) && ( vt[id[index]]==0)) {
+        cptexture = FALSE;
+      }
+      if ((!norm) && (!cptexture)) {
+        fprintf(output,"%d ",id[index]+1);
+      } else if ((norm) && (!cptexture)) {
+        fprintf(output,"%d//%d ",id[index]+1,vn[id[index]]+1);
+      } else if ((!norm) && (cptexture)) {
+        fprintf(output,"%d/%d ",id[index]+1,vt[id[index]]+1);
+      } else {
+        fprintf(output,"%d/%d/%d ",id[index]+1,vt[id[index]]+1,vn[id[index]]+1);
+      }
+
+      index = !index;
+      *swap = *swap + 1;
+    }
+           
+    if ((text) && ( vt[vertex2]==0))
+      cptexture = FALSE;
+	  if ((!norm) && (!cptexture))
+      fprintf(output,"\nq %d ",vertex2+1);
+    else if ((norm) && (!cptexture))
+      fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1);
+    else if ((!norm) && (cptexture))
+      fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1);
+    else
+      fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
+
+    id[index] = vertex2; index = !index;
+
+	  /* Get the next vertex not in common */
+	  vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
+	  a = temp1->face_id;
+	  b = temp2->face_id;
+	  c = temp3->face_id;
+	}
+
+  /* Do the last vertex */
+  if ((!norm) && (!cptexture))
+    fprintf(output,"\nq %d ",vertex2+1);
+  else if ((norm) && (!cptexture))
+    fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1);
+  else if ((!norm) && (cptexture))
+    fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1);
+  else
+    fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
+
+  Free_Strips();
+  return (num/3);
+}
+
+
+
+
+
+void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, int color2, int color3,BOOL end)
+{
+     /*   We will save everything into a list, rather than output at once,
+	     as was done in the old routine. This way for future modifications
+	     we can change the strips later on if we want to.
+     */
+
+    int temp1,temp2,temp3;
+    
+    /*  Make sure we do not have an error */
+    /*    There are degeneracies in some of the files */
+	if ( (id1 == id2) || (id1 == id3) || (id2 == id3))
+	{
+		printf("Degenerate triangle %d %d %d\n",id1,id2,id3);
+		exit(0);
+	}
+     else
+     {
+          Last_Edge(&temp1,&temp2,&temp3,0);
+	     Add_Id_Strips(id1,end);
+	     Add_Id_Strips(id2,end);
+	     Add_Id_Strips(id3,end);
+	     Last_Edge(&id1,&id2,&id3,1);
+     }
+}
+
+
+int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket,
+					ListHead *pListHead, BOOL first, int *swaps,
+                         FILE *bands,int color1,int color2,int color3,BOOL global, BOOL end)
+{
+	ListHead *pListFace;
+	PF_FACES face;
+	P_ADJACENCIES pfNode;
+	int next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
+	P_ADJACENCIES lpListInfo; 
+     int ties=0;
+     
+     /* We have a polygon to output, the id is face id, and the number
+	   of adjacent polygons to it is bucket. This routine extends the patches from
+        either end to make longer triangle strips.
+	*/
+                
+                   
+     /*  Now get the edge */
+     Last_Edge(&e1,&e2,&e3,0);
+    
+     /*  Get the polygon with id face_id */
+	pListFace  = PolFaces[face_id];
+	face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     /*  We can't go any more */
+     if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global))) /* if global, then we are still doing patches */
+     {
+        /*     Remove it from the list so we do not have to waste
+               time visiting it in the future, or winding up in an infinite loop
+               if it is the first on that we are looking at for a possible strip
+        */
+        if (face->nPolSize == 1)
+             RemoveList(pListHead,(PLISTINFO) temp);
+        if (first)
+             return 0;
+        else
+             return (Finished(swaps,bands,global));
+    }
+
+    if (face->nPolSize == 3)
+    {
+		/*      It is already a triangle */
+		if (bucket == 0)
+		{
+			/*      It is not adjacent to anything so we do not have to
+	 			   worry about the order of the sides or updating adjacencies
+			*/
+			    
+	          next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
+		                              e1,e2,e3,&other1,&other2);  
+			face->nPolSize = 1;
+                       
+               /* If this is the first triangle in the strip */
+               if ((e2 == 0) && (e3 ==0))
+               {
+                    e2 = other1;
+                    e3 = other2;
+               }
+
+               Output_Tri(e2,e3,next_face_id,bands,color1,color2,color3,end);
+               RemoveList(pListHead,(PLISTINFO) temp);
+               return (Finished(swaps,bands,global));
+          }
+		
+        
+          /*  It is a triangle with adjacencies. This means that we
+		    have to:
+				1. Update the adjacencies in the list, because we are
+					using this polygon and it will be deleted.
+				2. Get the next polygon.
+		*/
+		else
+		{
+			/*   Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current triangle.
+			*/
+            
+               next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+               {
+                       Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
+                                  color2,color3,end);
+                       face->nPolSize = 1;
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       return (Finished(swaps,bands,global));
+               }
+		  
+		     /*      Find the other vertex to transmit in the triangle */
+		     e3 = Return_Other(face->pPolygon,e1,e2);
+	          Last_Edge(&other1,&other2,&other3,0);
+	    
+	          if ((other2 != 0) && (other3 != 0))
+	          {
+	              /*   See which vertex in the output edge is not in the input edge */
+	              if ((e1 != other2) && (e1 != other3))
+		            e3 = e1;
+	              else if ((e2 != other2) && (e2 != other3))
+		             e3 = e2;
+	              else
+	              {
+		            printf("There is an error in the tri with adj\n");
+		            exit(0);
+	              }
+
+	              /*   See which vertex of the input edge is not in the output edge */
+	              if ((other2 != e1) && (other2 != e2))
+	              {
+		            other1 = other2;
+		            other2 = other3;
+	              }
+	              else if ((other3 != e1) && (other3 != e2))
+		            other1 = other3;
+	              else
+	              {
+		            printf("There is an error in getting the tri with adj\n");
+		            exit(0);
+	              }
+		      
+	          }
+               else
+               {
+                  /*     We are the first triangle in the strip and the starting edge
+                         has not been set yet
+                  */
+                  /*  Maybe we deleted something in a patch and could not find an adj polygon */
+                  if (next_face_id == -1)
+                  {
+                       Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
+                                  color2,color3,end);
+                       face->nPolSize = 1;
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       return (Finished(swaps,bands,global));
+                  }
+
+                  other1 = e3;
+                  e3 = e2;
+                  other2 = e1;
+               }
+	   
+	          /*   At this point the adjacencies have been updated  and we
+				have the next polygon id 
+	          */
+
+               Output_Tri(other1,other2,e3,bands,color1,color2,color3,end);
+               face->nPolSize = 1;
+		     RemoveList(pListHead,(PLISTINFO) temp);
+	          
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+                    return (Finished(swaps,bands,global));
+        
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+		     {
+			     printf("We deleted the next face 4%d\n",next_face_id);
+			     exit(0);
+	          }
+
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				(int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+			{
+				printf("There is an error finding the next polygon3 %d\n",next_face_id);
+				exit(0);
+			}
+			return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
+					             pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
+
+		}
+	}
+
+	else
+	{
+		/*   It is not a triangle, we have to triangulate it .
+			Since it is not adjacent to anything we can triangulate it
+			blindly
+		*/
+		if (bucket == 0)
+		{
+		          /*   It is the first polygon in the strip, therefore there is no
+                         input edge to start with.
+                    */
+                    if ((e2 == 0) && (e3 ==0))
+                       Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
+			                          TRUE,1,color1,color2,color3);
+
+                    else
+                       Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
+			                          FALSE,1,color1,color2,color3);
+
+			     RemoveList(pListHead,(PLISTINFO) temp);
+			               
+                    /*      We will be at the beginning of the next strip. */
+                    face->nPolSize = 1;
+                    return (Finished(swaps,bands,global));
+		}
+
+
+		else
+		{
+			
+             
+               /*  WHOLE triangulation */
+	          /*  It is not a triangle and has adjacencies. 
+				This means that we have to:
+				1. Triangulate this polygon, not blindly because
+					we have an edge that we want to come out on, that
+					is the edge that is adjacent to a polygon with the
+					least number of adjacencies. Also we must come in
+					on the last seen edge.
+				2. Update the adjacencies in the list, because we are
+					using this polygon .
+				3. Get the next polygon.
+			*/
+			/*      Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current polygon.
+			*/
+				
+               next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
+	    
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+               {
+ 
+                    /*   If we are at the first polygon in the strip and there is no input
+                         edge, then begin is TRUE
+                    */
+                    if ((e2 == 0) && (e3 == 0))
+                         Blind_Triangulate(face->nPolSize,face->pPolygon,
+			                            bands,TRUE,1,color1,color2,color3);
+
+                    else
+                         Blind_Triangulate(face->nPolSize,face->pPolygon,
+			                            bands,FALSE,1,color1,color2,color3);
+
+		          RemoveList(pListHead,(PLISTINFO) temp);
+		              
+    	               /*      We will be at the beginning of the next strip. */
+                    face->nPolSize = 1;
+                    return (Finished(swaps,bands,global));
+               }
+
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+	          {
+			    printf("We deleted the next face 6 %d %d\n",next_face_id,face_id);
+			    exit(0);
+		     }
+			
+			Non_Blind_Triangulate(face->nPolSize,face->pPolygon, 
+				                 bands,next_face_id,face_id,1,color1,color2,color3);
+				     
+               RemoveList(pListHead,(PLISTINFO) temp);
+               face->nPolSize = 1;
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+					   (int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+		     {
+				printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
+				exit(0);
+			}
+			return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
+					             pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
+		}
+
+	}
+    Last_Edge(&e1,&e2,&e3,0);
+
+}       
+
+
+int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands,
+                int color1,int color2,int color3,int *vert_norm, int normals,
+                int *vert_texture, int texture)
+{
+    int dummy=0,next_bucket;
+    P_ADJACENCIES pfNode,lpListInfo;
+    ListHead *pListHead;
+
+    /*    Try to extend backwards off of the local strip that we just found */
+    
+    vn = vert_norm;
+    vt = vert_texture;
+    norm = normals;
+    text = texture;
+
+    *swaps = 0;
+    /*	Find the face that is adjacent to the edge and is not the
+		current face.
+    */
+    face_id = Find_Face(face_id, e1, e2,&next_bucket);
+    if (face_id == -1)
+          return 0;
+			
+    pListHead = array[next_bucket];
+    pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+    if ( pfNode )
+		pfNode->face_id = face_id;
+    lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+		       (int (*)(void *,void *)) (Compare)));
+    if (lpListInfo == NULL)
+    {
+		printf("There is an error finding the next polygon3 %d\n",face_id);
+		exit(0);
+    }
+    Last_Edge(&dummy,&e1,&e2,1);
+    
+    /*  Find a strip extending from the patch and return the cost */
+    return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps,bands,color1,color2,color3,TRUE,TRUE));
+}
+
+
diff --git a/Stripe_w/output.h b/Stripe_w/output.h
new file mode 100644
index 000000000..fd4b34c27
--- /dev/null
+++ b/Stripe_w/output.h
@@ -0,0 +1,34 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: output.h
+-----------------------------------------------------------------------*/
+
+
+#include "polverts.h"
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, 
+		int color2, int color3,BOOL end);
+void Sgi_Test();
+int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket,
+		   ListHead *pListHead, BOOL first, int *swaps,
+		   FILE *bands,int color1,int color2,int color3,
+		   BOOL global, BOOL end);
+void Last_Edge();
+void Extend_Backwards();
+int Finished(int *swap, FILE *output, BOOL global);
+int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands,
+                int color1,int color2,int color3,int *vert_norm, int normals,
+                int *vert_texture, int texture);
+void Fast_Reset();
+
+
diff --git a/Stripe_w/outputex.c b/Stripe_w/outputex.c
new file mode 100644
index 000000000..10bfb741f
--- /dev/null
+++ b/Stripe_w/outputex.c
@@ -0,0 +1,514 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: outputex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "outputex.h"
+#include "triangulatex.h"
+#include "polverts.h"
+#include "ties.h"
+#include "partial.h"
+#include "sturctsex.h"
+#include "options.h"
+#include "output.h"
+#include "common.h"
+#include "util.h"
+
+
+void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, int flag,
+		int where)
+{
+   /* We will save everything into a list, rather than output at once,
+      as was done in the old routine. This way for future modifications
+      we can change the strips later on if we want to.
+   */
+
+  int swap,temp1,temp2,temp3;
+  static int total=0;
+  static int tri=0;
+  static int strips = 0;
+  static int cost = 0;
+
+  if (flag == -20)
+  {
+    cost = cost + where+total+tri+strips+strips;
+    printf("We will need to send %d vertices to the renderer\n",cost);
+    total = 0;
+    tri = 0;
+    strips = 0;
+    return ;
+  }
+
+
+  if (flag == -10) /* We are finished, now is time to output the triangle list */
+  {
+    fprintf(output,"\nt ");
+    tri = tri + Finished(&swap,output,FALSE);
+    total = total + swap;
+    strips++;
+    /*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/
+  }
+   
+  else
+  {
+    Last_Edge(&temp1,&temp2,&temp3,0);
+    Add_Id_Strips(id1,where);
+    Add_Id_Strips(id2,where);
+    Add_Id_Strips(id3,where);
+    Last_Edge(&id1,&id2,&id3,1);
+  }
+}
+
+		
+
+
+void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, 
+			int tie, int triangulate, int swaps, int *next_id)
+{
+    /*  We just made a strip, now we are going to see if we can extend
+	   backwards from the starting face, which had 2 or more adjacencies
+	   to start with.
+    */
+    int bucket,next_face,num,x,y,z,c,max,f;
+    ListHead *pListFace;
+    PF_FACES face;
+    P_ADJACENCIES temp;
+
+    /*  Get the first triangle that we have saved the the strip data 
+	   structure, so we can see if there are any polygons adjacent
+	   to this edge or a neighboring one
+    */
+    First_Edge(&x,&y,&z); 
+    
+    pListFace  = PolFaces[face_id];
+    face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+    num = face->nPolSize;
+
+    /*  Go through the edges to see if there is an adjacency
+	   with a vertex in common to the first triangle that was
+	   outputted in the strip. (maybe edge was deleted....)
+    */
+    for (c=0; c<num ; c++)
+    {
+	   
+	if ( (c != (num-1)) && 
+	     (( (*(face->pPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) ||
+		(*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x)))
+	{
+	    /*  Input edge is still there see if there is an adjacency */
+	    next_face = Find_Face(face_id, x, y, &bucket);
+	    if (next_face == -1)
+		/*  Could not find a face adjacent to the edge */
+	     	break;
+	    pListFace = array[bucket];
+	    max = NumOnList(pListFace);
+	    for (f=0;;f++)
+	    {
+			temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);	
+		     if (temp->face_id == next_face)
+		     {
+		          Last_Edge(&z,&y,&x,1);
+		          Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
+        			  		       output,strip,ties,tie,triangulate,swaps,next_id,0);
+		          return;
+		     }
+
+			if (temp == NULL)
+			{
+					printf("Error in the new buckets%d %d %d\n",bucket,max,0);
+					exit(0);
+			}
+	    }
+
+	}
+	else if ( (c == (num -1)) &&
+	   ( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) ||
+	      (*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x)))
+	{
+	     next_face = Find_Face(face_id,x,y,&bucket);
+	     if (next_face == -1)
+		/*  Could not find a face adjacent to the edge */
+		     break;
+		pListFace = array[bucket];
+		max = NumOnList(pListFace);
+		for (f=0;;f++)
+		{
+			temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);
+		     if (temp->face_id == next_face)
+		     {
+		          Last_Edge(&z,&y,&x,1);
+		          Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
+				   	            output,strip,ties,tie,triangulate,swaps,next_id,0);
+		          return;
+		     }
+
+			if (temp == NULL)
+			{
+					printf("Error in the new buckets%d %d %d\n",bucket,max,0);
+					exit(0);
+			}
+	    }
+	}
+    
+    }
+
+}
+
+void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
+		      ListHead *pListHead, FILE *output, FILE *strips,
+		      int *ties, int tie, int triangulate, int swaps,
+		      int *next_id, int where)
+{
+	ListHead *pListFace;
+	PF_FACES face;
+	P_ADJACENCIES pfNode;
+	static BOOL begin = TRUE;
+	int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
+	P_ADJACENCIES lpListInfo; 
+
+	/*      We have a polygon to output, the id is face id, and the number
+		   of adjacent polygons to it is bucket.
+	*/
+
+     Last_Edge(&e1,&e2,&e3,0);
+    
+     /*  Get the polygon with id face_id */
+	pListFace  = PolFaces[face_id];
+	face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     if (face->nPolSize == 3)
+	{
+		/*      It is already a triangle */
+		if (bucket == 0)
+		{
+			/*      It is not adjacent to anything so we do not have to
+				   worry about the order of the sides or updating adjacencies
+			*/
+			    
+	          Last_Edge(&e1,&e2,&e3,0);
+	          next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
+		                              e1,e2,e3,&other1,&other2);
+	          /*  No input edge, at the start */
+	          if ((e2 ==0) && (e3 == 0))
+	          {
+		          e2 = other1;
+		          e3 = other2;
+	          }
+	    
+			Output_TriEx(e2,e3,next_face_id,strips,-1,begin,where);
+			RemoveList(pListHead,(PLISTINFO) temp);
+			/*      We will be at the beginning of the next strip. */
+			begin = TRUE;
+		}
+		/*      It is a triangle with adjacencies. This means that we
+			   have to:
+				1. Update the adjacencies in the list, because we are
+					using this polygon and it will be deleted.
+				2. Get the next polygon.
+		*/
+		else
+		{
+			/*   Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current triangle.
+			*/
+            
+               next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+			old_face = next_face_id;
+				        
+              /*  Break the tie,  if there was one */
+		    if (tie != FIRST)
+				old_face = Get_Next_Face(tie,face_id,triangulate);
+
+              if (next_face_id == -1)
+              {
+                    Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+	     		    triangulate,swaps,next_id,where);
+                    return;
+              }
+
+
+	        /*  We are using a different face */
+	        if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON))
+             {
+		        next_face_id = old_face;
+		        /*  Get the new output edge, since e1 and e2 are for the
+		            original next face that we got.
+		        */
+                  e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id,face->nPolSize,0,0);
+	        }
+			
+		   /*      Find the other vertex to transmit in the triangle */
+		   e3 = Return_Other(face->pPolygon,e1,e2);
+	        Last_Edge(&other1,&other2,&other3,0);
+	    
+	        if ((other1 != 0) && (other2 != 0))
+	        {
+	               /*   See which vertex in the output edge is not in the input edge */
+	               if ((e1 != other2) && (e1 != other3))
+		               e3 = e1;
+	               else if ((e2 != other2) && (e2 != other3))
+		               e3 = e2;
+	               /* can happen with > 2 polys on an edge  but won't form a good strip so stop
+                       the strip here
+                    */
+                    else
+	               {
+                         Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+         		                           triangulate,swaps,next_id,where);
+                         return;
+	       }
+
+	       /*   See which vertex of the input edge is not in the output edge */
+	       if ((other2 != e1) && (other2 != e2))
+	       {
+		          other1 = other2;
+		          other2 = other3;
+	       }
+	       else if ((other3 != e1) && (other3 != e2))
+		          other1 = other3;
+	       else
+	       {
+                 /* Degenerate triangle just return*/
+               Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
+			RemoveList(pListHead,(PLISTINFO) temp);
+			begin = FALSE;
+               return;
+	       }
+		      
+	   }
+	   
+	   /*   There was not an input edge, we are the first triangle in a strip */
+	   else 
+	   {
+	       /*   Find the correct order to transmit the triangle, what is
+		       the output edge that we want ?
+	       */
+	       other1 = e3;
+	       e3 = e2;
+	       other2 = e1;
+	   }
+	   
+	   /*   At this point the adjacencies have been updated  and we
+		   have the next polygon id 
+	   */
+        Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
+  	   RemoveList(pListHead,(PLISTINFO) temp);
+	   begin = FALSE;
+
+	   if (Done(next_face_id,59,&next_bucket) == NULL)
+		return;
+
+        pListHead = array[next_bucket];
+	   pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+	   if ( pfNode )
+	  	pfNode->face_id = next_face_id;
+	   lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				 (int (*)(void *,void *)) (Compare)));
+	   if (lpListInfo == NULL)
+	   {
+				printf("There is an error finding the next polygon3 %d\n",next_face_id);
+				exit(0);
+	   }
+	   Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+					pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+
+	}
+}
+
+	else
+	{
+		/*      It is not a triangle, we have to triangulate it .
+			   Since it is not adjacent to anything we can triangulate it
+			   blindly
+		*/
+		if (bucket == 0)
+		{
+			/*  Check to see if there is not an input edge */
+	          Last_Edge(&other1,&other2,&other3,0);
+	          if ((other1 == 0) && (other2 ==0))
+		          Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						          output,TRUE,where);
+	          else
+		          Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
+			                         output,FALSE,where);
+
+			RemoveList(pListHead,(PLISTINFO) temp);
+			/*      We will be at the beginning of the next strip. */
+			begin = TRUE;
+		}
+
+		 /*  If we have specified PARTIAL triangulation then
+			we will go to special routines that will break the
+			polygon and update the data structure. Else everything
+			below will simply triangulate the whole polygon 
+		*/
+		else if (triangulate == PARTIAL)
+		{
+	    
+	          /*  Return the face_id of the next polygon we will be using,
+			*/
+			next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties);
+
+		
+			/* Don't do it partially, because we can go inside and get
+		        less adjacencies, for a quad we can do the whole thing.
+	          */
+	          if ((face_id == next_face_id) && (face->nPolSize == 4)  && (swaps == ON))
+	          {
+                    next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+		          if (next_face_id == -1)
+		          {
+		               /*  There is no sequential face to go to, end the strip */
+		               Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+					                 triangulate,swaps,next_id,where);
+		               return;
+		          }
+               
+                    /* Break the tie,  if there was one */
+		          if (tie != FIRST)
+			          next_face_id = Get_Next_Face(tie,face_id,triangulate);
+		          Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						              output,next_face_id,face_id,where);
+			     RemoveList(pListHead,(PLISTINFO) temp);
+	          }
+	   
+	          /*   Was not a quad but we still do not want to do it partially for
+		          now, since we want to only do one triangle at a time
+	          */
+	          else if ((face_id == next_face_id) && (swaps == ON))
+	               Inside_Polygon(face->nPolSize,face->pPolygon,strips,output,
+		                         next_face_id,face_id,next_id,pListHead,temp,where);
+
+	          else
+	          {
+					 if ((tie != FIRST) && (swaps == ON))
+						 next_face_id = Get_Next_Face(tie,face_id,triangulate);
+					 Partial_Triangulate(face->nPolSize,face->pPolygon,strips,
+						                output,next_face_id,face_id,next_id,pListHead,temp,where);
+					/*    Check the next bucket again ,maybe it changed 
+						 We calculated one less, but that might not be the case
+					*/
+               }
+
+			if (Done(next_face_id,59,&next_bucket) == NULL)
+			{
+     			/*  Check to see if there is not an input edge */
+	               Last_Edge(&other1,&other2,&other3,0);
+	               if ((other1 == 0) && (other2 ==0))
+		               Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						               output,TRUE,where);
+	               else
+		               Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
+			                              output,FALSE,where);
+                    
+                    if (Done(face_id,59,&bucket) != NULL)
+                    {
+                         pListHead = array[bucket];
+			          pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			          if ( pfNode )
+				          pfNode->face_id = face_id;
+			          lpListInfo = (P_ADJACENCIES) (SearchList(array[bucket], pfNode,
+				                  (int (*)(void *,void *)) (Compare)));
+			          RemoveList(pListHead,(PLISTINFO)lpListInfo);
+                    }
+                    begin = TRUE;
+				return;
+			}
+			
+			begin = FALSE;
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				        (int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+			{
+				printf("There is an error finding the next polygon1 %d %d\n",next_face_id,next_bucket);
+				exit(0);
+			}
+			Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+				            pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+		}
+
+          
+		else
+		{
+			/*  WHOLE triangulation */
+	          /*  It is not a triangle and has adjacencies. 
+				This means that we have to:
+				1. TriangulateEx this polygon, not blindly because
+					we have an edge that we want to come out on, that
+					is the edge that is adjacent to a polygon with the
+					least number of adjacencies. Also we must come in
+					on the last seen edge.
+				2. Update the adjacencies in the list, because we are
+					using this polygon .
+				3. Get the next polygon.
+			*/
+			/*   Return the face_id of the next polygon we will be using,
+				while updating the adjacency list by decrementing the
+				adjacencies of everything adjacent to the current polygon.
+			*/
+				
+               next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+               {
+                    Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+			                      triangulate,swaps,next_id,where);
+                    /*    Because maybe there was more than 2 polygons on the edge */
+                    return;
+		     }
+
+		     /*      Break the tie,  if there was one */
+			else if (tie != FIRST)
+				next_face_id = Get_Next_Face(tie,face_id,triangulate);
+				
+			Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+						         output,next_face_id,face_id,where);
+			RemoveList(pListHead,(PLISTINFO) temp);
+			begin = FALSE;
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = next_face_id;
+			lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+					   (int (*)(void *,void *)) (Compare)));
+			if (lpListInfo == NULL)
+		     {
+					printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
+					exit(0);
+               }
+			Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+					       pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+		}
+
+	}
+    Last_Edge(&e1,&e2,&e3,0);
+
+}       
+
+
+
+	
+
+
+
+
diff --git a/Stripe_w/outputex.h b/Stripe_w/outputex.h
new file mode 100644
index 000000000..f59f7e75c
--- /dev/null
+++ b/Stripe_w/outputex.h
@@ -0,0 +1,31 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: outputex.h
+-----------------------------------------------------------------------*/
+
+
+#include "polverts.h"
+
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, 
+		  int flag, int where);
+void Sgi_Test();
+void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
+		      ListHead *pListHead, FILE *output, FILE *strips,
+		      int *ties, int tie, int triangulate, int swaps,
+		      int *next_id, int where);
+void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, 
+			int tie, int triangulate, int swaps,int *next_id);
+void FinishedEx();
+
+
diff --git a/Stripe_w/partial.c b/Stripe_w/partial.c
new file mode 100644
index 000000000..847b40501
--- /dev/null
+++ b/Stripe_w/partial.c
@@ -0,0 +1,668 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: partial.c
+     This file contains routines that are used partial triangulation of polygons
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "outputex.h"
+#include "polyvertsex.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "polverts.h"
+#include "common.h"
+#include "util.h"
+
+void P_Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,FILE *fp,int reversed,int face_id,
+					  int *next_id,ListHead *pListHead, 
+					  P_ADJACENCIES temp,
+                      int where)
+{
+    int vertex4,vertex5,dummy=60;
+	
+    /*	This routine will nonblindly triangulate a quad, meaning
+		that there is a definite input and a definite output
+		edge that we must adhere to. Reversed will tell the orientation
+		of the input edge. (Reversed is -1 is we do not have an input
+		edge, in other words we are at the beginning of a strip.)
+		Out_edge* is the output edge, and in_edge* is the input edge. 
+		Index are the edges of the polygon
+		and size is the size of the polygon. Begin is whether we are
+		at the start of a new strip.
+		Note that we will not necessarily triangulate the whole quad;
+		maybe we will do half and leave the other half (a triangle)
+		for later.
+	*/
+	
+
+    /*	If we do not have an input edge, then we can make our input
+		edge whatever we like, therefore it will be easier to come
+		out on the output edge.	In this case the whole quad is done.
+	*/
+	if (reversed == -1)
+	{
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+		Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+		RemoveList(pListHead,(PLISTINFO) temp);
+		return;
+	}
+	
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off, but cannot use the whole quad?
+	*/
+
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge. Save the other half for later.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+          Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,
+				face_id,&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		/*	Put the new face in the proper bucket of adjacencies 
+			There are 2 edges that need to be checked for the triangle
+			that was just outputted. For the output edge we definitely
+			will be decreasing the adjacency, but we must check for the
+			input edge.
+		*/
+
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge1,out_edge2,vertex4);
+		return;									  
+	}
+	else if (in_edge1 == out_edge1)
+	{
+		/*	We want to output the first triangle (whose output
+			edge is not the one that we want.
+			We have to find the vertex that we need, which is
+			the other vertex which we do not have.
+		*/						
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+		Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge2,out_edge2,vertex4);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge2,out_edge1,vertex4);
+          return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+		/*	Now we have a triangle used, and a triangle that is
+			left for later.
+		*/
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+		dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
+		
+		/*	Update the face data structure, by deleting the old
+			face and putting in the triangle as the new face 
+		*/
+		New_Face(face_id,in_edge1,out_edge1,vertex4);
+		return;
+	}
+
+	/*	The final case is where we want to come out the opposite
+		edge.
+	*/
+	else
+	{
+        if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
+                    ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
+		{
+			/*	We need to know the orientation of the input
+				edge, so we know which way to put the diagonal.
+                And also the output edge, so that we triangulate
+                correctly. Does not need partial.
+             */
+			Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
+			dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+			RemoveList(pListHead,(PLISTINFO) temp);
+		}
+		else
+		{
+			/*      Input and output orientation was reversed, so diagonal will
+					be reversed from above.
+			*/
+			Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
+			dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+			RemoveList(pListHead,(PLISTINFO) temp);
+		}
+		return;
+	}
+}
+
+void P_Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1,
+						   int in_edge2,int size,
+						  int *index,FILE *output,FILE *fp,
+						  int reversed,int face_id,int *next_id,
+						  ListHead *pListHead, P_ADJACENCIES temp2,
+                          int where)
+{
+	/*	We have a polygon greater than 4 sides, which we wish
+		to partially triangulate
+	*/
+	int next_bucket,vertex4,dummy = 60;
+	int *temp;
+	P_ADJACENCIES pfNode;
+
+		
+    /*	Since we are calling this recursively, we have to check whether		
+		we are down to the case of the quad.
+	*/
+	if (size == 4)
+	{
+		P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+							index,output,fp,reversed,face_id,next_id,
+							pListHead,temp2,where);
+		return;
+	}
+	
+	/*	We do not have a specified input edge, and therefore we
+		can make it anything we like, as long as we still come out 
+		the output edge that we want.
+	*/
+	if (reversed  == -1)
+	{
+		/*	Get the vertex for the last triangle, which is
+			the one coming out the output edge, before we do
+			any deletions to the list. We will be doing this
+			bottom up.
+		*/
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(out_edge2,index,size);
+		/*	We do not have to partially triangulate, since
+			we will do the whole thing, so use the whole routine
+		*/
+		/* Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
+				      vertex4,size-1,index,output,fp,reversed,
+				      face_id,next_id,pListHead,temp2,where); */
+		Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
+				      vertex4,size-1,index,output,fp,reversed,
+				      face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		/*	Lastly do the triangle that comes out the output
+			edge.
+		*/
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		/*	We were able to do the whole polygon, now we
+			can delete the whole thing from our data structure.
+		*/
+		dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+		RemoveList(pListHead,(PLISTINFO) temp2);
+		return;
+	}	  
+
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off that comes out the correct output edge, 
+		but we cannot use the whole polygon?
+	*/
+	if (in_edge2 == out_edge1) 
+	{
+		Output_TriEx(in_edge1,out_edge1,out_edge2,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge2,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+
+	/*	Next case is where it is again consecutive, but the triangle
+		formed by the consecutive edges do not come out of the
+		correct output edge. (the input edge will be reversed in
+		the next triangle)
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge1,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+        Delete_From_ListEx(in_edge1,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+		
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		
+		/*	Put the new face in the proper bucket of adjacencies */
+		next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge2,index,size);
+		/*	Update the face data structure, by deleting the old
+			face and putting in the polygon minus the triangle 
+			as the new face, here we will be decrementing the size
+			by one.
+		*/
+		New_Size_Face(face_id);
+		return;
+	}
+
+	/*	Else the edge is not consecutive, and it is sufficiently
+		far away, for us not to make a conclusion at this time.
+		So we can take off a triangle and recursively call this
+		function.
+	*/
+	else
+	{
+          if (!reversed)
+		{
+			vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+			Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+			
+			/*	Now delete the adjacencies by one for all the faces
+				that are adjacent to the triangle that we just outputted.
+			*/
+			Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+			Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+			
+			/*	Put the new face in the proper bucket of adjacencies */
+			next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+			next_bucket = Change_FaceEx(face_id,in_edge1,vertex4,pListHead,temp2,FALSE);
+			
+			/*	Create a new edgelist without the triangle that
+				was just outputted.
+			*/
+			Delete_From_ListEx(in_edge1,index,size);
+			/*	Update the face data structure, by deleting the old
+				face and putting in the polygon minus the triangle 
+				as the new face, here we will be decrementing the size
+				by one.
+			*/
+			New_Size_Face(face_id);
+
+			/*	Save the info for the new bucket, we will need it on
+				the next pass for the variables, pListHead and temp 
+			*/
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = face_id;
+			temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				(int (*)(void *,void *)) (Compare)));
+			if (temp2 == NULL)
+			{
+				printf("There is an error finding the next polygon10 %d %d\n",next_bucket,face_id);
+				exit(0);
+			}
+
+			P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+						 vertex4,size-1,index,output,fp,!reversed,
+						 face_id,next_id,pListHead,temp2,where);
+		}
+		else
+		{
+			vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+			Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+
+			/*	Now delete the adjacencies by one for all the faces
+				that are adjacent to the triangle that we just outputted.
+			*/
+			Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+			Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+			
+			/*	Put the new face in the proper bucket of adjacencies */
+			next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+			next_bucket = Change_FaceEx(face_id,in_edge2,vertex4,pListHead,temp2,FALSE);
+			
+			/*	Create a new edgelist without the triangle that
+				was just outputted.
+			*/
+			Delete_From_ListEx(in_edge2,index,size);
+			
+			/*	Update the face data structure, by deleting the old
+				face and putting in the polygon minus the triangle 
+				as the new face, here we will be decrementing the size
+				by one.
+			*/
+			New_Size_Face(face_id);
+			
+			/*	Save the info for the new bucket, we will need it on
+				the next pass for the variables, pListHead and temp 
+			*/
+			pListHead = array[next_bucket];
+			pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+			if ( pfNode )
+				pfNode->face_id = face_id;
+			temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+				(int (*)(void *,void *)) (Compare)));
+			if (temp2 == NULL)
+			{
+				printf("There is an error finding the next polygon11 %d %d\n",face_id,next_bucket);
+				exit(0);
+			}
+
+			P_Triangulate_Polygon(out_edge1,out_edge2,vertex4,
+						       in_edge1,size-1,index,output,fp,!reversed,
+						       face_id,next_id,pListHead,temp2,where);
+		}
+		return;
+	}
+}
+
+void P_Triangulate(int out_edge1,int out_edge2,int in_edge1,
+				 int in_edge2,int size,int *index,
+				 FILE *fp,FILE *output,int reversed,int face_id,
+				 int *next_id,ListHead *pListHead, 
+				 P_ADJACENCIES temp,int where)
+{
+		
+	if (size == 4)
+		P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			              index,fp,output,reversed,face_id,next_id,pListHead, temp,where);
+	else
+		P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			                 index,fp,output,reversed,face_id,next_id,pListHead,temp,where);
+}
+
+ void Partial_Triangulate(int size,int *index, FILE *fp,
+						 FILE *output,int next_face_id,int face_id,
+						 int *next_id,ListHead *pListHead,
+						 P_ADJACENCIES temp, int where)
+{
+	int id1,id2,id3;
+	int nedge1,nedge2;
+	int reversed;
+
+	/*	We have a polygon that has to be triangulated and we cannot
+		do it blindly, ie we will try to come out on the edge that
+		has the least number of adjacencies, But also we do not
+		want to triangulate the whole polygon now, so that means 
+		we will output the least number of triangles that we can
+		and then update the data structures, with the polygon
+		that is left after we are done.
+	*/
+	Last_Edge(&id1,&id2,&id3,0);
+	
+	/*	Find the edge that is adjacent to the new face ,
+		also return whether the orientation is reversed in the
+		face of the input edge, which is id2 and id3.
+	*/
+	reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+	
+	/*   Input edge and output edge can be the same if there are more than
+          one polygon on an edge 
+     */
+     if ( ((nedge1 == id2) && (nedge2 == id3)) ||
+          ((nedge1 == id3) && (nedge2 == id2)) )
+          /*   Set output edge arbitrarily but when come out of here the
+               next face will be on the old output edge (identical one)
+          */
+          nedge2 = Return_Other(index,id2,id3);
+
+          /*	Do the triangulation */	
+	P_Triangulate(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
+		         face_id,next_id,pListHead,temp,where);
+}
+
+ void Input_Edge(int face_id, int *index, int size, int in_edge1, int in_edge2, 
+                FILE *fp, FILE *output,ListHead *pListHead, P_ADJACENCIES temp2,
+                int where)
+ {
+     /* The polygon had an input edge, specified by input1 and input2 */
+    
+     int output1;
+     int vertex4, vertex5,dummy=60;
+
+     output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2);
+	vertex5 = AdjacentEx(in_edge2,in_edge1,index,size); 
+     vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+
+     if (vertex4 == output1)
+     {
+		Output_TriEx(in_edge2,in_edge1,output1,output,-1,-1,where);
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(in_edge2,output1,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		/*	Put the new face in the proper bucket of adjacencies */
+		Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		Change_FaceEx(face_id,in_edge2,output1,pListHead,temp2,FALSE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge2,index,size);
+
+    }	
+    else if (vertex5 == output1)
+    {
+          Output_TriEx(in_edge1,in_edge2,vertex5,output,-1,-1,where);
+		/*	Now delete the adjacencies by one for all the faces
+			that are adjacent to the triangle that we just outputted.
+		*/
+		Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+				&dummy,&dummy,&dummy);
+		Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy, 
+				face_id,&dummy,&dummy,&dummy);
+		/*	Put the new face in the proper bucket of adjacencies */
+		Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+		Change_FaceEx(face_id,in_edge1,vertex5,pListHead,temp2,FALSE);
+		
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+          Delete_From_ListEx(in_edge1,index,size);
+    }
+		
+    /*	Update the face data structure, by deleting the old
+		face and putting in the polygon minus the triangle 
+		as the new face, here we will be decrementing the size
+		by one.
+    */
+    New_Size_Face(face_id);
+    return;
+ }
+ 
+ void Inside_Polygon(int size,int *index,FILE *fp,FILE *output,
+                   int next_face_id,int face_id,int *next_id,
+                   ListHead *pListHead,P_ADJACENCIES temp, int where)
+ {
+     /* We know that we have a polygon that is greater than 4 sides, and
+        that it is better for us to go inside the polygon for the next
+        one, since inside will have less adjacencies than going outside.
+        So, we are not doing partial for a part of the polygon.
+      */
+    int id1,id2,id3;
+    int new1,new2;
+
+    Last_Edge(&id1,&id2,&id3,0);
+
+    /*  See if the input edge existed in the polygon, that will help us */
+	if (Exist(face_id,id2,id3))
+        Input_Edge(face_id,index,size,id2,id3,output,fp,pListHead,temp,where);
+    else
+    {
+        /*  Make one of the input edges 
+            We will choose it by trying to get an edge that has something
+            in common with the last triangle, or by getting the edge that
+            is adjacent to the least number of thigs, with preference given
+            to the first option
+        */
+               
+        Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id);
+        Input_Edge(face_id,index,size,new1,new2,output,fp,pListHead,temp,where);
+    }
+ }
+
+
diff --git a/Stripe_w/partial.h b/Stripe_w/partial.h
new file mode 100644
index 000000000..6a4e3a5b1
--- /dev/null
+++ b/Stripe_w/partial.h
@@ -0,0 +1,20 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: partial.h
+-----------------------------------------------------------------------*/
+
+void Partial_Triangulate(int size,int *index, FILE *fp,
+			 FILE *output,int next_face_id,int face_id,
+			 int *next_id,ListHead *pListHead,
+			 P_ADJACENCIES temp, int where);
+void Inside_Polygon(int size,int *index,FILE *fp,FILE *output,
+		    int next_face_id,int face_id,int *next_id,
+		    ListHead *pListHead,P_ADJACENCIES temp, int where);
+
diff --git a/Stripe_w/polverts.h b/Stripe_w/polverts.h
new file mode 100644
index 000000000..b3979eb4b
--- /dev/null
+++ b/Stripe_w/polverts.h
@@ -0,0 +1,108 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: polverts.h
+-----------------------------------------------------------------------*/
+
+
+#ifndef _POLVERTS_H
+#define _POLVERTS_H
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "queue.h"
+
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#else
+#  include <malloc.h>
+#endif
+
+
+typedef struct adjacencies
+{
+	Node ListNode;
+	int face_id;
+} ADJACENCIES,*P_ADJACENCIES;
+
+typedef struct FVerts
+{
+	Node ListNode;
+	int *pPolygon;
+	int nPolSize;
+	int nId;
+} F_VERTS, *PF_VERTS;
+
+/*Every time we need to use this, cast it ( ListInfo*)*/
+
+typedef struct FEdges
+{
+	Node ListNode;
+	int edge[3];
+}F_EDGES,*PF_EDGES;
+
+typedef struct FFaces
+{
+	Node ListNode;
+	int *pPolygon;
+	int *pNorms;
+    int     seen;
+    int seen2;
+    int seen3;
+	int nPolSize;
+	F_EDGES **VertandId;
+	int *marked;
+		int *walked;
+} F_FACES,*PF_FACES;
+	
+
+typedef struct Strips
+{
+	Node ListNode;
+	int face_id;
+} Strips,*P_STRIPS;
+
+
+     struct vert_added
+     {
+          int num;
+          int *normal;
+     };
+
+
+/*      external functions */
+void Find_Adjacencies(int num_faces);
+void Test_Adj_Struct();
+void Test_SGI_Struct();
+void Write_Edges();
+void Build_SGI_Table(int num_verts,int num_faces);
+void Save_Walks(int numfaces);
+void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, 
+                int *cost, int *tri, int norms, int *vert_norms, int texture,
+		int *vert_texture);
+void Save_Rest(int *numfaces);
+void Assign_Walk(int lastvert, PF_FACES temp2, int front_walk,int y,
+				int back_walk);
+void Save_Walks(int numfaces);
+	
+
+/*      Globals */
+extern ListHead **PolVerts;
+extern ListHead **PolFaces;
+extern ListHead **PolEdges;
+extern ListHead *array[60];
+extern int     id_array[60];
+extern ListHead *strips[1];
+extern ListHead *all_strips[100000]; /*  Assume max 100000 strips */
+
+
+#endif _POLVERTS_H
diff --git a/Stripe_w/polyvertsex.h b/Stripe_w/polyvertsex.h
new file mode 100644
index 000000000..8e05a7dd3
--- /dev/null
+++ b/Stripe_w/polyvertsex.h
@@ -0,0 +1,34 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: polvertsex.h
+-----------------------------------------------------------------------*/
+
+#include "queue.h"
+#include <malloc.h>
+
+
+/*      external functions */
+void Start_Vert_Struct();
+void Start_Face_StructEx();
+void Start_Edge_StructEx();
+void AddNewNode();
+void AddNewFaceEx();      
+void Find_AdjacenciesEx();
+void Test_Adj_Struct();
+void Test_SGI_Struct();
+void Write_Edges();
+void End_Verts_Struct();
+void End_Face_StructEx();
+void End_Edge_StructEx();
+void Build_SGI_TableEx();
+void Add_AdjEdgeEx();
+
+
+
diff --git a/Stripe_w/queue.c b/Stripe_w/queue.c
new file mode 100644
index 000000000..966f20379
--- /dev/null
+++ b/Stripe_w/queue.c
@@ -0,0 +1,226 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: queue.c
+     This file contains the routines used in the data structures lists, which
+     are queues.
+*/
+/*---------------------------------------------------------------------*/
+
+ #include "queue.h"
+ 
+
+
+/*----------------------------------------------------------------------------
+ * InitList:
+ */
+BOOL  InitList  (PLISTHEAD LHead)
+ 
+{
+  if (LHead == NULL) return(FALSE);
+
+  LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL;
+  LHead->NumList = 0;
+  return(TRUE);
+}
+
+/*----------------------------------------------------------------------------
+ * AddHead:
+ */
+BOOL  AddHead(PLISTHEAD LHead, PLISTINFO LInfo)
+{
+     if (LHead == NULL || LInfo == NULL)
+          return(FALSE);
+     if (EMPTYLIST(LHead))
+          LHead->LHeaders[LISTTAIL] = LInfo;
+     else LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void  *) LInfo;
+
+     LInfo->ListNode.Next = (void  *) LHead->LHeaders[LISTHEAD];
+     LHead->LHeaders[LISTHEAD] = LInfo;
+     LInfo->ListNode.Previous = NULL;
+     LHead->NumList++;
+     return(TRUE);
+}
+
+/*----------------------------------------------------------------------------
+ * AddTail
+ */
+BOOL  AddTail(PLISTHEAD LHead, PLISTINFO LInfo)
+{
+     if (LHead == NULL || LInfo == NULL)
+          return(FALSE);
+     if (EMPTYLIST(LHead))
+          LHead->LHeaders[LISTHEAD] = LInfo;
+     else LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo;
+
+     LInfo->ListNode.Previous = (void  *) LHead->LHeaders[LISTTAIL];
+     LHead->LHeaders[LISTTAIL] = LInfo;
+     LInfo->ListNode.Next = NULL;
+     LHead->NumList++;
+     return(TRUE);
+}
+
+
+BOOL  InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo )
+{
+PLISTINFO LAddNode;
+
+     if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) ) 
+          return( FALSE );
+
+     if ( nPos == 0 )
+          AddHead( LHead, LInfo );
+     else if ( nPos == NumOnList( LHead ) ) 
+          AddTail( LHead, LInfo );
+     else
+     {
+          if ( (LAddNode = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL )
+               return( FALSE );
+          
+          ((PLISTINFO)LAddNode->ListNode.Next)->ListNode.Previous = LInfo;
+          LInfo->ListNode.Next      = LAddNode->ListNode.Next;
+          LInfo->ListNode.Previous  = LAddNode;
+          LAddNode->ListNode.Next   = LInfo;
+          
+          LHead->NumList++;
+     }
+
+     return( TRUE );
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+ *  RemHead:
+ */
+PLISTINFO  RemHead(PLISTHEAD LHead)
+{
+     PLISTINFO t, t1;
+
+     if ( LHead == NULL || EMPTYLIST(LHead) )
+          return(NULL);
+
+     t = LHead->LHeaders[LISTHEAD];
+     LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next;
+
+     if (LHead->LHeaders[LISTHEAD] != NULL)
+     {
+          t1 = (PLISTINFO) t->ListNode.Next;
+          t1->ListNode.Previous = NULL;
+     }
+     else
+          LHead->LHeaders[LISTTAIL] = NULL;
+
+     LHead->NumList--;
+
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ *  RemTail:
+ */
+PLISTINFO  RemTail(PLISTHEAD   LHead)
+{
+     PLISTINFO   t, t1;
+
+     if ( LHead == NULL || EMPTYLIST(LHead) )
+          return(NULL);
+
+     t = LHead->LHeaders[LISTTAIL];
+     LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous;
+     if (LHead->LHeaders[LISTTAIL] != NULL)
+     {
+          t1 = (PLISTINFO) t->ListNode.Previous;
+          t1->ListNode.Next = NULL;
+     }
+     else
+          LHead->LHeaders[LISTHEAD] = NULL;
+
+     LHead->NumList--;
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ * PeekList:
+ */
+PLISTINFO  PeekList(PLISTHEAD LHead, int wch, int index )
+{
+     PLISTINFO  t;
+
+     if (LHead == NULL)
+          return(NULL);
+     if ( (t = LHead->LHeaders[wch]) == NULL )
+          return(NULL);
+
+     for (; t != NULL && index > 0; index-- )
+          t = (wch == LISTHEAD)  ? (PLISTINFO) t->ListNode.Next  :
+                                   (PLISTINFO) t->ListNode.Previous;
+     return(t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * RemoveList:
+ */
+PLISTINFO   RemoveList( PLISTHEAD LHead, PLISTINFO LInfo )
+{
+     PLISTINFO     t, t1;
+
+     t = LInfo;
+     if (LHead == NULL)
+          return(NULL);
+     if (LHead->LHeaders[LISTHEAD] == t)
+          t = (PLISTINFO) RemHead(LHead);
+     else if (LHead->LHeaders[LISTTAIL] == t)
+          t = (PLISTINFO) RemTail(LHead);
+     else
+     {
+          t1                    = (PLISTINFO) t->ListNode.Previous;
+          t1->ListNode.Next     = t->ListNode.Next;
+          t1                    = (PLISTINFO) t->ListNode.Next;
+          t1->ListNode.Previous = t->ListNode.Previous;
+          LHead->NumList--;
+     }
+
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ * SearchList:
+ *       Try to find a specific node in the queue whose key matches with
+ *  searching key. Return the pointer to that node if found, return NULL
+ *  otherwise
+ *
+ *  Input:
+ *    lpHashTbl       => a far pointer to the hash table
+ *    lpKey           => a far poniter to searching key
+ *    CompareCallBack => comparision function
+ *
+ *  Output: a far pointer to the node to be found
+ *
+ */
+PLISTINFO  SearchList(
+                        PLISTHEAD lpListHead,
+                        PVOID lpSKey,
+                        int (* CompareCallBack) ( PVOID, PVOID ) )
+{
+PLISTINFO lpListInfo;
+
+     lpListInfo = PeekList( lpListHead, LISTHEAD, 0);
+     while ( lpListInfo != NULL )
+     {
+          if ( CompareCallBack( lpListInfo, lpSKey ) )
+               break;
+          lpListInfo = GetNextNode( lpListInfo );
+     }
+
+     return( lpListInfo );
+}
+ 
diff --git a/Stripe_w/queue.h b/Stripe_w/queue.h
new file mode 100644
index 000000000..0bf926e0f
--- /dev/null
+++ b/Stripe_w/queue.h
@@ -0,0 +1,283 @@
+
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:queue.h
+-----------------------------------------------------------------------*/
+
+#ifndef QUEUE_INCLUDED
+#define QUEUE_INCLUDED
+
+/*        %%s  Node      */
+/*****************************************************************
+     This structure is used to store the List linkage information of a
+ListInfo structure.  It contains all the necessary information for the
+List functions to function properly.  This structure must be the first
+one defined in any block of memory to be linked with the List functions.
+for an example of the used of The Node structure look in the files
+ipd2dms.c and ipd2man.h
+******************************************************************/
+#include <stdio.h>
+#define FALSE 0
+#define TRUE  1
+typedef struct
+{
+     void  *Next;
+     void  *Previous;
+}
+     Node, * PNODE;
+
+/*****************************************************************
+     Next     :  is a pointer to the next structure in this List.
+     Previous :  is a pointer to the previous structure in this List.
+     priority :  this is the priority of this structure in the List.  The
+                 highest priority is 0.  This field is only used by the
+                 functions EnQue and DeQue.
+******************************************************************/
+/*        %%e       */
+
+
+/*        %%s  ListInfo      */
+
+/*****************************************************************
+      This is the general means of linking application defined information into
+Lists and queues.  All structures must begin with the Node Structure.  All
+other data in the structure is user definable.
+******************************************************************/
+
+typedef struct List
+{
+     Node     ListNode;       /*  link to the next Listinfo Structure  */
+     /*  user definable data  */
+}    ListInfo, *PLISTINFO;
+
+/*****************************************************************
+     ListNode  :  this is the required node structure for the List
+                  mainpulation functions.  This must be the first
+                  element of a user definable structure.
+
+     In order for an application to use the List routines, it must define
+a structure with all the needed information.  The first element in the
+user definable structure must be a Node structure.  The Node structure
+contains all the necessary information for the List routines to do their
+magic.  For an example of a user defined List structure see the file
+ipd2i.h.  The User definable structure can be passed to any List function
+that excepts a pointer to a ListInfo structure.
+
+example:
+
+typedef  mstruct
+{
+     Node   ListNode;
+     int    a,b,c,d,e,f,g;
+}
+     mystruct;
+
+     the user definable portion of the above structure is represented by
+the integers a,b,c,d,e,f,g.  When passing this structure to a List
+function a cast of (ListInfo *) must be made to satisify the "C" complier.
+******************************************************************/
+/*        %%e       */
+
+
+/*        %%s ListHead        */
+/*****************************************************************
+     ListHead is used as a header to a List.  LHeaders[0] points to the
+head of the List.  LHeaders[1] points the tail of the list.  When
+accessing these variables use the defines  LISTHEAD, LISTTAIL.
+******************************************************************/
+
+typedef struct LHead
+{
+     PLISTINFO  LHeaders[2];
+     int         NumList;
+}
+ListHead, *PLISTHEAD;
+
+/*****************************************************************
+     LHeaders   :  this is an array of two pointers to ListInfo structures.
+                   This information is used to point to the head and tail of
+                   a list.
+     NumList    :  this integer hold the number of structures linked into this
+                   list.
+
+ListHead #define:
+
+     LISTHEAD  :  when Peeking down a list this specifies you should
+                  start at the Head of the list and search downward.
+
+     LISTTAIL  :  when Peeking down a list this specifies you should
+                  start at the tail of the list and search foward.
+ ******************************************************************/
+
+#define  LISTHEAD  0
+
+#define  LISTTAIL  1
+/*        %%e       */ 
+
+typedef int BOOL;
+typedef void * PVOID;
+
+#define PEEKFROMHEAD( lh, ind )     ( PeekList( (lh), LISTHEAD, (ind) ) )
+#define PEEKFROMTAIL( lh, ind )     ( PeekList( (lh), LISTTAIL, (ind) ) )
+#define EMPTYLIST( lh )             ( ( (lh)->LHeaders[LISTHEAD] == NULL ) )
+
+/*   General utility routines   */
+/*        %%s QueRoutines          */
+BOOL    InitList      ( PLISTHEAD );
+
+/*****************************************************************
+     InitList :  Initialize a new list structure for use with the List
+                 routines
+
+     INPUTS   :  LHead : a pointer to a ListHead structure.
+     OUTPUT   :  a boolean value TRUE if no errors occured FALSE
+                 otherwise
+******************************************************************/
+
+
+PLISTINFO  PeekList      ( PLISTHEAD, int, int   );
+
+/*****************************************************************
+     PeekList :  This funciton peeks down a list for the N'th element
+                 from the HEAD or TAIL of the list
+
+     INPUTS   :  LHead    :  a pointer to a List head structure.
+                 from     :  can either search from the HEAD or TAIL
+                             of the list
+                 where    :  how many nodes from the begining should the
+                             List routines look.
+     OUTPUT   :  a pointer to a ListInfo structure identified by
+                 from/where or NULL if an error occurred.
+******************************************************************/
+
+
+PLISTINFO   RemoveList( PLISTHEAD LHead, PLISTINFO LInfo );
+
+
+/*****************************************************************
+     RemoveList: Remove a ListInfo structure from a List.
+
+     INPUTS    : LHead  :  a pointer to a ListHead structure.
+                 LInfo  :  a pointer to the ListInfo structure to remove
+                           from the list.
+     OUTPUT    : a pointer to the ListInfo structure that was removed or
+                 NULL if an error occurred.
+******************************************************************/
+
+BOOL  InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo );
+
+/*****************************************************************
+     InsertNode: add a node to a list after a given node
+     
+     INPUTS    : LHead : a pointer to a ListHead structure.
+                 nPos  : the position to insert the node into
+                 LInfo : a pointer to the new node to add to the list.
+     OUTPUT: a boolean value TRUE if all goes well false otherwise
+*****************************************************************/
+
+BOOL   AddHead       ( PLISTHEAD, PLISTINFO );
+
+/*****************************************************************
+     AddHead   : add a ListInfo structure to the HEAD of a list.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the list
+                          to add to.
+                 LInfo  : a pointer to the ListInfo structure to add to
+                          the list.
+     OUTPUT    : A boolean value TRUE if no errors occurred FALSE
+                 otherwise.
+******************************************************************/
+
+
+BOOL     AddTail       ( PLISTHEAD, PLISTINFO );
+
+/*****************************************************************
+     AddTail   : Add a ListInfo structure to the TAIL of a list.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to add to.
+                 LInfo  : a pointer to the ListInfo structure to add to
+                          the List.
+     OUTPUT    : a boolean value TRUE if no errors occurred FALSE
+                 otherwise.
+******************************************************************/
+
+
+PLISTINFO  RemTail       ( PLISTHEAD );
+
+/*****************************************************************
+     RemTail   : Remove a ListInfo structure from the TAIL of a List.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to remove from.
+     OUTPUT    : a pointer to the ListInfo structure that was removed
+                 or NULL if an error occurred.
+******************************************************************/
+
+
+PLISTINFO  RemHead       ( PLISTHEAD );
+
+/*****************************************************************
+     RemHead   : Remove a ListInfo structure from the Head of a List.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to remove from.
+     OUTPUT    : a pointer to the ListInfo structure that was removed or
+                 NULL if an error occurred.
+******************************************************************/
+
+PLISTINFO  SearchList(
+                        PLISTHEAD lpListHead,
+                        PVOID lpSKey,
+                        int ( * CompareCallBack) ( PVOID, PVOID ) );
+
+/*****************************************************************
+  SearchList:
+        Try to find a specific node in the queue whose key matches with
+   searching key. Return the pointer to that node if found, return NULL
+   otherwise
+
+   Input:
+     lpHashTbl       => a far pointer to the hash table
+     lpKey           => a far poniter to searching key
+     CompareCallBack => comparision function
+
+   Output: a far pointer to the node to be found
+
+ ******************************************************************/
+
+#define           NumOnList(lh) ( ((lh)->NumList)        )
+
+/*****************************************************************
+     NumOnList: Returns the number of Nodes linked to a ListHead
+                structure.  This number is maintained by the List
+                routines.
+******************************************************************/
+
+#define           GetNextNode(pli) ( ((pli)->ListNode.Next) )
+
+/********************************************************
+     GetNextNode: This macro returns the Next Structure in this list.
+                  This macro will return NULL if no more structures are
+                  in the List.
+*********************************************************/
+
+#define           GetPrevNode(pli) ( ((pli)->ListNode.Previous) )
+
+/********************************************************
+     GetPrevNode: This macro returns the Previous Structure in this list.
+                  This macro will reutrn NULL if no more structures are
+                  in the List.
+********************************************************/
+/*        %%e       */
+
+#endif
+
+
diff --git a/Stripe_w/sgi_triang.c b/Stripe_w/sgi_triang.c
new file mode 100644
index 000000000..1a130906e
--- /dev/null
+++ b/Stripe_w/sgi_triang.c
@@ -0,0 +1,628 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sgi_triang.c
+     File contains the routines that do the whole triangulation
+     of polygons.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "output.h"
+#include "polverts.h"
+#include "sturcts.h"
+#include "common.h"
+#include "util.h"
+#include "init.h"
+
+int Adjacent(int id2,int id1, int *list, int size)
+{
+	/*	Return the vertex that is adjacent to id1,
+		but is not id2, in the list of integers.
+	*/
+
+	register int x=0;
+	
+	while (x < size)
+	{
+		if (*(list+x) == id1)
+		{
+			if ((x != (size -1)) && (x != 0))
+			{
+				if ( *(list+x+1) != id2)
+					return *(list+x+1);
+				else
+					return *(list+x-1);
+			}
+			else if (x == (size -1))
+			{
+				if (*(list) != id2)
+					return *(list);
+				else
+					return *(list+x-1);
+			}
+			else
+			{
+				if (*(list+size-1) != id2)
+					return *(list+size-1);
+				else
+					return *(list+x+1);
+			}
+		}
+		x++;
+	}
+	/*   if there are degeneracies */
+     return id1;
+}
+
+
+void Rearrange_Index(int *index, int size)
+{
+	/*	If we are in the middle of a strip we must find the
+		edge to start on, which is the last edge that we had
+		transmitted.
+	*/
+	int x,f,y,e1,e2,e3;
+ 	register int increment = 1;
+     int *temp;
+
+	/*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+	for (y = 0; y < size; y++)
+	{
+		if (*(index+y) == e2)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e3))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e3))
+				break;
+               else if ((y != 0) && (*(index+y-1) == e3))
+               {
+                    increment = -1;
+                    break;
+               }
+               else if ((y==0) && (*(index+size-1) == e3))
+               {
+                    increment = -1;
+                    break;
+               }
+		}
+		if (*(index+y) == e3)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e2))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e2))
+				break;
+            else if ((y != 0) && (*(index+y-1) == e2))
+            {
+                increment = -1;
+                break;
+            }
+            else if ((y==0) && (*(index+size-1) == e2))
+            {
+                increment = -1;
+                break;
+            }
+		}
+		/*	Edge is not here, we are at the beginning */
+		if ((y == (size-1)) && (increment != -1))
+			return;
+	}
+	
+	/*	Now put the list into a new list, starting with the
+		input edge. Increment tells us whether we have to go 
+		forward or backward.
+	*/
+	/*	Was in good position already */
+	if ((y == 0) && (increment == 1)) 
+		return;
+	
+     temp = (int *) malloc(sizeof(int) * size);
+     memcpy(temp,index,sizeof(int)*size);
+
+	if (increment == 1)
+	{
+		x=0;
+		for (f = y ; f< size; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = 0; f < y ; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+	else
+	{
+		x=0;
+		for (f = y ; f >= 0; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = (size - 1); f > y ; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+}
+
+void Delete_From_List(int id,int *list, int *size)
+{
+	/*	Delete the occurence of id in the list.
+		(list has size size)
+	*/
+
+	int *temp;
+	register int x,y=0;
+
+	temp = (int *) malloc(sizeof(int) * (*size));
+	for (x=0; x<(*size); x++)
+	{
+		if (*(list+x) != id)
+		{
+			*(temp+y) = *(list+x);
+			y++;
+		}
+	}
+	*(temp+y) = -1;
+     *size = *size - (*size - y - 1);
+	memcpy(list,temp,sizeof(int)*(*size));
+}
+
+
+void Build_SGI_Table(int num_verts,int num_faces)
+{
+	/*      Build a table that has the polygons sorted by the
+	        number of adjacent polygons.
+	*/
+	int x,y,size,tally=0;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+
+	/* For each face....*/
+	for (x=0;x < num_faces;x++)
+	{
+		pListHead = PolFaces[x];
+		temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+		/*   Check each edge of the face and tally the number of adjacent
+			polygons to this face. 
+		*/                      
+		if ( temp != NULL )
+		{
+			/*      Size of the polygon */
+			size = temp->nPolSize;
+			if (size != 1)
+      {
+        for (y = 0; y< size; y++)
+			  {
+				  if (y != (size-1))
+					  tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1));
+				  else
+					  tally += Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)));
+        }
+			
+			  /* Tally is the number of polygons that is adjacent to
+				   the current polygon. 
+			  */
+			  /* Now put the face in the proper bucket depending on tally. */
+			  Add_Sgi_Adj(tally,x);
+			  temp = NULL;
+			  tally=0;
+      }
+		}
+	}
+}
+
+
+void Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,int reversed,int face_id,
+                      int where,int color1,int color2,int color3)
+{
+	int vertex4,vertex5;
+	
+	/*	This routine will nonblindly triangulate a quad, meaning
+		that there is a definite input and a definite output
+		edge that we must adhere to. Reversed will tell the orientation
+		of the input edge. (Reversed is -1 is we do not have an input
+		edge, in other words we are at the beginning of a strip.)
+		Out_edge* is the output edge, and in_edge* is the input edge. 
+		Index are the edges of the polygon
+		and size is the size of the polygon. Begin is whether we are
+		at the start of a new strip.
+	*/
+	
+	/*	If we do not have an input edge, then we can make our input
+		edge whatever we like, therefore it will be easier to come
+		out on the output edge.
+	*/
+	if (reversed == -1)
+	{
+		vertex4 = Adjacent(out_edge1,out_edge2,index,size);
+		vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+		Output_Tri(vertex5,vertex4,out_edge1,output,color1,color2,color3,where);
+		Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where);
+		return;
+	}
+	
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off, but cannot use the whole quad?
+	*/
+
+	if (in_edge2 == out_edge1) 
+	{
+		/* Output the triangle that comes out the correct
+			 edge last. First output the triangle that comes out
+			 the wrong edge.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+    Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+    Output_Tri(vertex4,in_edge2,out_edge2,output,color1,color2,color3,where);
+		return;
+	}
+	/* The next case is where it is impossible to come out the
+		 edge that we want. So we will have to start a new strip to
+		 come out on that edge. We will output the one triangle
+		 that we can, and then start the new strip with the triangle
+		 that comes out on the edge that we want to come out on.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/* We want to output the first triangle (whose output
+			 edge is not the one that we want.
+			 We have to find the vertex that we need, which is
+			 the other vertex which we do not have.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
+		Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+		Output_Tri(vertex4,in_edge1,out_edge2,output,color1,color2,color3,where);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+		Output_Tri(vertex4,in_edge1,out_edge1,output,color1,color2,color3,where);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+		Output_Tri(vertex4,in_edge2,out_edge1,output,color1,color2,color3,where);
+		return;
+	}
+
+	/*	The final case is where we want to come out the opposite
+		edge.
+	*/
+	else
+	{
+    if( ((!reversed) && (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) ||
+        ((reversed) && (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size)))))
+		{
+		  /* We need to know the orientation of the input
+				 edge, so we know which way to put the diagonal.
+         And also the output edge, so that we triangulate
+         correctly.
+      */
+			Output_Tri(in_edge1,in_edge2,out_edge2,output,color1,color2,color3,where);
+			Output_Tri(in_edge2,out_edge2,out_edge1,output,color1,color2,color3,where);
+		}
+		else
+		{
+			/* Input and output orientation was reversed, so diagonal will
+				 be reversed from above.
+			*/
+			Output_Tri(in_edge1,in_edge2,out_edge1,output,color1,color2,color3,where);
+			Output_Tri(in_edge2,out_edge1,out_edge2,output,color1,color2,color3,where);
+		}
+		return;
+	}
+}
+
+void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1,
+			                   int in_edge2, int size, int *index,
+						             FILE *output, int reversed, int face_id,
+                         int where, int color1, int color2, int color3)
+{
+	/* We have a polygon that we need to nonblindly triangulate.
+		 We will recursively try to triangulate it, until we are left
+		 with a polygon of size 4, which can use the quad routine
+		 from above. We will be taking off a triangle at a time
+		 and outputting it. We will have 3 cases similar to the
+		 cases for the quad above. The inputs to this routine
+		 are the same as for the quad routine.
+	*/
+
+	int vertex4;
+	int *temp;
+		
+	/* Since we are calling this recursively, we have to check whether
+		 we are down to the case of the quad.
+	*/
+	
+  if (size == 4)
+	{
+	  Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+				index,output,reversed,face_id,where,color1,color2,color3);
+		return;
+	}
+
+    
+	
+	/*	We do not have a specified input edge, and therefore we
+		can make it anything we like, as long as we still come out 
+		the output edge that we want.
+	*/
+	if (reversed  == -1)
+	{
+		/*	Get the vertex for the last triangle, which is
+			the one coming out the output edge, before we do
+			any deletions to the list. We will be doing this
+			bottom up.
+		*/
+		vertex4 = Adjacent(out_edge1,out_edge2,index,size);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(out_edge2,index,&size);
+		Triangulate_Polygon(out_edge1,vertex4,in_edge2,
+						 vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		/*	Lastly do the triangle that comes out the output
+			edge.
+		*/
+		Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where);
+		return;
+	}
+
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off that comes out the correct output edge, 
+		but we cannot use the whole polygon?
+	*/
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge last. First recursively do the rest of the
+			polygon.
+		*/
+		/*	Do the rest of the polygon without the triangle. 
+			We will be doing a fan triangulation.
+		*/
+		/*	Get the vertex adjacent to in_edge1, but is not
+			in_edge2.
+		*/
+		vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+          Delete_From_List(in_edge1,index,&size);
+		Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+						vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Next case is where it is again consecutive, but the triangle
+		formed by the consecutive edges do not come out of the
+		correct output edge. For this case, we can not do much to
+		keep it sequential. Try and do the fan.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = Adjacent(in_edge1,in_edge2,index,size);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+		/*	Since that triangle goes out of the polygon (the
+			output edge of it), we can make our new input edge
+			anything we like, so we will try to make it good for
+			the strip. (This will be like starting a new strip,
+			all so that we can go out the correct output edge.)
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(in_edge2,index,&size);
+		Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
+						vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = Adjacent(in_edge1,in_edge2,index,size);
+		Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(in_edge2,index,&size);
+          Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
+						vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+		Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_List(in_edge1,index,&size);
+          Triangulate_Polygon(out_edge1,out_edge2,vertex4,
+						in_edge2,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Else the edge is not consecutive, and it is sufficiently
+		far away, for us not to make a conclusion at this time.
+		So we can take off a triangle and recursively call this
+		function.
+	*/
+	else
+	{
+			vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+			Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+			temp = (int *) malloc(sizeof(int) * size);
+			memcpy(temp,index,sizeof(int)*size);
+			Delete_From_List(in_edge1,index,&size);
+               Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+						     vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
+			memcpy(index,temp,sizeof(int)*size);
+		     return;
+	}
+}
+
+void Triangulate(int out_edge1,int out_edge2,int in_edge1,
+				 int in_edge2,int size,int *index,
+				 FILE *output,int reversed,int face_id, int where,
+                     int color1, int color2,int color3)
+{
+	/*	We have the info we need to triangulate a polygon */
+
+	if (size == 4)
+		Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			            index,output,reversed,face_id,where,color1,color2,color3);
+	else
+		Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			               index,output,reversed,face_id,where,color1,color2,color3);
+}
+
+void Non_Blind_Triangulate(int size,int *index,
+					  FILE *output,int next_face_id,int face_id,int where,
+                           int color1,int color2,int color3)
+{
+	int id1,id2,id3;
+	int nedge1,nedge2;
+	int reversed;
+	/*	We have a polygon that has to be triangulated and we cannot
+		do it blindly, ie we will try to come out on the edge that
+		has the least number of adjacencies
+	*/
+
+	Last_Edge(&id1,&id2,&id3,0);
+	/*	Find the edge that is adjacent to the new face ,
+		also return whether the orientation is reversed in the
+		face of the input edge, which is id2 and id3.
+	*/
+	if (next_face_id == -1)
+     {
+        printf("The face is -1 and the size is %d\n",size);
+        exit(0);
+     }
+    
+     reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+	/*	Do the triangulation */
+	
+	/*	If reversed is -1, the input edge is not in the polygon, therefore we can have the
+		input edge to be anything we like, since we are at the beginning
+		of a strip
+	*/
+	Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed,
+		       face_id, where,color1,color2,color3);
+}
+
+
+
+void Blind_Triangulate(int size, int *index, FILE *output,
+				   BOOL begin, int where ,int color1,int color2,
+                       int color3)
+{
+	/*	save sides in temp array, we need it so we know
+		about swaps.
+	*/
+	int mode, decreasing,increasing,e1,e2,e3;
+
+	/*	Rearrange the index list so that the input edge is first
+	*/
+	if (!begin)
+		Rearrange_Index(index,size);
+	
+	/*	We are given a polygon of more than 3 sides
+		and want to triangulate it. We will output the
+		triangles to the output file.
+	*/
+	
+    /*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+     if (( (!begin) && (*(index) == e2) ) || (begin))
+     {
+	    Output_Tri(*(index+0),*(index+1),*(index+size-1),output,color1,color2,color3,where);
+        /*	If we have a quad, (chances are yes), then we know that
+	   	     we can just add one diagonal and be done. (divide the
+		     quad into 2 triangles.
+        */
+        if (size == 4)
+        {
+		    Output_Tri(*(index+1),*(index+size-1),*(index+2),output,color1,color2,color3,where);
+              return;
+        }
+        increasing = 1;
+        mode = 1;
+
+    }
+    else if (!begin)
+    {
+        Output_Tri(*(index+1),*(index+0),*(index+size-1),output,color1,color2,color3,where);
+        if (size == 4)
+        {
+            Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where);
+            return;
+        }
+        Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where);
+        increasing = 2;
+        mode = 0;
+    }
+    if (size != 4)
+    {
+		/*	We do not have a quad, we have something bigger. */
+		decreasing = size - 1;		
+		do
+		{
+			/*	Will be alternating diagonals, so we will be increasing
+				and decreasing around the polygon.
+			*/
+			if (mode)
+			{
+				Output_Tri(*(index+increasing),*(index+decreasing),*(index+increasing+1),output,color1,color2,color3,where);
+				increasing++;
+			}
+			else
+			{
+				Output_Tri(*(index+decreasing),*(index+increasing),*(index+decreasing-1),output,color1,color2,color3,where);
+                    decreasing--;
+               }
+			mode = !mode;
+		} while ((decreasing - increasing) >= 2);
+
+	}
+}
+
+
+
+
diff --git a/Stripe_w/sgi_triangex.c b/Stripe_w/sgi_triangex.c
new file mode 100644
index 000000000..9f153a1e8
--- /dev/null
+++ b/Stripe_w/sgi_triangex.c
@@ -0,0 +1,582 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sgi_triangex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "outputex.h"
+#include "polverts.h"
+#include "sturctsex.h"
+#include "common.h"
+#include "util.h"
+
+
+int AdjacentEx(int id2,int id1, int *list, int size)
+{
+	/*	Return the vertex that is adjacent to id1,
+		but is not id2, in the list of integers.
+	*/
+
+	register int x=0;
+	
+	while (x < size)
+	{
+		if (*(list+x) == id1)
+		{
+			if ((x != (size -1)) && (x != 0))
+			{
+				if ( *(list+x+1) != id2)
+					return *(list+x+1);
+				else
+					return *(list+x-1);
+			}
+			else if (x == (size -1))
+			{
+				if (*(list) != id2)
+					return *(list);
+				else
+					return *(list+x-1);
+			}
+			else
+			{
+				if (*(list+size-1) != id2)
+					return *(list+size-1);
+				else
+					return *(list+x+1);
+			}
+		}
+		x++;
+	}
+	printf("Error in the list\n");
+	exit(0);
+}
+
+
+void Delete_From_ListEx(int id,int *list, int size)
+{
+	/*	Delete the occurence of id in the list.
+		(list has size size)
+	*/
+
+	int *temp;
+	register int x,y=0;
+
+	temp = (int *) malloc(sizeof(int) * size);
+	for (x=0; x<size; x++)
+	{
+		if (*(list+x) != id)
+		{
+			*(temp+y) = *(list+x);
+			y++;
+		}
+	}
+	if(y != (size-1))
+	{
+		printf("There is an error in the delete\n");
+		exit(0);
+	}
+	*(temp+size-1) = -1;
+	memcpy(list,temp,sizeof(int)*size);
+
+}
+
+
+void Triangulate_QuadEx(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,FILE *fp,int reversed,int face_id,
+                      int where)
+{
+	int vertex4,vertex5;
+	
+	/*	This routine will nonblindly triangulate a quad, meaning
+		that there is a definite input and a definite output
+		edge that we must adhere to. Reversed will tell the orientation
+		of the input edge. (Reversed is -1 is we do not have an input
+		edge, in other words we are at the beginning of a strip.)
+		Out_edge* is the output edge, and in_edge* is the input edge. 
+		Index are the edges of the polygon
+		and size is the size of the polygon. Begin is whether we are
+		at the start of a new strip.
+	*/
+	
+	/*	If we do not have an input edge, then we can make our input
+		edge whatever we like, therefore it will be easier to come
+		out on the output edge.
+	*/
+	if (reversed == -1)
+	{
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+		Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		return;
+	}
+	
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*   Are they consecutive so that we form a triangle to
+		peel off, but cannot use the whole quad?
+	*/
+
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge last. First output the triangle that comes out
+			the wrong edge.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+          Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+          Output_TriEx(vertex4,in_edge2,out_edge2,output,-1,-1,where);
+		return;
+	}
+	/*	The next case is where it is impossible to come out the
+		edge that we want. So we will have to start a new strip to
+		come out on that edge. We will output the one triangle
+		that we can, and then start the new strip with the triangle
+		that comes out on the edge that we want to come out on.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	We want to output the first triangle (whose output
+			edge is not the one that we want.
+			We have to find the vertex that we need, which is
+			the other vertex which we do not have.
+		*/
+		vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
+		Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+		Output_TriEx(vertex4,in_edge1,out_edge2,output,-1,-1,where);
+		return;
+	}
+	
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+		Output_TriEx(vertex4,in_edge1,out_edge1,output,-1,-1,where);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+		Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+		Output_TriEx(vertex4,in_edge2,out_edge1,output,-1,-1,where);
+		return;
+	}
+
+	/*	The final case is where we want to come out the opposite edge.*/
+	else
+	{
+           if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
+                    ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
+		 {
+			/*	We need to know the orientation of the input
+				edge, so we know which way to put the diagonal.
+                    And also the output edge, so that we triangulate correctly.
+               */
+			Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
+		 }
+		else
+		{
+			/*   Input and output orientation was reversed, so diagonal will
+				be reversed from above.
+			*/
+			Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+			Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
+		}
+		return;
+	}
+}
+
+void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1,
+					  int in_edge2,int size,int *index,
+					  FILE *output,FILE *fp,int reversed,int face_id,
+                           int where)
+{
+	/*	We have a polygon that we need to nonblindly triangulate.
+		We will recursively try to triangulate it, until we are left
+		with a polygon of size 4, which can use the quad routine
+		from above. We will be taking off a triangle at a time
+		and outputting it. We will have 3 cases similar to the
+		cases for the quad above. The inputs to this routine
+		are the same as for the quad routine.
+	*/
+
+	int vertex4;
+	int *temp;
+
+		
+	/*	Since we are calling this recursively, we have to check whether
+		we are down to the case of the quad.
+	*/
+	
+    if (size == 4)
+	{
+		Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+					    index,output,fp,reversed,face_id,where);
+		return;
+	}
+
+    
+	
+	/*	We do not have a specified input edge, and therefore we
+		can make it anything we like, as long as we still come out 
+		the output edge that we want.
+	*/
+	if (reversed  == -1)
+	{
+		/*	Get the vertex for the last triangle, which is
+			the one coming out the output edge, before we do
+			any deletions to the list. We will be doing this
+			bottom up.
+		*/
+		vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(out_edge2,index,size);
+		Triangulate_PolygonEx(out_edge1,vertex4,in_edge2,
+					   	  vertex4,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		/*	Lastly do the triangle that comes out the output
+			edge.
+		*/
+		Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+		return;
+	}
+
+	/*	These are the 5 cases that we can have for the output edge */
+	
+	/*  Are they consecutive so that we form a triangle to
+		peel off that comes out the correct output edge, 
+		but we cannot use the whole polygon?
+	*/
+	if (in_edge2 == out_edge1) 
+	{
+		/*	Output the triangle that comes out the correct
+			edge last. First recursively do the rest of the
+			polygon.
+		*/
+		/*	Do the rest of the polygon without the triangle. 
+			We will be doing a fan triangulation.
+		*/
+		/*	Get the vertex adjacent to in_edge1, but is not
+			in_edge2.
+		*/
+		vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+		Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+		/*	Create a new edgelist without the triangle that
+			was just outputted.
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+          Delete_From_ListEx(in_edge1,index,size);
+		Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
+						  vertex4,size-1,index,output,fp,!reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Next case is where it is again consecutive, but the triangle
+		formed by the consecutive edges do not come out of the
+		correct output edge. For this case, we can not do much to
+		keep it sequential. Try and do the fan.
+	*/
+	else if (in_edge1 == out_edge1)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+		Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+		/*	Since that triangle goes out of the polygon (the
+			output edge of it), we can make our new input edge
+			anything we like, so we will try to make it good for
+			the strip. (This will be like starting a new strip,
+			all so that we can go out the correct output edge.)
+		*/
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(in_edge2,index,size);
+		Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
+						  vertex4,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	/*	Consecutive cases again, but with the output edge reversed */
+	else if (in_edge1 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+		Output_TriEx(in_edge2,in_edge1,vertex4,fp,-1,-1,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(in_edge2,index,size);
+          Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
+		      		       vertex4,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+	else if (in_edge2 == out_edge2)
+	{
+		/*	Get vertex adjacent to in_edge2, but is not in_edge1 */
+		vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+		Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+		temp = (int *) malloc(sizeof(int) * size);
+		memcpy(temp,index,sizeof(int)*size);
+		Delete_From_ListEx(in_edge1,index,size);
+          Triangulate_PolygonEx(out_edge1,out_edge2,vertex4,
+						  in_edge2,size-1,index,output,fp,reversed,face_id,where);
+		memcpy(index,temp,sizeof(int)*size);
+		return;
+	}
+
+	/*	Else the edge is not consecutive, and it is sufficiently
+		far away, for us not to make a conclusion at this time.
+		So we can take off a triangle and recursively call this
+		function.
+	*/
+	else
+	{
+			vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+			Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+			temp = (int *) malloc(sizeof(int) * size);
+			memcpy(temp,index,sizeof(int)*size);
+			Delete_From_ListEx(in_edge1,index,size);
+               Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
+						       vertex4,size-1,index,output,fp,!reversed,face_id,where);
+			memcpy(index,temp,sizeof(int)*size);
+		     return;
+	}
+}
+
+void TriangulateEx(int out_edge1,int out_edge2,int in_edge1,
+				 int in_edge2,int size,int *index,
+				 FILE *fp,FILE *output,int reversed,int face_id, int where)
+{
+	/*	We have the info we need to triangulate a polygon */
+
+	if (size == 4)
+		Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			              index,fp,output,reversed,face_id,where);
+	else
+		Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+			                 index,fp,output,reversed,face_id,where);
+}
+
+void Non_Blind_TriangulateEx(int size,int *index, FILE *fp,
+						 FILE *output,int next_face_id,int face_id,int where)
+{
+	int id1,id2,id3;
+	int nedge1,nedge2;
+	int reversed;
+	/*	We have a polygon that has to be triangulated and we cannot
+		do it blindly, ie we will try to come out on the edge that
+		has the least number of adjacencies
+	*/
+
+	Last_Edge(&id1,&id2,&id3,0);
+	/*	Find the edge that is adjacent to the new face ,
+		also return whether the orientation is reversed in the
+		face of the input edge, which is id2 and id3.
+	*/
+	if (next_face_id == -1)
+    {
+        printf("The face is -1 and the size is %d\n",size);
+        exit(0);
+    }
+    
+    reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+	/*	Do the triangulation */
+	
+	/*	If reversed is -1, the input edge is not in the polygon, therefore we can have the
+		input edge to be anything we like, since we are at the beginning
+		of a strip
+	*/
+	TriangulateEx(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
+		         face_id, where);
+}
+
+void Rearrange_IndexEx(int *index, int size)
+{
+	/*	If we are in the middle of a strip we must find the
+		edge to start on, which is the last edge that we had
+		transmitted.
+	*/
+	int x,f,y,e1,e2,e3;
+	int increment = 1;
+     int *temp;
+
+	/*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+	for (y = 0; y < size; y++)
+	{
+		if (*(index+y) == e2)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e3))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e3))
+				break;
+               else if ((y != 0) && (*(index+y-1) == e3))
+               {
+                   increment = -1;
+                   break;
+               }
+               else if ((y==0) && (*(index+size-1) == e3))
+               {
+                   increment = -1;
+                   break;
+               }
+		}
+		if (*(index+y) == e3)
+		{
+			if ((y != (size - 1)) && (*(index+y+1) == e2))
+				break;
+			else if ((y == (size - 1)) && (*(index) == e2))
+				break;
+               else if ((y != 0) && (*(index+y-1) == e2))
+               {
+                   increment = -1;
+                   break;
+               }
+               else if ((y==0) && (*(index+size-1) == e2))
+               {
+                   increment = -1;
+                   break;
+               }
+		}
+		/*	Edge is not here, we are at the beginning */
+		if ((y == (size-1)) && (increment != -1))
+			return;
+	}
+	
+	/*	Now put the list into a new list, starting with the
+		input edge. Increment tells us whether we have to go 
+		forward or backward.
+	*/
+	/*	Was in good position already */
+	if ((y == 0) && (increment == 1)) 
+		return;
+	
+	            
+    temp = (int *) malloc(sizeof(int) * size);
+    memcpy(temp,index,sizeof(int)*size);
+
+	if (increment == 1)
+	{
+		x=0;
+		for (f = y ; f< size; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = 0; f < y ; f++)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+	else
+	{
+		x=0;
+		for (f = y ; f >= 0; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+		/*	Finish the rest of the list */	
+		for(f = (size - 1); f > y ; f--)
+		{
+			*(index+x) = *(temp+f);
+			x++;
+		}
+	}
+}
+
+void Blind_TriangulateEx(int size, int *index, FILE *fp,
+						 FILE *output, BOOL begin, int where )
+{
+	/*	save sides in temp array, we need it so we know
+		about swaps.
+	*/
+	int mode, decreasing,increasing,e1,e2,e3;
+
+	/*	Rearrange the index list so that the input edge is first
+	*/
+	if (!begin)
+		Rearrange_IndexEx(index,size);
+	
+	/*	We are given a polygon of more than 3 sides
+		and want to triangulate it. We will output the
+		triangles to the output file.
+	*/
+	
+    /*	Find where the input edge is in the input list */
+	Last_Edge(&e1,&e2,&e3,0);
+     if (( (!begin) && (*(index) == e2) ) || (begin))
+     {
+	    Output_TriEx(*(index+0),*(index+1),*(index+size-1),fp,-1,-1,where);
+        /*	If we have a quad, (chances are yes), then we know that
+		we can just add one diagonal and be done. (divide the
+		quad into 2 triangles.
+        */
+        if (size == 4)
+        {
+		    Output_TriEx(*(index+1),*(index+size-1),*(index+2),fp,-1,-1,where);
+              return;
+        }
+        increasing = 1;
+        mode = 1;
+
+    }
+    else if (!begin)
+    {
+        Output_TriEx(*(index+1),*(index+0),*(index+size-1),fp,-1,-1,where);
+        if (size == 4)
+        {
+            Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
+            return;
+        }
+        Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
+        increasing = 2;
+        mode = 0;
+    }
+	if (size != 4)
+	{
+		/*	We do not have a quad, we have something bigger. */
+		decreasing = size - 1;
+		
+		do
+		{
+			/*	Will be alternating diagonals, so we will be increasing
+				and decreasing around the polygon.
+			*/
+			if (mode)
+			{
+				Output_TriEx(*(index+increasing),*(index+decreasing),*(index+increasing+1),fp,-1,-1,where);
+				increasing++;
+			}
+			else
+			{
+				Output_TriEx(*(index+decreasing),*(index+increasing),*(index+decreasing-1),fp,-1,-1,where);
+                    decreasing--;
+               }
+			mode = !mode;
+		} while ((decreasing - increasing) >= 2);
+
+	}
+}
+
+
diff --git a/Stripe_w/struct.c b/Stripe_w/struct.c
new file mode 100644
index 000000000..7010012b7
--- /dev/null
+++ b/Stripe_w/struct.c
@@ -0,0 +1,549 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: struct.c
+     Contains routines that update structures, and micellaneous routines.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "polverts.h"
+#include "ties.h"
+#include "output.h"
+#include "triangulate.h"
+#include "sturcts.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+int out1 = -1;
+int out2 = -1;
+
+int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
+	        int size, int id1, int id2)
+{
+	/*	Put the edge that is adjacent to face_id into edge1
+		and edge2. For each edge see if it is adjacent to
+		face_id. Id1 and id2 is the input edge, so see if 
+		the orientation is reversed, and save it in reversed.
+	*/
+	register int x;
+	int reversed = -1;
+	BOOL set = FALSE;
+    
+     for (x=0; x< size; x++)
+	{
+		if (x == (size-1))
+		{
+			if ((*(index) == id1) && (*(index+size-1)==id2))
+			{
+				if (set)
+                         return 1;
+				reversed = 1;
+			}
+			else if ((*(index) == id2) && (*(index+size-1)==id1))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+				
+			if (Look_Up(*(index),*(index+size-1),face_id))
+			{
+				if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) &&
+                       ( (out2 == *(index)) || (out2 == *(index+size-1)) ))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				else if (out1 == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				if ((reversed != -1) && (set))  
+					return reversed;
+			}
+		}		
+		else
+		{
+			if ((*(index+x) == id1) && (*(index+x+1)==id2))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+			else if ((*(index+x) == id2) && (*(index+x+1)==id1))
+			{
+				if (set)
+					return 1;
+				reversed = 1;
+			}
+
+			if (Look_Up(*(index+x),*(index+x+1),face_id))
+			{
+				if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) &&
+                         ((out2 == *(index+x)) || (out2 == *(index+x+1))))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                         *edge2 = *(index+x+1);
+                    }
+				else if (out1 == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+				     *edge2 = *(index+x + 1);
+                    }
+				if ((reversed != -1) && (set))
+                         return reversed;
+			}
+		}
+	}			
+	if ((x == size) && (reversed != -1))
+	{
+		/*	Could not find the output edge */
+		printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2);
+		exit(0);
+	}
+	return reversed;
+}
+
+
+void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
+				 int *e2,int temp1,int temp2,int *ties)
+{
+	/*	We have a face id that needs to be decremented.
+		We have to determine where it is in the structure,
+		so that we can decrement it.
+	*/
+	/*	The number of adjacencies may have changed, so to locate
+		it may be a little tricky. However we know that the number
+		of adjacencies is less than or equal to the original number
+		of adjacencies,
+	*/
+	int y,size;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+	PLISTINFO lpListInfo;
+	static int each_poly = 0;
+	BOOL there = FALSE;
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+	{
+		/*	Size of the polygon */
+        size = temp->nPolSize;
+        /*  We did it already */
+        if (size == 1)
+            return;
+        for (y = 0; y< size; y++)
+	   {
+			/*	If we are doing partial triangulation, we must check
+				to see whether the edge is still there in the polygon,
+				since we might have done a portion of the polygon
+				and saved the rest for later.
+			*/
+            if (y != (size-1))
+	  	  {
+				if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1)))
+					|| ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+		  }
+		  else
+		  {
+				if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1)))
+					|| ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+		  }
+	 }
+		
+      if (!there)
+		/*	Original edge was already used, we cannot use this polygon */
+			return;
+		
+	/*	We have a starting point to start our search to locate
+		this polygon. 
+	*/
+
+	/*	Check to see if this polygon was done */
+	lpListInfo = Done(face_id,59,&y);
+
+	if (lpListInfo == NULL)
+		return;
+
+     /*  Was not done, but there is an error in the adjacency calculations */
+     if (y == 0)
+     {
+            printf("There is an error in finding the adjacencies\n");
+            exit(0);
+     }
+
+     /*	Now put the face in the proper bucket depending on tally. */
+	/*	First add it to the new bucket, then remove it from the old */
+	Add_Sgi_Adj(y-1,face_id);
+	RemoveList(array[y],lpListInfo);
+        
+     /*	Save it if it was the smallest seen so far since then
+		it will be the next face 
+		Here we will have different options depending on
+		what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+	*/
+	/*	At a new strip */
+	if (*next_bucket == 60)
+		*ties = *ties + each_poly;
+	/*	Have a tie */
+	if (*next_bucket == (y-1))
+	{
+		Add_Ties(face_id);
+		each_poly++;
+	}
+	/*	At a new minimum */
+	if (*next_bucket > (y-1))
+	{
+		*next_bucket = y-1;
+		*min_face = face_id;
+		*e1 = temp1;
+		*e2 = temp2;
+		each_poly = 0;
+		Clear_Ties();
+		Add_Ties(face_id);
+	}
+     }
+}
+
+
+void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, 
+			 int current_face,int *e1,int *e2,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Delete one adjacency from it. Save the min
+		adjacency seen so far.
+	*/
+	register int count=0;
+	PF_EDGES temp = NULL;
+	ListHead *pListHead;
+	int next_face;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+	/*	It could be a new edge that we created. So we can
+		exit, since there is not a face adjacent to it.
+	*/
+		return;
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	Was a new edge that was created and therefore
+				does not have anything adjacent to it
+			*/
+			return;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return;
+
+	/*	Was adjacent to something */
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Now we need to decrement this faces' adjacencies.
+	*/
+	Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
+}
+
+
+int Change_Face(int face_id,int in1,int in2,
+				 ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check)
+{
+	/*	We are doing a partial triangulation and we need to
+		put the new face of triangle into the correct bucket
+	*/
+	int input_adj,y;
+	
+	/*	Find the old number of adjacencies to this face,
+		so we know where to delete it from
+	*/
+	y = Old_Adj(face_id);
+	
+	/*	Do we need to change the adjacency? Maybe the edge on the triangle
+		that was outputted was not adjacent to anything. We know if we
+		have to check by "check". We came out on the output edge
+		that we needed, then we know that the adjacencies will decrease
+		by exactly one.
+	*/
+	if (!no_check)
+	{
+		input_adj = Number_Adj(in1,in2,face_id);
+		/*	If there weren't any then don't do anything */
+		if (input_adj == 0)
+			return y;
+	}
+
+	RemoveList(pListHead,(PLISTINFO)temp);
+	/*	Before we had a quad with y adjacencies. The in edge
+		did not have an adjacency, since it was just deleted,
+		since we came in on it. The outedge must have an adjacency
+		otherwise we would have a bucket 0, and would not be in this
+		routine. Therefore the new adjacency must be y-1
+	*/
+    
+    Add_Sgi_Adj(y-1,face_id);
+    return (y-1);
+}
+
+int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
+					   int *ties)
+{
+	/*	Give the face with id face_id, we want to decrement
+		all the faces that are adjacent to it, since we will
+		be deleting face_id from the data structure.
+		We will return the face that has the least number
+		of adjacencies.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face = -1;
+	
+     *next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+		else
+			Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+	}
+	return (min_face);
+}
+
+
+void Find_Adj_Tally(int id1, int id2,int *next_bucket,int *min_face, 
+				int current_face,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Save the min adjacency seen so far.
+	*/
+	int size,each_poly=0,y,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	int next_face;
+	BOOL there = FALSE;
+
+    
+    /*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	This was a new edge that was created, so it is
+		adjacent to nothing.
+	*/
+		return;
+
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	This was a new edge that we created */
+			return;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return;
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Find how many faces it is adjacent to.
+	*/
+	pListHead = PolFaces[next_face];
+	temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent 
+		polygons to this face. This will be the original number of
+		polygons adjacent to this polygon, we must then see if this
+		number has been decremented
+	*/	      		
+	if ( temp2 != NULL )
+	{
+		/*	Size of the polygon */
+		size = temp2->nPolSize;
+		/*  We did it already */
+          if (size == 1)
+            return;
+          for (y = 0; y< size; y++)
+		{
+			/*	Make sure that the edge is still in the
+				polygon and was not deleted, because if the edge was
+				deleted, then we used it already.
+			*/
+			if (y != (size-1))
+			{
+				if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+					|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{		
+				if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+		if (!there)
+			/*	Edge already used and deleted from the polygon*/
+			return;
+		
+		/*	See if the face was already deleted, and where
+			it is if it was not
+		*/
+		if (Done(next_face,size,&y) == NULL)
+			return;
+		
+		/*	Save it if it was the smallest seen so far since then
+			it will be the next face 
+			Here we will have different options depending on
+			what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+		*/
+		
+		/*	At a new strip */
+		if (*next_bucket == 60)
+			*ties = *ties + each_poly;
+		/*	Have a tie */
+		if (*next_bucket == (y-1))
+		{
+			Add_Ties(next_face);
+			each_poly++;
+		}
+		/*	At a new minimum */
+		if (*next_bucket > (y-1))
+		{
+			*next_bucket = y-1;
+			*min_face = next_face;
+			each_poly = 0;
+			Clear_Ties();
+			Add_Ties(next_face);
+		}
+	}
+}
+
+
+int Min_Face_Adj(int face_id, int *next_bucket, int *ties)
+{
+	/*	Used for the Partial triangulation to find the next
+		face. It will return the minimum adjacency face id
+		found at this face.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face,test_face;
+	
+	*next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Find_Adj_Tally(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,ties);
+		else
+			Find_Adj_Tally(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,ties);
+	}
+	/*    Maybe we can do better by triangulating the face, because
+          by triangulating the face we will go to a polygon of lesser
+          adjacencies
+    */
+    if (size == 4)
+    {
+         /*    Checking for a quad whether to do the whole polygon will
+               result in better performance because the triangles in the polygon
+               have less adjacencies
+         */
+         Check_In_Quad(face_id,&test_face);
+         if (*next_bucket > test_face)
+              /*    We can do better by going through the polygon */
+              min_face = face_id;
+    }
+
+    /*  We have a polygon with greater than 4 sides, check to see if going
+        inside is better than going outside the polygon for the output edge.
+    */
+    else
+    {
+        Check_In_Polygon(face_id,&test_face,size);
+        if (*next_bucket > test_face)
+            /*  We can do better by going through the polygon */
+            min_face = face_id;
+    }
+    
+    return (min_face);
+}
+
+
+
diff --git a/Stripe_w/structex.c b/Stripe_w/structex.c
new file mode 100644
index 000000000..70359ddc0
--- /dev/null
+++ b/Stripe_w/structex.c
@@ -0,0 +1,553 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: structex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "polverts.h"
+#include "ties.h"
+#include "outputex.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+int out1Ex = -1;
+int out2Ex = -1;
+
+int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
+			int size, int id1, int id2)
+{
+	/*	Put the edge that is adjacent to face_id into edge1
+		and edge2. For each edge see if it is adjacent to
+		face_id. Id1 and id2 is the input edge, so see if 
+		the orientation is reversed, and save it in reversed.
+	*/
+	int x;
+	int reversed = -1;
+	BOOL set = FALSE;
+
+     for (x=0; x< size; x++)
+	{
+		if (x == (size-1))
+		{
+			if ((*(index) == id1) && (*(index+size-1)==id2))
+			{
+				if (set)
+                         return 1;
+				reversed = 1;
+			}
+			else if ((*(index) == id2) && (*(index+size-1)==id1))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+				
+			if (Look_Up(*(index),*(index+size-1),face_id))
+			{
+				if ( (out1Ex != -1) && ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) &&
+                       ( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) ))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				else if (out1Ex == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+				if ((reversed != -1) && (set))  
+					return reversed;
+			}
+		}		
+		else
+		{
+			if ((*(index+x) == id1) && (*(index+x+1)==id2))
+			{
+				if (set)
+                         return 0;
+				reversed = 0;
+			}
+			else if ((*(index+x) == id2) && (*(index+x+1)==id1))
+			{
+				if (set)
+					return 1;
+				reversed = 1;
+			}
+
+			if (Look_Up(*(index+x),*(index+x+1),face_id))
+			{
+				if ( (out1Ex != -1) && ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) &&
+                        ((out2Ex == *(index+x)) || (out2Ex == *(index+x+1))))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                         *edge2 = *(index+x+1);
+                    }
+				else if (out1Ex == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+				     *edge2 = *(index+x + 1);
+                    }
+				if ((reversed != -1) && (set))
+                         return reversed;
+			}
+		}
+	}			
+	if ((x == size) && (reversed != -1))
+	{
+		/*	Could not find the output edge */
+		printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex);
+		exit(0);
+	}
+	return reversed;
+}
+
+
+void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
+			    int *e2,int temp1,int temp2,int *ties)
+{
+	/*	We have a face id that needs to be decremented.
+		We have to determine where it is in the structure,
+		so that we can decrement it.
+	*/
+	/*	The number of adjacencies may have changed, so to locate
+		it may be a little tricky. However we know that the number
+		of adjacencies is less than or equal to the original number
+		of adjacencies,
+	*/
+	int y,size;
+	ListHead *pListHead;
+	PF_FACES temp = NULL;
+	PLISTINFO lpListInfo;
+	static int each_poly = 0;
+	BOOL there = FALSE;
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent
+		polygons to this face. 
+	*/	      		
+	if ( temp != NULL )
+	{
+		/*	Size of the polygon */
+        size = temp->nPolSize;
+        for (y = 0; y< size; y++)
+		{
+			/*	If we are doing partial triangulation, we must check
+				to see whether the edge is still there in the polygon,
+				since we might have done a portion of the polygon
+				and saved the rest for later.
+			*/
+               if (y != (size-1))
+			{
+				if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1)))
+					|| ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{
+				if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1)))
+					|| ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+          if (!there)
+		/*	Original edge was already used, we cannot use this polygon */
+			return;
+		
+		/*	We have a starting point to start our search to locate
+			this polygon. 
+		*/
+
+		/*	Check to see if this polygon was done */
+		lpListInfo = Done(face_id,59,&y);
+
+		if (lpListInfo == NULL)
+			return;
+
+          /*  Was not done, but there is an error in the adjacency calculations */
+          /*     If more than one edge is adj to it then maybe it was not updated */
+          if (y == 0)
+            return;
+			
+		/*	Now put the face in the proper bucket depending on tally. */
+		/*	First add it to the new bucket, then remove it from the old */
+		Add_Sgi_Adj(y-1,face_id);
+		RemoveList(array[y],lpListInfo);
+        
+          /*	Save it if it was the smallest seen so far since then
+			it will be the next face 
+			Here we will have different options depending on
+			what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+		*/
+		/*	At a new strip */
+		if (*next_bucket == 60)
+			*ties = *ties + each_poly;
+		/*	Have a tie */
+		if (*next_bucket == (y-1))
+		{
+			Add_Ties(face_id);
+			each_poly++;
+		}
+		/*	At a new minimum */
+		if (*next_bucket > (y-1))
+		{
+			*next_bucket = y-1;
+			*min_face = face_id;
+			*e1 = temp1;
+			*e2 = temp2;
+			each_poly = 0;
+			Clear_Ties();
+			Add_Ties(face_id);
+		}
+	}
+}
+
+
+void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, 
+				int current_face,int *e1,int *e2,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Delete one adjacency from it. Save the min
+		adjacency seen so far.
+	*/
+	register int count=0;
+	PF_EDGES temp = NULL;
+	ListHead *pListHead;
+	int next_face;
+
+	/*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+	/*	It could be a new edge that we created. So we can
+		exit, since there is not a face adjacent to it.
+	*/
+		return;
+     while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	Was a new edge that was created and therefore
+				does not have anything adjacent to it
+			*/
+			return;
+    }
+	/*	Was not adjacent to anything else except itself */
+    if (temp->edge[2] == -1)
+		return;
+
+    /*	Was adjacent to something */
+    else
+    {
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Now we need to decrement this faces' adjacencies.
+	*/
+	Update_FaceEx(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
+}
+
+int Change_FaceEx(int face_id,int in1,int in2,
+				 ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check)
+{
+	/*	We are doing a partial triangulation and we need to
+		put the new face of triangle into the correct bucket
+	*/
+	int input_adj,y;
+     P_ADJACENCIES pfNode,lpListInfo;
+	
+     /*	Find the old number of adjacencies to this face,
+		so we know where to delete it from
+	*/
+	y = Old_Adj(face_id);
+	pListHead = array[y];
+
+     pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+	if ( pfNode )
+		pfNode->face_id = face_id;
+	lpListInfo = (P_ADJACENCIES) (SearchList(array[y], pfNode,
+                  (int (*)(void *,void *)) (Compare)));
+	if (lpListInfo == NULL)
+	{
+		printf("There is an error finding the next polygon3 %d\n",face_id);
+		exit(0);
+	}
+
+     /*	Do we need to change the adjacency? Maybe the edge on the triangle
+		that was outputted was not adjacent to anything. We know if we
+		have to check by "check". We came out on the output edge
+		that we needed, then we know that the adjacencies will decrease
+		by exactly one.
+	*/
+	if (!no_check)
+	{
+		input_adj = Number_Adj(in1,in2,face_id);
+		/*	If there weren't any then don't do anything */
+		if (input_adj == 0)
+			return y;
+	}
+     
+	RemoveList(pListHead,(PLISTINFO)/*(temp*/lpListInfo);
+	/*	Before we had a quad with y adjacencies. The in edge
+		did not have an adjacency, since it was just deleted,
+		since we came in on it. The outedge must have an adjacency
+		otherwise we would have a bucket 0, and would not be in this
+		routine. Therefore the new adjacency must be y-1
+	*/
+    
+    Add_Sgi_Adj(y-1,face_id);
+    return (y-1);
+}
+
+int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2,
+					int *ties)
+{
+	/*	Give the face with id face_id, we want to decrement
+		all the faces that are adjacent to it, since we will
+		be deleting face_id from the data structure.
+		We will return the face that has the least number
+		of adjacencies.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face = -1;
+	
+     *next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Delete_AdjEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+		else
+			Delete_AdjEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,e1,e2,ties);
+	}
+	return (min_face);
+}
+
+
+
+void Find_Adj_TallyEx(int id1, int id2,int *next_bucket,int *min_face, 
+			       int current_face,int *ties)
+{
+	/*	Find the face that is adjacent to the edge and is not the
+		current face. Save the min adjacency seen so far.
+	*/
+	int size,each_poly=0,y,tally=0,count=0;
+	PF_EDGES temp = NULL;
+	PF_FACES temp2 = NULL;
+	ListHead *pListHead;
+	int next_face;
+	BOOL there = FALSE;
+
+    
+    /*	Always want smaller id first */
+	switch_lower(&id1,&id2);
+	
+	pListHead = PolEdges[id1];
+	temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*	This was a new edge that was created, so it is
+		adjacent to nothing.
+	*/
+		return;
+	while (temp->edge[0] != id2)
+     {
+		count++;
+		temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+			/*	This was a new edge that we created */
+			return;
+     }
+	/*	Was not adjacent to anything else except itself */
+	if (temp->edge[2] == -1)
+		return;
+	else
+	{
+		if (temp->edge[2] == current_face)
+			next_face =  temp->edge[1];
+		else 
+			next_face = temp->edge[2];
+	}
+	/*	We have the other face adjacent to this edge, it is 
+		next_face. Find how many faces it is adjacent to.
+	*/
+	pListHead = PolFaces[next_face];
+	temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	/*	Check each edge of the face and tally the number of adjacent 
+		polygons to this face. This will be the original number of
+		polygons adjacent to this polygon, we must then see if this
+		number has been decremented
+	*/	      		
+	if ( temp2 != NULL )
+	{
+		/*	Size of the polygon */
+		size = temp2->nPolSize;
+		for (y = 0; y< size; y++)
+		{
+			/*	Make sure that the edge is still in the
+				polygon and was not deleted, because if the edge was
+				deleted, then we used it already.
+			*/
+			if (y != (size-1))
+			{
+				if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+					|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+			else
+			{		
+				if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+					|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+					/*	edge is still there we are ok */
+					there = TRUE;
+			}
+		}
+		
+		if (!there)
+			/*	Edge already used and deleted from the polygon*/
+			return;
+		
+		/*	See if the face was already deleted, and where
+			it is if it was not
+		*/
+		if (Done(next_face,size,&y) == NULL)
+			return;
+		
+		/*	Save it if it was the smallest seen so far since then
+			it will be the next face 
+			Here we will have different options depending on
+			what we want for resolving ties:
+			1) First one we see we will use
+			2) Random resolving
+			3) Look ahead
+			4) Alternating direction
+		*/
+					
+		/*	At a new strip */
+		if (*next_bucket == 60)
+			*ties = *ties + each_poly;
+		/*	Have a tie */
+		if (*next_bucket == (y-1))
+		{
+			Add_Ties(next_face);
+			each_poly++;
+		}
+		/*	At a new minimum */
+		if (*next_bucket > (y-1))
+		{
+			*next_bucket = y-1;
+			*min_face = next_face;
+			each_poly = 0;
+			Clear_Ties();
+			Add_Ties(next_face);
+		}
+	}
+}
+
+
+int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties)
+{
+	/*	Used for the Partial triangulation to find the next
+		face. It will return the minimum adjacency face id
+		found at this face.
+	*/
+	PF_FACES temp = NULL;
+	ListHead *pListHead;
+	int size,y,min_face,test_face;
+	
+	*next_bucket = 60;
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	
+	if ( temp == NULL )
+	{
+		printf("The face was already deleted, there is an error\n");
+		exit(0);
+	}
+	
+	/*	Size of the polygon */
+	size = temp->nPolSize;
+	for (y = 0; y< size; y++)
+	{
+		if (y != (size-1))
+			Find_Adj_TallyEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+				next_bucket,&min_face,face_id,ties);
+		else
+			Find_Adj_TallyEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+				next_bucket,&min_face,face_id,ties);
+	}
+	/*    Maybe we can do better by triangulating the face, because
+          by triangulating the face we will go to a polygon of lesser
+          adjacencies
+    */
+    if (size == 4)
+    {
+         /*    Checking for a quad whether to do the whole polygon will
+               result in better performance because the triangles in the polygon
+               have less adjacencies
+         */
+         Check_In_Quad(face_id,&test_face);
+         if (*next_bucket > test_face)
+              /*    We can do better by going through the polygon */
+              min_face = face_id;
+    }
+
+    /*  We have a polygon with greater than 4 sides, check to see if going
+        inside is better than going outside the polygon for the output edge.
+    */
+    else
+    {
+        Check_In_Polygon(face_id,&test_face,size);
+        if (*next_bucket > test_face)
+            /*  We can do better by going through the polygon */
+            min_face = face_id;
+    }
+    
+    return (min_face);
+}
+
+
diff --git a/Stripe_w/sturcts.h b/Stripe_w/sturcts.h
new file mode 100644
index 000000000..57490a695
--- /dev/null
+++ b/Stripe_w/sturcts.h
@@ -0,0 +1,36 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sturcts.h
+-----------------------------------------------------------------------*/
+
+#define EVEN(x) (((x) & 1) == 0)
+
+int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
+	     int size, int id1, int id2);
+void add_vert_id();
+void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
+		 int *e2,int temp1,int temp2,int *ties);
+int Min_Adj();
+int Min_Face_Adj(int face_id, int *next_bucket, int *ties);
+int Change_Face(int face_id,int in1,int in2, ListHead *pListHead, 
+		P_ADJACENCIES temp, BOOL no_check);
+void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, 
+		int current_face,int *e1,int *e2,int *ties);
+int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
+		       int *ties);
+int Get_Output_Edge();
+int Find_Face();
+
+
+
+
+
+
+
diff --git a/Stripe_w/sturctsex.h b/Stripe_w/sturctsex.h
new file mode 100644
index 000000000..6a4a76dbe
--- /dev/null
+++ b/Stripe_w/sturctsex.h
@@ -0,0 +1,33 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:sturctsex.h
+-----------------------------------------------------------------------*/
+
+#define EVEN(x) (((x) & 1) == 0)
+
+int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
+	       int size, int id1, int id2);
+void add_vert_idEx();
+void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
+		   int *e2,int temp1,int temp2,int *ties);
+int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties);
+int Change_FaceEx(int face_id,int in1,int in2,
+		  ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check);
+void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, 
+		  int current_face,int *e1,int *e2,int *ties);
+int Number_AdjEx();
+int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2,
+			 int *ties);
+
+
+
+
+
+
diff --git a/Stripe_w/ties.c b/Stripe_w/ties.c
new file mode 100644
index 000000000..e3fd31f78
--- /dev/null
+++ b/Stripe_w/ties.c
@@ -0,0 +1,304 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*	STRIPE: ties.c
+     This file will contain all the routines used to determine the next face if there
+	is a tie
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "ties.h"
+#include "sturctsex.h"
+#include "triangulatex.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+#define MAX_TIE 60
+int ties_array[60];
+int last = 0;
+
+void Clear_Ties()
+{
+	/*	Clear the buffer, because we do not have the tie
+		any more that we had before */
+	last = 0;
+}
+
+void Add_Ties(int id)
+{
+	/*	We have a tie to add to the buffer */
+	ties_array[last++] = id;
+}
+
+int Alternate_Tie()
+{
+	/*	Alternate in what we choose to break the tie 
+		We are just alternating between the first and
+		second thing that we found
+	*/
+	static int x = 0;
+	register int t;
+	
+	t = ties_array[x];
+	x++;
+	if (x == 2)
+		x = 0;
+	return t;
+}
+
+int Random_Tie()
+{
+	/*	Randomly choose the next face with which
+		to break the tie
+	*/
+	register int num;
+
+	num = rand();
+	while (num >= last)
+		num = num/20;
+	return (ties_array[num]);
+}
+
+int Look_Ahead(int id)
+{
+	/*	Look ahead at this face and save the minimum
+		adjacency of all the faces that are adjacent to
+		this face.
+	*/
+	return Min_Adj(id);
+}
+
+int Random_Look(int id[],int count)
+{
+	/*	We had a tie within a tie in the lookahead, 
+		break it randomly 
+	*/
+	register int num;
+
+	num = rand();
+	while (num >= count)
+		num = num/20;
+	return (id[num]);
+}
+
+
+int Look_Ahead_Tie()
+{
+	/*	Look ahead and find the face to go to that
+		will give the least number of adjacencies
+	*/
+	int id[60],t,x,f=0,min = 60;
+
+	for (x = 0; x < last; x++)
+	{
+		t = Look_Ahead(ties_array[x]);
+		/*	We have a tie */
+		if (t == min)
+			id[f++] = ties_array[x];
+		if (t < min)
+		{
+			f = 0;
+			min = t;
+			id[f++] = ties_array[x];
+		}
+	}
+	/*	No tie within the tie */
+	if ( f == 1)
+		return id[0];
+	/*	Or ties, but we are at the end of strips */
+	if (min == 0)
+		return id[0];
+	return (Random_Look(id,f));
+}
+
+
+int Sequential_Tri(int *index)
+{
+    /*  We have a triangle and need to break the ties at it.
+        We will choose the edge that is sequential. There
+        is definitely one since we know we have a triangle
+        and that there is a tie and there are only 2 edges
+        for the tie.
+    */
+    int e1,e2,e3,output1,output2,output3,output4;
+
+    /*  e2 and e3 are the input edge to the triangle */
+    Last_Edge(&e1,&e2,&e3,0);
+    
+    if ((e2 == 0) && (e3 == 0))
+        /*  Starting the strip, don't need to do this */
+        return ties_array[0];
+
+    /*  For the 2 ties find the edge adjacent to face id */
+    Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
+    Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0);
+
+    if ((output1 == e3) || (output2 == e3))
+        return ties_array[0];
+    if ((output3 == e3) || (output4 == e3))
+        return ties_array[1];
+    printf("There is an error trying to break sequential triangle \n");
+}
+
+int Sequential_Quad(int *index,	int triangulate)
+{
+    /*  We have a quad that need to break its ties, we will try
+        and choose a side that is sequential, otherwise use lookahead
+    */
+    int output1,output2,x,e1,e2,e3;
+
+    /*  e2 and e3 are the input edge to the quad */
+    Last_Edge(&e1,&e2,&e3,0);
+
+    /*  No input edge */
+    if ((e2 == 0) && (e3 == 0))
+        return ties_array[0];
+
+	/*  Go through the ties and see if there is a sequential one */
+    for (x = 0; x < last; x++)
+	{
+        Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0);
+        /*  Partial and whole triangulation will have different requirements */
+        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
+            return ties_array[x];
+        if (((output1 != e3) && (output1 != e2) &&
+                (output2 != e3) && (output2 != e2)))
+            return ties_array[x];
+    }
+    /*  There was not a tie that was sequential */
+	return Look_Ahead_Tie();
+}
+
+void Whole_Output(int in1,int in2, int *index, int size, int *out1, int *out2)
+{
+    /*  Used to sequentially break ties in the whole triangulation for polygons
+        greater than 4 sides. We will find the output edge that is good
+        for sequential triangulation.
+    */
+
+    int half;
+    
+    /*  Put the input edge first in the list */
+    Rearrange_IndexEx(index,size);
+
+    if (!(EVEN(size)))
+    {
+        if (*(index) == in1)
+            half = size/2 ;
+        else
+            half = size/2 +1;
+    }
+    else
+        half = size/2;
+
+    *out1 = *(index+half);
+    *out2 = *(index+half+1);
+}
+
+int Sequential_Poly(int size, int *index, int triangulate)
+{
+    /*  We have a polygon of greater than 4 sides and wish to break the
+        tie in the most sequential manner.
+    */
+
+    int x,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4;
+    
+    /*  e2 and e3 are the input edge to the quad */
+    Last_Edge(&e1,&e2,&e3,0);
+
+    /*  If we are using whole, find the output edge that is sequential */
+    if (triangulate == WHOLE)
+        Whole_Output(e2,e3,index,size,&output3,&output4);
+
+    /*  No input edge */
+    if ((e2 == 0) && (e3 == 0))
+        return ties_array[0];
+    
+    for (x = 0; x < last ; x++)
+    {
+        Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0);
+        /*  Partial that can be removed in just one triangle */
+        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
+            saved1 = ties_array[x];
+        /*  Partial removed in more than one triangle */
+        if ((output1 != e3) && (output1 != e2) && (output2 != e3) && (output2 != e2) &&
+            (triangulate == PARTIAL) && (saved2 != -1))
+            saved2 = ties_array[x];
+        /*  Whole is not so easy, since the whole polygon must be done. Given
+            an input edge there is only one way to come out, approximately half
+            way around the polygon.
+        */
+        if (((output1 == output3) && (output2 == output4)) ||
+            ((output1 == output4) && (output2 == output3)) &&
+            (triangulate == WHOLE))
+            return ties_array[x];
+    }
+    
+    if (saved1 != -1)
+        return saved1;
+    if (saved2 != -1)
+        return saved2;
+    
+    /*  There was not a tie that was sequential */
+    return Look_Ahead_Tie();
+}
+
+int Sequential_Tie(int face_id, int triangulate)
+{
+    /*  Break the tie by choosing the face that will
+        not give us a swap and is sequential. If there
+        is not one, then do the lookahead to break the
+        tie.
+    */
+    /*  Separate into 3 cases for simplicity, if the current
+        polygon has 3 sides, 4 sides or if the sides were 
+        greater. We can do the smaller cases faster, so that
+        is why I separated the cases.
+    */
+
+     ListHead *pListFace;
+	PF_FACES face;
+
+    /*	Get the polygon with id face_id */
+	pListFace  = PolFaces[face_id];
+	face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     if (face->nPolSize == 3)
+        return(Sequential_Tri(face->pPolygon));
+     if (face->nPolSize == 4)
+        return(Sequential_Quad(face->pPolygon,triangulate));
+     else
+        return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate));
+
+}
+
+int Get_Next_Face(int t, int face_id, int triangulate)
+{
+	/*	Get the next face depending on what
+		the user specified
+	*/
+	
+	/*	Did not have a tie, don't do anything */
+	if (last == 1)
+		return(ties_array[0]);
+	if (t == RANDOM)
+		return Random_Tie();
+	if (t == ALTERNATE)
+		return Alternate_Tie();
+	if (t == LOOK)
+		return Look_Ahead_Tie();
+     if (t == SEQUENTIAL)
+        return Sequential_Tie(face_id,triangulate);
+
+	printf("Illegal option specified for ties, using first \n");
+     return (ties_array[0]);
+}
diff --git a/Stripe_w/ties.h b/Stripe_w/ties.h
new file mode 100644
index 000000000..502aabf4d
--- /dev/null
+++ b/Stripe_w/ties.h
@@ -0,0 +1,15 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: ties.h
+-----------------------------------------------------------------------*/
+
+void Clear_Ties();
+void Add_Ties(int id);
+int Get_Next_Face(int t, int face_id, int triangulate);
diff --git a/Stripe_w/triangulate.h b/Stripe_w/triangulate.h
new file mode 100644
index 000000000..1f677430a
--- /dev/null
+++ b/Stripe_w/triangulate.h
@@ -0,0 +1,27 @@
+
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: triangulate.h
+-----------------------------------------------------------------------*/
+
+void Blind_Triangulate(int size, int *index, FILE *output,
+		       BOOL begin, int where ,int color1,int color2,
+                       int color3);
+void Non_Blind_Triangulate(int size,int *index, FILE *output,
+			   int next_face_id,int face_id,int where,
+                           int color1,int color2,int color3);
+int Adjacent(int id2,int id1, int *list, int size);
+void Delete_From_List(int id,int *list, int *size);
+void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1,
+			 int in_edge2, int size, int *index,
+			 FILE *output, int reversed, int face_id,
+                         int where, int color1, int color2, int color3);
+void Rearrange_Index(int *index, int size);
+void Find_Local_Strips();
diff --git a/Stripe_w/triangulatex.h b/Stripe_w/triangulatex.h
new file mode 100644
index 000000000..3b2d8fb5c
--- /dev/null
+++ b/Stripe_w/triangulatex.h
@@ -0,0 +1,28 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: triangulatex.h
+-----------------------------------------------------------------------*/
+
+enum swap_type
+{ ON, OFF};
+
+void SGI_StripEx();
+void Blind_TriangulateEx(int size, int *index, FILE *fp, FILE *output, 
+			 BOOL begin, int where );
+void Non_Blind_TriangulateEx(int size,int *index, FILE *fp, FILE *output,
+			     int next_face_id,int face_id,int where);
+int AdjacentEx(int id2,int id1, int *list, int size);
+void Delete_From_ListEx(int id,int *list, int size);
+void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1,
+			   int in_edge2,int size,int *index,
+			   FILE *output,FILE *fp,int reversed,int face_id,
+                           int where);
+void Rearrange_IndexEx(int *index, int size);
+void Find_StripsEx();
diff --git a/Stripe_w/util.c b/Stripe_w/util.c
new file mode 100644
index 000000000..f17fe5f7c
--- /dev/null
+++ b/Stripe_w/util.c
@@ -0,0 +1,272 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: util.c
+     This file contains routines that are used for various functions
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+#include "polverts.h"
+
+void switch_lower (int *x, int *y)
+{
+	register int temp;
+	
+	/*	Put lower value in x */
+	if (*y < *x)
+	{
+		temp = *x;
+		*x = *y;
+		*y = temp;
+	}
+}
+
+BOOL member(int x , int id1, int id2, int id3)
+{
+    /*  Is x in the triangle specified by id1,id2,id3 */
+    if ((x != id1) && (x != id2) && (x != id3))
+	return FALSE;
+    return TRUE;
+}
+
+
+int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2)
+{
+	/*	This will only return whether 2 adjacency nodes
+		are equivalent.								  
+	*/
+	if (node1->face_id == node2->face_id)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+
+BOOL Exist(int face_id, int id1, int id2)
+{
+	/*	Does the edge specified by id1 and id2 exist in this
+		face currently? Maybe we deleted in partial triangulation
+	*/
+	ListHead *pListHead;
+	PF_FACES temp;
+	register int x,size;
+	BOOL a=FALSE,b =FALSE; 
+
+	pListHead = PolFaces[face_id];
+	temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+	size = temp->nPolSize;
+	for (x=0; x<size; x++)
+	{
+		if (*(temp->pPolygon+x) == id1)
+			a = TRUE;
+		if (*(temp->pPolygon+x) == id2)
+			b = TRUE;
+		if (a && b)
+			return TRUE;
+	}
+	return FALSE;
+}
+
+int Get_Next_Id(int *index,int e3, int size)
+{
+    /*  Return the id following e3 in the list of vertices */
+
+    register int x;
+
+    for (x = 0; x< size; x++)
+    {
+        if ((*(index+x) == e3) && (x != (size-1)))
+            return *(index+x+1);
+        else if (*(index+x) == e3)
+            return *(index);
+    }
+    printf("There is an error in the next id\n");
+    exit(0);
+}
+
+int Different (int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y)
+{
+    /*    Find the vertex in the first 3 numbers that does not exist in 
+	     the last three numbers
+    */
+    if ((id1 != id4) && (id1 != id5) && (id1 != id6))
+    {
+	*x = id2;
+	*y = id3;
+	return id1;
+    }
+    if ((id2 != id4) && (id2 != id5) && (id2 != id6))
+    {
+	*x = id1;
+	*y = id3;
+	return id2;
+    }
+    if ((id3 != id4) && (id3 != id5) && (id3 != id6))
+    {
+	*x = id1;
+	*y = id2;
+	return id3;
+    }
+    
+    /*  Because there are degeneracies in the data, this might occur */
+    *x = id5;
+    *y = id6;
+    return id4;
+}
+
+int Return_Other(int *index,int e1,int e2)
+{
+	/*   We have a triangle and want to know the third vertex of it */
+	register int x;
+
+	for (x=0;x<3;x++)
+	{
+		if ((*(index+x) != e1) && (*(index+x) != e2))
+			return *(index+x);
+	}
+     /*   If there is a degenerate triangle return arbitrary */
+     return e1;
+}
+
+int Get_Other_Vertex(int id1,int id2,int id3,int *index)
+{
+	/*	We have a list index of 4 numbers and we wish to
+          return the number that is not id1,id2 or id3
+	*/
+	register int x;
+
+	for (x=0; x<4; x++)
+	{
+		if ((*(index+x) != id1) && (*(index+x) != id2) &&
+			(*(index+x) != id3))
+			return *(index+x);
+	}
+	/*   If there is some sort of degeneracy this might occur,
+          return arbitrary 
+     */
+     if (x==4)
+          return id1;
+}
+
+
+PLISTINFO Done(int face_id, int size, int *bucket)
+{
+	/*	Check to see whether the polygon with face_id was used
+		already, return NULL if it was, otherwise return a pointer to the face.
+	*/
+	P_ADJACENCIES pfNode;
+	register int y;
+	PLISTINFO lpListInfo;
+	
+	pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+	if ( pfNode )
+		pfNode->face_id = face_id;
+		
+	for (y=size; ; y--)
+	{
+		lpListInfo = SearchList(array[y], pfNode,
+			(int (*)(void *,void *)) (Compare));
+		if (lpListInfo != NULL)
+		{
+			*bucket = y;
+			return lpListInfo;
+		}
+		if (y == 0)
+		/*	This adjacent face was done already */
+			return lpListInfo;
+	}
+	free (pfNode);
+}
+
+void Output_Edge(int *index,int e2,int e3,int *output1,int *output2)
+{
+    /*  Given a quad and an input edge return the other 2 vertices of the
+        quad.
+    */
+    
+    *output1 = -1;
+    *output2 = -1;
+
+    if ((*(index) != e2) && (*(index) != e3))
+        *output1 = *(index);
+
+    if ((*(index+1) != e2) && (*(index+1) != e3))
+    {
+        if (*output1 == -1)
+            *output1 = *(index+1);
+        else
+        {
+            *output2 = *(index+1);
+            return;
+        }
+    }
+
+    if ((*(index+2) != e2) && (*(index+2) != e3))
+    {
+        if (*output1 == -1)
+            *output1 = *(index+2);
+        else
+        {
+            *output2 = *(index+2);
+            return;
+        }
+    }
+
+    *output2 = *(index+3);
+}
+
+
+void First_Edge(int *id1,int *id2, int *id3)
+{
+    /*  Get the first triangle in the strip we just found, we will use this to
+	   try to extend backwards in the strip
+    */
+
+    ListHead *pListHead;
+    register int num;
+    P_STRIPS temp1,temp2,temp3;
+	 
+    pListHead = strips[0];
+    num = NumOnList(pListHead);
+     
+    /*    Did not have a strip */
+    if (num < 3)
+         return;
+	  
+    temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
+    temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
+    temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
+    *id1 = temp1->face_id;
+    *id2 = temp2->face_id;
+    *id3 = temp3->face_id;
+ 
+}
+
+void Last_Edge(int *id1, int *id2, int *id3, BOOL save)
+{
+	/*   We need the last edge that we had  */
+	static int v1, v2, v3;
+
+	if (save)
+	{
+		v1 = *id1;
+		v2 = *id2;
+		v3 = *id3;
+	}
+	else
+	{
+		*id1 = v1;
+		*id2 = v2;
+		*id3 = v3;
+	}
+}
+
+
diff --git a/Stripe_w/util.h b/Stripe_w/util.h
new file mode 100644
index 000000000..64c2f2334
--- /dev/null
+++ b/Stripe_w/util.h
@@ -0,0 +1,24 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: util.h
+-----------------------------------------------------------------------*/
+
+void switch_lower (int *x, int *y);
+int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2);
+BOOL Exist(int face_id, int id1, int id2);
+int Get_Next_Id(int *index,int e3, int size);
+int Different(int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y);
+int Return_Other(int *index,int e1,int e2);
+int Get_Other_Vertex(int id1,int id2,int id3,int *index);
+PLISTINFO Done(int face_id, int size, int *bucket);
+void Output_Edge(int *index,int e2,int e3,int *output1,int *output2);
+void Last_Edge(int *id1, int *id2, int *id3, BOOL save);
+void First_Edge(int *id1,int *id2, int *id3);
+BOOL member(int x , int id1, int id2, int id3);

From 4e827cd7dfb5b44dfa5e96ab9799f50361cbf096 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 6 Aug 1998 12:47:59 +0000
Subject: [PATCH 129/283] Removed overlap in tiles as a test.

---
 AssemTris/assemtris.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index ed42f8087..2eb891784 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -365,6 +365,8 @@ void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
     double n[3];
     char line[256];
 
+    offset_lon = offset_lat = 0.0;
+
     while ( fgets(line, 250, fp) != NULL ) {
 	if ( strncmp(line, "gdn ", 4) == 0 ) {
 	    sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]);
@@ -529,9 +531,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.10  1998/07/21 04:34:20  curt
-/* Mods to handle extra nodes (i.e. preserve cutouts).
+/* Revision 1.11  1998/08/06 12:47:59  curt
+/* Removed overlap in tiles as a test.
 /*
+ * Revision 1.10  1998/07/21 04:34:20  curt
+ * Mods to handle extra nodes (i.e. preserve cutouts).
+ *
  * Revision 1.9  1998/07/04 00:55:39  curt
  * typedef'd struct fgBUCKET.
  *

From 7744be1d60b34cee36bfacb9cdc8c5f44d3d9983 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 24 Aug 1998 20:03:31 +0000
Subject: [PATCH 130/283] Eliminated a possible memory overrun error. Use the
 proper free() rather than the incorrect delete().

---
 DEM/dem.cxx | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index e47906808..13bd4ea0b 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -207,7 +207,7 @@ static int next_exp(gzFile fd) {
 int fgDEM::read_a_record( void ) {
     int i, inum;
     double dnum;
-    char name[144];
+    char name[256];
     char token[80];
     char *ptr;
 
@@ -819,12 +819,16 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
 
 fgDEM::~fgDEM( void ) {
     // printf("class fgDEM DEstructor called.\n");
-    free(dem_data);
-    free(output_data);
+    delete(dem_data);
+    delete(output_data);
 }
 
 
 // $Log$
+// Revision 1.12  1998/08/24 20:03:31  curt
+// Eliminated a possible memory overrun error.
+// Use the proper free() rather than the incorrect delete().
+//
 // Revision 1.11  1998/07/20 12:46:11  curt
 // When outputing to a .node file, first check for an optional
 // "index.node.ex" file in case there is a .poly file to go along with this

From c9d460db0681d10bd851e1b836bc4fb89bdcec31 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 26 Aug 1998 22:31:29 +0000
Subject: [PATCH 131/283] Write out version and "meta" info into each dem's
 subdirectory containing all the tiles.

---
 Tools/process-dem.pl | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 2f9f72be9..a38be6d8d 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -26,6 +26,9 @@
 #---------------------------------------------------------------------------
 
 
+# format version number
+$scenery_format_version = "0.1";
+
 $max_area = 10000;            # maximum triangle area
 $remove_tmps = 0;
 
@@ -133,6 +136,15 @@ sub dem2node {
 	    $subdir =~ s/^Dir = //;
 	    chop($subdir);
 	}
+	if ( m/Quad name field/ ) {
+	    $quad_name = $_;
+	    # strip header
+	    $quad_name =~ s/.*Quad name field: //;
+	    # crunch consequetive spaces
+	    $quad_name =~ s/  +/ /g;
+	    chop($quad_name);
+	    print "QUAD NAME = $quad_name\n";
+	}
     }
     close(OUT);
 } 
@@ -429,6 +441,18 @@ sub install {
     print "Install dir = $install_dir\n";
     system("mkdir -p $install_dir");
 
+    # write out version and info record
+    open(VERSION, ">$install_dir/VERSION") || 
+	die "Cannot open $install_dir/VERSION for writing\n";
+    print VERSION "FGFS Scenery Version $scenery_format_version\n";
+    $date = `date`; chop($date);
+    print VERSION "Created by $ENV{LOGNAME} on $date\n";
+    print VERSION "\n";
+    print VERSION "DEM File Name = $dem_file\n";
+    print VERSION "DEM Label = $quad_name\n";
+    print VERSION "Error Tolerance = $error (this value is squared)\n";
+    close(VERSION);
+
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	chop($file);
@@ -454,6 +478,10 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.26  1998/08/26 22:31:29  curt
+# Write out version and "meta" info into each dem's subdirectory containing
+# all the tiles.
+#
 # Revision 1.25  1998/07/22 21:46:09  curt
 # minor tweaks.
 #

From 96a0774d3fab86f7dba443dc63f47588fa1e3b97 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 1 Sep 1998 19:34:32 +0000
Subject: [PATCH 132/283] Initial revision.

---
 GenAirports/Makefile.am |  61 +++++++++++
 GenAirports/area.cxx    | 232 +++++++++++++++++++++++++++++++++++++++
 GenAirports/area.hxx    |  63 +++++++++++
 GenAirports/main.cxx    | 236 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 592 insertions(+)
 create mode 100644 GenAirports/Makefile.am
 create mode 100644 GenAirports/area.cxx
 create mode 100644 GenAirports/area.hxx
 create mode 100644 GenAirports/main.cxx

diff --git a/GenAirports/Makefile.am b/GenAirports/Makefile.am
new file mode 100644
index 000000000..a5d9d981c
--- /dev/null
+++ b/GenAirports/Makefile.am
@@ -0,0 +1,61 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started January 1998.
+#
+# Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+bin_PROGRAMS = genapts
+
+genapts_SOURCES = area.cxx area.hxx main.cxx
+
+genapts_LDADD = \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/zlib/libz.a
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1998/09/01 19:34:32  curt
+# Initial revision.
+#
+# Revision 1.2  1998/07/30 23:49:18  curt
+# Removed libtool support.
+#
+# Revision 1.1  1998/07/20 12:54:53  curt
+# Whoops, need to commit Makefile.am, not Makefile.
+#
+# Revision 1.2  1998/04/14 02:25:59  curt
+# Code reorganizations.  Added a Lib/ directory for more general libraries.
+#
+# Revision 1.1  1998/04/08 22:54:57  curt
+# Adopted Gnu automake/autoconf system.
+#
+# Revision 1.2  1998/01/21 02:55:46  curt
+# Incorporated new make system from Bob Kuehne <rpk@sgi.com>.
+#
+# Revision 1.1  1998/01/15 02:45:25  curt
+# Initial revision.
+#
+
diff --git a/GenAirports/area.cxx b/GenAirports/area.cxx
new file mode 100644
index 000000000..cfefd744d
--- /dev/null
+++ b/GenAirports/area.cxx
@@ -0,0 +1,232 @@
+// area.c -- routines to assist with inserting "areas" into FG terrain
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#include <math.h>
+#include <stdio.h>
+
+#include <Include/fg_constants.h>
+
+#include "area.hxx"
+
+
+// calc new x, y for a rotation
+double rot_x(double x, double y, double theta) {
+    return ( x * cos(theta) + y * sin(theta) );
+}
+
+
+// calc new x, y for a rotation
+double rot_y(double x, double y, double theta) {
+    return ( -x * sin(theta) + y * cos(theta) );
+}
+
+
+// calc new lon/lat given starting lon/lat, and offset radial, and
+// distance.  NOTE: distance is specified in meters (and converted
+// internally to radians)
+point2d calc_lon_lat( point2d orig, point2d offset ) {
+    point2d result;
+
+    // printf("calc_lon_lat()  offset.theta = %.2f offset.dist = %.2f\n",
+    //        offset.theta, offset.dist);
+
+    offset.dist *= METER_TO_NM * NM_TO_RAD;
+
+    result.lat = asin( sin(orig.lat) * cos(offset.dist) + 
+		       cos(orig.lat) * sin(offset.dist) * cos(offset.theta) );
+
+    if ( cos(result.lat) < FG_EPSILON ) {
+        result.lon = orig.lon;      // endpoint a pole
+    } else {
+        result.lon = 
+	    fmod(orig.lon - asin( sin(offset.theta) * sin(offset.dist) / 
+				  cos(result.lat) ) + FG_PI, FG_2PI) - FG_PI;
+    }
+
+    return(result);
+}
+
+
+point2d cart_to_polar_2d(point2d in) {
+    point2d result;
+    result.dist = sqrt( in.x * in.x + in.y * in.y );
+    result.theta = atan2(in.y, in.x);    
+
+    return(result);
+}
+
+
+list < point2d >
+batch_cart_to_polar_2d( list < point2d > in_list)
+{
+    list < point2d > out_list;
+    list < point2d > :: iterator current;                          
+    list < point2d > :: iterator last;                    
+    point2d p;
+
+    current = in_list.begin();
+    last = in_list.end();
+    while ( current != last ) {
+	p = cart_to_polar_2d( *current );
+	out_list.push_back(p);
+	current++;
+    }
+
+    return out_list;
+}
+
+
+// given a set of 2d coordinates relative to a center point, and the
+// lon, lat of that center point (specified in degrees), as well as a
+// potential orientation angle, generate the corresponding lon and lat
+// of the original 2d verticies.
+list < point2d >
+gen_area(point2d origin, double angle, list < point2d > cart_list)
+{
+    list < point2d > rad_list;
+    list < point2d > result_list;
+    list < point2d > :: iterator current;                          
+    list < point2d > :: iterator last;                    
+    point2d origin_rad, p;
+
+    origin_rad.lon = origin.lon * DEG_TO_RAD;
+    origin_rad.lat = origin.lat * DEG_TO_RAD;
+	
+    // convert to polar coordinates
+    rad_list = batch_cart_to_polar_2d(cart_list);
+
+    /*
+    // display points
+    printf("converted to polar\n");
+    current = rad_list.begin();
+    last = rad_list.end();
+    while ( current != last ) {
+	printf("(%.2f, %.2f)\n", current->theta, current->dist);
+	current++;
+    }
+    printf("\n");
+    */
+
+    // rotate by specified angle
+    // printf("Rotating points by %.2f\n", angle);
+    current = rad_list.begin();
+    last = rad_list.end();
+    while ( current != last ) {
+	current->theta -= angle;
+	while ( current->theta > FG_2PI ) {
+	    current->theta -= FG_2PI;
+	}
+	// printf("(%.2f, %.2f)\n", current->theta, current->dist);
+	current++;
+    }
+    // printf("\n");
+
+    // find actual lon,lat of coordinates
+    // printf("convert to lon, lat relative to %.2f %.2f\n", 
+    //        origin.lon, origin.lat);
+    current = rad_list.begin();
+    last = rad_list.end();
+    while ( current != last ) {
+	p = calc_lon_lat(origin_rad, *current);
+	// printf("(%.8f, %.8f)\n", p.lon, p.lat);
+	result_list.push_back(p);
+	current++;
+    }
+    // printf("\n");
+
+    return result_list;
+}
+
+
+// generate an area for a runway
+list < point2d >
+gen_runway_area( double lon, double lat, double heading, 
+		      double length, double width) 
+{
+    list < point2d > result_list;
+    list < point2d > tmp_list;
+    list < point2d > :: iterator current;                          
+    list < point2d > :: iterator last;                    
+
+    point2d p;
+    point2d origin;
+    double l, w;
+    int i;
+
+    /*
+    printf("runway: lon = %.2f lat = %.2f hdg = %.2f len = %.2f width = %.2f\n",
+	   lon, lat, heading, length, width);
+    */
+
+    origin.lon = lon;
+    origin.lat = lat;
+    l = length / 2.0;
+    w = width / 2.0;
+
+    // generate untransformed runway area vertices
+    p.x =  l; p.y =  w; tmp_list.push_back(p);
+    p.x =  l; p.y = -w; tmp_list.push_back(p);
+    p.x = -l; p.y = -w; tmp_list.push_back(p);
+    p.x = -l; p.y =  w; tmp_list.push_back(p);
+
+    /*
+    // display points
+    printf("Untransformed, unrotated runway\n");
+    current = tmp_list.begin();
+    last = tmp_list.end();
+    while ( current != last ) {
+	printf("(%.2f, %.2f)\n", current->x, current->y);
+	current++;
+    }
+    printf("\n");
+    */
+
+    // rotate, transform, and convert points to lon, lat
+    result_list = gen_area(origin, heading, tmp_list);
+
+    /*
+    // display points
+    printf("Results in radians.\n");
+    current = result_list.begin();
+    last = result_list.end();
+    while ( current != last ) {
+	printf("(%.8f, %.8f)\n", current->lon, current->lat);
+	current++;
+    }
+    printf("\n");
+    */
+
+    return result_list;
+}
+
+
+// $Log$
+// Revision 1.1  1998/09/01 19:34:33  curt
+// Initial revision.
+//
+// Revision 1.1  1998/07/20 12:54:05  curt
+// Initial revision.
+//
+//
diff --git a/GenAirports/area.hxx b/GenAirports/area.hxx
new file mode 100644
index 000000000..8ef514694
--- /dev/null
+++ b/GenAirports/area.hxx
@@ -0,0 +1,63 @@
+// area.h -- routines to assist with inserting "areas" into FG terrain
+//
+// Written by Curtis Olson, started February 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#ifndef _AREA_H
+#define _AREA_H
+
+
+#include <list>
+
+
+typedef struct {
+    union {
+	double x;
+	double dist;
+	double lon;
+    };
+    union {
+	double y;
+	double theta;
+	double lat;
+    };
+} point2d;
+
+
+// generate an area for a runway
+list < point2d >
+gen_runway_area( double lon, double lat, double heading, 
+		      double length, double width);
+
+
+#endif // _AREA_H
+
+
+// $Log$
+// Revision 1.1  1998/09/01 19:34:33  curt
+// Initial revision.
+//
+// Revision 1.1  1998/07/20 12:54:05  curt
+// Initial revision.
+//
+//
diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
new file mode 100644
index 000000000..fa5464c56
--- /dev/null
+++ b/GenAirports/main.cxx
@@ -0,0 +1,236 @@
+// main.cxx -- main loop
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <list>
+#include <stdio.h>
+#include <string.h>
+#include <string>
+
+#include <Bucket/bucketutils.h>
+#include <Include/fg_constants.h>
+#include <Include/fg_zlib.h>
+
+#include "area.hxx"
+
+
+// process and airport + runway list
+void process_airport( string last_airport, list < string > & runway_list ) {
+    list < point2d > rwy_list, apt_list;
+    list < point2d > :: iterator current;                          
+    list < point2d > :: iterator last;                    
+
+    string line_str;
+    double lon, lat;
+    int len, width, hdg, label_hdg, elev;
+    char codes[10];
+    char side;
+
+    printf( "(apt) %s", last_airport.c_str() );
+
+    while ( runway_list.size() ) {
+	line_str = runway_list.front();
+	runway_list.pop_front();
+	printf( "%s", line_str.c_str() );
+
+	sscanf( line_str.c_str(), "%lf %lf %d %d %d %s %d %c %d\n",
+		&lon, &lat, &len, &width, &hdg, codes, &label_hdg, 
+		&side, &elev );
+
+	rwy_list = gen_runway_area( lon, lat, (double)hdg * DEG_TO_RAD, 
+				    (double)len * FEET_TO_METER,
+				    (double)width * FEET_TO_METER );
+
+	// add rwy_list to apt_list
+	current = rwy_list.begin();
+	last = rwy_list.end();
+	while ( current != last ) {
+	    apt_list.push_back(*current);
+	    current++;
+	}
+    }
+
+    printf("Final results in degrees\n");
+    current = apt_list.begin();
+    last = apt_list.end();
+    while ( current != last ) {
+	// printf( "(%.4f, %.4f)\n", 
+	printf( "%.5f %.5f\n", 
+		current->lon * RAD_TO_DEG,
+		current->lat * RAD_TO_DEG );
+	current++;
+    }
+    printf("\n");
+}
+
+
+// reads the apt_full file and extracts and processes the individual
+// airport records
+int main( int argc, char **argv ) {
+    list < string > runway_list;
+    string apt_path, gz_apt_path;
+    string airport, last_airport;
+    fgFile f;
+    char line[256];
+    /*
+    fgBUCKET b;
+    point2d nodes[4];
+    char base[256], path[256], command[256], file[256], exfile[256];
+    double lon, lat, elevation, heading;
+    double length, width;
+    long int index;
+    */
+
+    if ( argc != 3 ) {
+	printf("Usage %s <apt_file> <work dir>\n", argv[0]);
+	exit(0);
+    }
+
+    apt_path = argv[1];
+    gz_apt_path = apt_path + ".gz";
+
+    // first try "path.gz"
+    if ( (f = fgopen(gz_apt_path.c_str(), "rb")) == NULL ) {
+	// next try "path"
+        if ( (f = fgopen(apt_path.c_str(), "rb")) == NULL ) {
+	    printf( "Cannot open file: %s\n", apt_path.c_str());
+	}
+    }
+
+    while ( fggets(f, line, 250) != NULL ) {
+	// printf("%s", line);
+	if ( strlen(line) == 0 ) {
+	    // empty, skip
+	} else if ( line[0] == '#' ) {
+	    // comment, skip
+	} else if ( line[0] == '\t' ) {
+	    // runway entry
+	    runway_list.push_back(line);
+	} else {
+	    // start of airport record
+	    airport = line;
+
+	    if ( last_airport.length() ) {
+		// process previous record
+		process_airport(last_airport, runway_list);
+	    }
+
+	    last_airport = airport;
+	}
+    }
+
+    if ( last_airport.length() ) {
+	// process previous record
+	process_airport(last_airport, runway_list);
+    }
+
+    fgclose(f);
+
+    return(1);
+}
+
+
+#if 0
+    // P13 (Globe, AZ)
+    // lon = -110.6642442;
+    // lat = 33.3528903;
+    // heading = 102.0 * DEG_TO_RAD;
+    // length = 1769;
+    // width = 23;
+
+    // KANE
+    lon = -93.2113889;
+    lat = 45.145;
+    elevation = 912 * FEET_TO_METER;
+    heading = 270.0 * DEG_TO_RAD;
+    length = 1220;
+    width = 23;
+
+    gen_runway_area( lon * DEG_TO_RAD, lat * DEG_TO_RAD, 
+		     heading, length, width, nodes, &count );
+
+    fgBucketFind(lon, lat, &b);
+    printf( "Bucket = lon,lat = %d,%d  x,y index = %d,%d\n", 
+	    b.lon, b.lat, b.x, b.y);
+
+    index = fgBucketGenIndex(&b);
+    fgBucketGenBasePath(&b, base);
+    sprintf(path, "%s/Scenery/%s", argv[1], base);
+    sprintf(command, "mkdir -p %s\n", path);
+    system(command);
+    
+    sprintf(exfile, "%s/%ld.node.ex", path, index);
+    sprintf(file, "%s/%ld.poly", path, index);
+    printf( "extra node file = %s\n", exfile);
+    printf( "poly file = %s\n", file);
+
+    // output extra nodes
+    if ( (fd = fopen(exfile, "w")) == NULL ) {
+        printf("Cannot open file: %s\n", exfile);
+        exit(-1);
+    }
+
+    fprintf(fd, "%d 2 0 0\n", count);
+    for ( i = 0; i < count; i++ ) {
+	fprintf( fd, "%d %.2f %.2f %.2f\n", i + 1, 
+		 nodes[i].lon * RAD_TO_ARCSEC, nodes[i].lat * RAD_TO_ARCSEC, 
+		 elevation);
+    }
+    fclose(fd);
+
+    // output poly
+    if ( (fd = fopen(file, "w")) == NULL ) {
+        printf("Cannot open file: %s\n", file);
+        exit(-1);
+    }
+
+    // output empty node list
+    fprintf(fd, "0 2 0 0\n");
+
+    // output segments
+    fprintf(fd, "%d 0\n", count);
+    for ( i = 0; i < count - 1; i++ ) {
+	fprintf( fd, "%d %d %d\n", i + 1, i + 1, i + 2 );
+    }
+    fprintf( fd, "%d %d %d\n", count, count, 1 );
+
+    // output hole center
+    fprintf( fd, "1\n");
+    fprintf( fd, "1 %.2f %.2f\n", lon * 3600.0, lat * 3600);
+
+    fclose(fd);
+
+#endif
+
+
+// $Log: main.c,v
+//

From c862bf37942104b25999cde709d562e8dbb47a34 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 2 Sep 1998 14:38:07 +0000
Subject: [PATCH 133/283] Added Tools/GenAirports

---
 Tools/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index e9c467985..69f124bb7 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -7,6 +7,7 @@ SUBDIRS = \
 	DemInfo \
 	DemRaw2ascii \
 	FixNode \
+	GenAirports \
 	FixObj \
 	SplitTris \
 	Stripe_w \

From 235c7bdce7d336f7a2f7aa6c85a7f037f1e300ef Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 2 Sep 1998 21:31:01 +0000
Subject: [PATCH 134/283] Tweaks for final 0.53

---
 Tools/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 69f124bb7..7fd79620f 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -7,8 +7,8 @@ SUBDIRS = \
 	DemInfo \
 	DemRaw2ascii \
 	FixNode \
-	GenAirports \
 	FixObj \
+	GenAirports \
 	SplitTris \
 	Stripe_w \
 	Tri2obj \

From 99df9c1ee000eef8f9ef7532550cfb57b23cdeee Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 4 Sep 1998 23:04:47 +0000
Subject: [PATCH 135/283] Beginning of convex hull genereration routine.

---
 GenAirports/Makefile.am     |   9 ++-
 GenAirports/area.cxx        |  18 +++---
 GenAirports/area.hxx        |  19 ++----
 GenAirports/convex_hull.cxx | 120 ++++++++++++++++++++++++++++++++++++
 GenAirports/convex_hull.hxx |  61 ++++++++++++++++++
 GenAirports/main.cxx        |   7 ++-
 GenAirports/point2d.cxx     |  45 ++++++++++++++
 GenAirports/point2d.hxx     |  59 ++++++++++++++++++
 8 files changed, 310 insertions(+), 28 deletions(-)
 create mode 100644 GenAirports/convex_hull.cxx
 create mode 100644 GenAirports/convex_hull.hxx
 create mode 100644 GenAirports/point2d.cxx
 create mode 100644 GenAirports/point2d.hxx

diff --git a/GenAirports/Makefile.am b/GenAirports/Makefile.am
index a5d9d981c..e3593d492 100644
--- a/GenAirports/Makefile.am
+++ b/GenAirports/Makefile.am
@@ -26,7 +26,11 @@
 
 bin_PROGRAMS = genapts
 
-genapts_SOURCES = area.cxx area.hxx main.cxx
+genapts_SOURCES = \
+	area.cxx area.hxx \
+	convex_hull.cxx convex_hull.hxx \
+	main.cxx \
+	point2d.cxx point2d.hxx
 
 genapts_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
@@ -37,6 +41,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1998/09/04 23:04:47  curt
+# Beginning of convex hull genereration routine.
+#
 # Revision 1.1  1998/09/01 19:34:32  curt
 # Initial revision.
 #
diff --git a/GenAirports/area.cxx b/GenAirports/area.cxx
index cfefd744d..aa9907618 100644
--- a/GenAirports/area.cxx
+++ b/GenAirports/area.cxx
@@ -29,6 +29,7 @@
 #include <Include/fg_constants.h>
 
 #include "area.hxx"
+#include "point2d.hxx"
 
 
 // calc new x, y for a rotation
@@ -69,15 +70,6 @@ point2d calc_lon_lat( point2d orig, point2d offset ) {
 }
 
 
-point2d cart_to_polar_2d(point2d in) {
-    point2d result;
-    result.dist = sqrt( in.x * in.x + in.y * in.y );
-    result.theta = atan2(in.y, in.x);    
-
-    return(result);
-}
-
-
 list < point2d >
 batch_cart_to_polar_2d( list < point2d > in_list)
 {
@@ -150,6 +142,9 @@ gen_area(point2d origin, double angle, list < point2d > cart_list)
     last = rad_list.end();
     while ( current != last ) {
 	p = calc_lon_lat(origin_rad, *current);
+	// convert from radians to degress
+	p.lon *= RAD_TO_DEG;
+	p.lat *= RAD_TO_DEG;
 	// printf("(%.8f, %.8f)\n", p.lon, p.lat);
 	result_list.push_back(p);
 	current++;
@@ -203,7 +198,7 @@ gen_runway_area( double lon, double lat, double heading,
     printf("\n");
     */
 
-    // rotate, transform, and convert points to lon, lat
+    // rotate, transform, and convert points to lon, lat in degrees
     result_list = gen_area(origin, heading, tmp_list);
 
     /*
@@ -223,6 +218,9 @@ gen_runway_area( double lon, double lat, double heading,
 
 
 // $Log$
+// Revision 1.2  1998/09/04 23:04:48  curt
+// Beginning of convex hull genereration routine.
+//
 // Revision 1.1  1998/09/01 19:34:33  curt
 // Initial revision.
 //
diff --git a/GenAirports/area.hxx b/GenAirports/area.hxx
index 8ef514694..a1bbd342e 100644
--- a/GenAirports/area.hxx
+++ b/GenAirports/area.hxx
@@ -29,22 +29,10 @@
 
 #include <list>
 
-
-typedef struct {
-    union {
-	double x;
-	double dist;
-	double lon;
-    };
-    union {
-	double y;
-	double theta;
-	double lat;
-    };
-} point2d;
+#include "point2d.hxx"
 
 
-// generate an area for a runway
+// generate an area for a runway (return result points in degrees)
 list < point2d >
 gen_runway_area( double lon, double lat, double heading, 
 		      double length, double width);
@@ -54,6 +42,9 @@ gen_runway_area( double lon, double lat, double heading,
 
 
 // $Log$
+// Revision 1.2  1998/09/04 23:04:49  curt
+// Beginning of convex hull genereration routine.
+//
 // Revision 1.1  1998/09/01 19:34:33  curt
 // Initial revision.
 //
diff --git a/GenAirports/convex_hull.cxx b/GenAirports/convex_hull.cxx
new file mode 100644
index 000000000..223bb45db
--- /dev/null
+++ b/GenAirports/convex_hull.cxx
@@ -0,0 +1,120 @@
+// convex_hull.cxx -- calculate the convex hull of a set of points
+//
+// Written by Curtis Olson, started September 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#include <stdio.h>
+
+#include <list>
+#include <map>
+
+#ifdef NEEDNAMESPACESTD
+using namespace std;
+#endif
+
+#include "convex_hull.hxx"
+#include "point2d.hxx"
+
+// calculate the convex hull of a set of points, return as a list of
+// point2d
+list_container convex_hull( list_container input_list )
+{
+    list_iterator current, last;
+    map_iterator map_current, map_last;
+
+    // list of translated points
+    list_container trans_list;
+
+    // points sorted by radian degrees
+    map_container radians_map;
+
+    // will contain the convex hull
+    list_container con_hull;
+
+    point2d p, average;
+    double sum_x, sum_y;
+    int in_count;
+
+    // STEP ONE:  Find an average midpoint of the input set of points
+    current = input_list.begin();
+    last = input_list.end();
+    in_count = input_list.size();
+    sum_x = sum_y = 0.0;
+
+    while ( current != last ) {
+	sum_x += (*current).x;
+	sum_y += (*current).y;
+
+	current++;
+    }
+
+    average.x = sum_x / in_count;
+    average.y = sum_y / in_count;
+
+    printf("Average center point is %.4f %.4f\n", average.x, average.y);
+
+    // STEP TWO:  Translate input points so average is at origin
+    current = input_list.begin();
+    last = input_list.end();
+    trans_list.erase( trans_list.begin(), trans_list.end() );
+
+    while ( current != last ) {
+	p.x = (*current).x - average.x;
+	p.y = (*current).y - average.y;
+	printf("p is %.6f %.6f\n", p.x, p.y);
+	trans_list.push_back(p);
+	current++;
+    }
+
+    // STEP THREE:  convert to radians and sort by theta
+    current = trans_list.begin();
+    last = trans_list.end();
+    radians_map.erase( radians_map.begin(), radians_map.end() );
+
+    while ( current != last ) {
+	p = cart_to_polar_2d(*current);
+	radians_map[p.theta] = p.dist;
+	current++;
+    }
+
+    printf("Sorted list\n");
+    map_current = radians_map.begin();
+    map_last = radians_map.end();
+    while ( map_current != map_last ) {
+	p.x = (*map_current).first;
+	p.y = (*map_current).second;
+
+	printf("p is %.6f %.6f\n", p.x, p.y);
+
+	map_current++;
+    }
+
+    return con_hull;
+}
+
+
+// $Log$
+// Revision 1.1  1998/09/04 23:04:51  curt
+// Beginning of convex hull genereration routine.
+//
+//
diff --git a/GenAirports/convex_hull.hxx b/GenAirports/convex_hull.hxx
new file mode 100644
index 000000000..ca0b1fc60
--- /dev/null
+++ b/GenAirports/convex_hull.hxx
@@ -0,0 +1,61 @@
+// convex_hull.hxx -- calculate the convex hull of a set of points
+//
+// Written by Curtis Olson, started September 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#ifndef _CONVEX_HULL_HXX
+#define _CONVEX_HULL_HXX
+
+
+#include <list>
+#include <map>
+
+#ifdef NEEDNAMESPACESTD
+using namespace std;
+#endif
+
+#include "point2d.hxx"
+
+
+// stl list typedefs
+typedef list < point2d > list_container;
+typedef list_container::iterator list_iterator;
+
+// stl mapp typedefs
+typedef map < double, double, less<double> > map_container;
+typedef map_container::iterator map_iterator;
+
+
+// calculate the convex hull of a set of points, return as a list of
+// point2d
+list_container convex_hull( list_container input_list );
+
+
+#endif // _CONVEX_HULL_HXX
+
+
+// $Log$
+// Revision 1.1  1998/09/04 23:04:51  curt
+// Beginning of convex hull genereration routine.
+//
+//
diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index fa5464c56..9a42f9021 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -41,6 +41,7 @@
 #include <Include/fg_zlib.h>
 
 #include "area.hxx"
+#include "convex_hull.hxx"
 
 
 // process and airport + runway list
@@ -84,12 +85,12 @@ void process_airport( string last_airport, list < string > & runway_list ) {
     last = apt_list.end();
     while ( current != last ) {
 	// printf( "(%.4f, %.4f)\n", 
-	printf( "%.5f %.5f\n", 
-		current->lon * RAD_TO_DEG,
-		current->lat * RAD_TO_DEG );
+	printf( "%.5f %.5f\n", current->lon, current->lat );
 	current++;
     }
     printf("\n");
+
+    convex_hull(apt_list);
 }
 
 
diff --git a/GenAirports/point2d.cxx b/GenAirports/point2d.cxx
new file mode 100644
index 000000000..755224477
--- /dev/null
+++ b/GenAirports/point2d.cxx
@@ -0,0 +1,45 @@
+// point2d.cxx -- 2d coordinate routines
+//
+// Written by Curtis Olson, started September 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#include <math.h>
+
+#include "point2d.hxx"
+
+
+// convert a point from cartesian to polar coordinates
+point2d cart_to_polar_2d(point2d in) {
+    point2d result;
+    result.dist = sqrt( in.x * in.x + in.y * in.y );
+    result.theta = atan2(in.y, in.x);    
+
+    return(result);
+}
+
+
+// $Log$
+// Revision 1.1  1998/09/04 23:04:53  curt
+// Beginning of convex hull genereration routine.
+//
+//
diff --git a/GenAirports/point2d.hxx b/GenAirports/point2d.hxx
new file mode 100644
index 000000000..199524047
--- /dev/null
+++ b/GenAirports/point2d.hxx
@@ -0,0 +1,59 @@
+// point2d.hxx -- define a 2d point class
+//
+// Written by Curtis Olson, started February 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#ifndef _POINT2D_HXX
+#define _POINT2D_HXX
+
+
+#include <list>
+
+
+class point2d {
+public:
+    union {
+	double x;
+	double dist;
+	double lon;
+    };
+    union {
+	double y;
+	double theta;
+	double lat;
+    };
+};
+
+
+// convert a point from cartesian to polar coordinates
+point2d cart_to_polar_2d(point2d in);
+
+
+#endif // _POINT2D_HXX
+
+
+// $Log$
+// Revision 1.1  1998/09/04 23:04:53  curt
+// Beginning of convex hull genereration routine.
+//
+//

From 757ecbfcfd6deea9c9be0b1d9953b385cab04459 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 9 Sep 1998 16:24:04 +0000
Subject: [PATCH 136/283] Fixed a bug in the handling of exclude files which
 was causing a crash by calling fclose() on an invalid file handle.

---
 DEM/dem.cxx | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 13bd4ea0b..21e8ebc1d 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -774,8 +774,8 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
 	    printf("(extra) %d %.2f %.2f %.2f\n", 
 		    i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
 	}
+	fclose(fd);
     }
-    fclose(fd);
 
     printf("Creating node file:  %s\n", file);
     fd = fopen(file, "w");
@@ -825,6 +825,10 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.13  1998/09/09 16:24:04  curt
+// Fixed a bug in the handling of exclude files which was causing
+// a crash by calling fclose() on an invalid file handle.
+//
 // Revision 1.12  1998/08/24 20:03:31  curt
 // Eliminated a possible memory overrun error.
 // Use the proper free() rather than the incorrect delete().

From aa77cd6079f147be706362b9fae37e40b6c81088 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 9 Sep 1998 16:24:51 +0000
Subject: [PATCH 137/283] Fixed a bug in the handling of exclude files which
 was causing   a crash by calling fclose() on an invalid file handle. Removed
 overlapping offsets.

---
 AssemTris/assemtris.c | 35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index 2eb891784..ea16e68d3 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -36,6 +36,14 @@
 #include <Bucket/bucketutils.h>
 
 
+/*
+#define OFFSET_LON 0.1
+#define OFFSET_LAT 0.1
+*/
+
+#define OFFSET_LON 0.0
+#define OFFSET_LAT 0.0
+
 int nodecount = 0;
 int excount = 0;
 
@@ -123,8 +131,8 @@ void read_extra_nodes(char *exfile) {
 	    printf("(extra) %d %.2f %.2f %.2f\n", 
 		    i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
 	}
+        fclose(fd);
     }
-    fclose(fd);
 }
 
 
@@ -403,35 +411,35 @@ void build_node_list(char *basename, char *basepath) {
     read_extra_nodes(exfile);
 
     ne = my_open(basename, basepath, ".ne");
-    read_nodes(ne, 0.1, 0.1);
+    read_nodes(ne, OFFSET_LON, OFFSET_LAT);
     fclose(ne);
 
     nw = my_open(basename, basepath, ".nw");
-    read_nodes(nw, -0.1, 0.1);
+    read_nodes(nw, -1.0 * OFFSET_LON, OFFSET_LAT);
     fclose(nw);
 
     se = my_open(basename, basepath, ".se");
-    read_nodes(se, 0.1, -0.1);
+    read_nodes(se, OFFSET_LON, -1.0 * OFFSET_LAT);
     fclose(se);
 
     sw = my_open(basename, basepath, ".sw");
-    read_nodes(sw, -0.1, -0.1);
+    read_nodes(sw, -1.0 * OFFSET_LON, -1.0 * OFFSET_LAT);
     fclose(sw);
 
     north = my_open(basename, basepath, ".north");
-    read_nodes(north, 0.0, 0.1);
+    read_nodes(north, 0.0, OFFSET_LAT);
     fclose(north);
 
     south = my_open(basename, basepath, ".south");
-    read_nodes(south, 0.0, -0.1);
+    read_nodes(south, 0.0, -1.0 * OFFSET_LAT);
     fclose(south);
 
     east = my_open(basename, basepath, ".east");
-    read_nodes(east, 0.1, 0.0);
+    read_nodes(east, OFFSET_LON, 0.0);
     fclose(east);
 
     west = my_open(basename, basepath, ".west");
-    read_nodes(west, -0.1, 0.0);
+    read_nodes(west, -1.0 * OFFSET_LON, 0.0);
     fclose(west);
 
     body = my_open(basename, basepath, ".body");
@@ -531,9 +539,14 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.11  1998/08/06 12:47:59  curt
-/* Removed overlap in tiles as a test.
+/* Revision 1.12  1998/09/09 16:24:51  curt
+/* Fixed a bug in the handling of exclude files which was causing
+/*   a crash by calling fclose() on an invalid file handle.
+/* Removed overlapping offsets.
 /*
+ * Revision 1.11  1998/08/06 12:47:59  curt
+ * Removed overlap in tiles as a test.
+ *
  * Revision 1.10  1998/07/21 04:34:20  curt
  * Mods to handle extra nodes (i.e. preserve cutouts).
  *

From 5b1b93bf87f6b026fe0c00e8fb5754caeeb784f2 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 9 Sep 1998 16:26:31 +0000
Subject: [PATCH 138/283] Continued progress in implementing the convex hull
 algorithm.

---
 GenAirports/area.cxx        |  15 ++--
 GenAirports/convex_hull.cxx | 173 +++++++++++++++++++++++++++++++++---
 GenAirports/convex_hull.hxx |  11 ++-
 GenAirports/main.cxx        | 108 +++++++++++++++++++---
 4 files changed, 275 insertions(+), 32 deletions(-)

diff --git a/GenAirports/area.cxx b/GenAirports/area.cxx
index aa9907618..3ceaf1b1e 100644
--- a/GenAirports/area.cxx
+++ b/GenAirports/area.cxx
@@ -83,7 +83,7 @@ batch_cart_to_polar_2d( list < point2d > in_list)
     while ( current != last ) {
 	p = cart_to_polar_2d( *current );
 	out_list.push_back(p);
-	current++;
+	++current;
     }
 
     return out_list;
@@ -116,7 +116,7 @@ gen_area(point2d origin, double angle, list < point2d > cart_list)
     last = rad_list.end();
     while ( current != last ) {
 	printf("(%.2f, %.2f)\n", current->theta, current->dist);
-	current++;
+	++current;
     }
     printf("\n");
     */
@@ -131,7 +131,7 @@ gen_area(point2d origin, double angle, list < point2d > cart_list)
 	    current->theta -= FG_2PI;
 	}
 	// printf("(%.2f, %.2f)\n", current->theta, current->dist);
-	current++;
+	++current;
     }
     // printf("\n");
 
@@ -147,7 +147,7 @@ gen_area(point2d origin, double angle, list < point2d > cart_list)
 	p.lat *= RAD_TO_DEG;
 	// printf("(%.8f, %.8f)\n", p.lon, p.lat);
 	result_list.push_back(p);
-	current++;
+	++current;
     }
     // printf("\n");
 
@@ -193,7 +193,7 @@ gen_runway_area( double lon, double lat, double heading,
     last = tmp_list.end();
     while ( current != last ) {
 	printf("(%.2f, %.2f)\n", current->x, current->y);
-	current++;
+	++current;
     }
     printf("\n");
     */
@@ -208,7 +208,7 @@ gen_runway_area( double lon, double lat, double heading,
     last = result_list.end();
     while ( current != last ) {
 	printf("(%.8f, %.8f)\n", current->lon, current->lat);
-	current++;
+	++current;
     }
     printf("\n");
     */
@@ -218,6 +218,9 @@ gen_runway_area( double lon, double lat, double heading,
 
 
 // $Log$
+// Revision 1.3  1998/09/09 16:26:31  curt
+// Continued progress in implementing the convex hull algorithm.
+//
 // Revision 1.2  1998/09/04 23:04:48  curt
 // Beginning of convex hull genereration routine.
 //
diff --git a/GenAirports/convex_hull.cxx b/GenAirports/convex_hull.cxx
index 223bb45db..75c41c52a 100644
--- a/GenAirports/convex_hull.cxx
+++ b/GenAirports/convex_hull.cxx
@@ -23,6 +23,7 @@
 //
 
 
+#include <math.h>
 #include <stdio.h>
 
 #include <list>
@@ -32,15 +33,80 @@
 using namespace std;
 #endif
 
+#include <Include/fg_constants.h>
+
 #include "convex_hull.hxx"
 #include "point2d.hxx"
 
+
+// stl map typedefs
+typedef map < double, double, less<double> > map_container;
+typedef map_container::iterator map_iterator;
+
+
+// Calculate theta of angle (a, b, c)
+double calc_angle(point2d a, point2d b, point2d c) {
+    point2d u, v;
+    double udist, vdist, uv_dot, tmp;
+
+    // u . v = ||u|| * ||v|| * cos(theta)
+
+    u.x = b.x - a.x;
+    u.y = b.y - a.y;
+    udist = sqrt( u.x * u.x + u.y * u.y );
+    // printf("udist = %.6f\n", udist);
+
+    v.x = b.x - c.x;
+    v.y = b.y - c.y;
+    vdist = sqrt( v.x * v.x + v.y * v.y );
+    // printf("vdist = %.6f\n", vdist);
+
+    uv_dot = u.x * v.x + u.y * v.y;
+    // printf("uv_dot = %.6f\n", uv_dot);
+
+    tmp = uv_dot / (udist * vdist);
+    // printf("tmp = %.6f\n", tmp);
+
+    return acos(tmp);
+}
+
+
+// Test to see if angle(Pa, Pb, Pc) < 180 degrees
+bool test_point(point2d Pa, point2d Pb, point2d Pc) {
+    point2d origin, a, b, c;
+    double a1, a2;
+
+    origin.x = origin.y = 0.0;
+
+    a.x = cos(Pa.theta) * Pa.dist;
+    a.y = sin(Pa.theta) * Pa.dist;
+
+    b.x = cos(Pb.theta) * Pb.dist;
+    b.y = sin(Pb.theta) * Pb.dist;
+
+    c.x = cos(Pc.theta) * Pc.dist;
+    c.y = sin(Pc.theta) * Pc.dist;
+
+    // printf("a is %.6f %.6f\n", a.x, a.y);
+    // printf("b is %.6f %.6f\n", b.x, b.y);
+    // printf("c is %.6f %.6f\n", c.x, c.y);
+
+    a1 = calc_angle(a, b, origin);
+    a2 = calc_angle(origin, b, c);
+
+    printf("a1 = %.2f  a2 = %.2f\n", a1 * RAD_TO_DEG, a2 * RAD_TO_DEG);
+
+    return ( (a1 + a2) < FG_PI );
+}
+
+
 // calculate the convex hull of a set of points, return as a list of
-// point2d
+// point2d.  The algorithm description can be found at:
+// http://riot.ieor.berkeley.edu/riot/Applications/ConvexHull/CHDetails.html
 list_container convex_hull( list_container input_list )
 {
     list_iterator current, last;
-    map_iterator map_current, map_last;
+    map_iterator map_current, map_next, map_next_next, map_last;
 
     // list of translated points
     list_container trans_list;
@@ -51,9 +117,9 @@ list_container convex_hull( list_container input_list )
     // will contain the convex hull
     list_container con_hull;
 
-    point2d p, average;
+    point2d p, average, Pa, Pb, Pc, result;
     double sum_x, sum_y;
-    int in_count;
+    int in_count, last_size;
 
     // STEP ONE:  Find an average midpoint of the input set of points
     current = input_list.begin();
@@ -65,7 +131,7 @@ list_container convex_hull( list_container input_list )
 	sum_x += (*current).x;
 	sum_y += (*current).y;
 
-	current++;
+	++current;
     }
 
     average.x = sum_x / in_count;
@@ -81,9 +147,9 @@ list_container convex_hull( list_container input_list )
     while ( current != last ) {
 	p.x = (*current).x - average.x;
 	p.y = (*current).y - average.y;
-	printf("p is %.6f %.6f\n", p.x, p.y);
+	printf("%.6f %.6f\n", p.x, p.y);
 	trans_list.push_back(p);
-	current++;
+	++current;
     }
 
     // STEP THREE:  convert to radians and sort by theta
@@ -93,8 +159,10 @@ list_container convex_hull( list_container input_list )
 
     while ( current != last ) {
 	p = cart_to_polar_2d(*current);
-	radians_map[p.theta] = p.dist;
-	current++;
+	if ( p.dist > radians_map[p.theta] ) {
+	    radians_map[p.theta] = p.dist;
+	}
+	++current;
     }
 
     printf("Sorted list\n");
@@ -106,7 +174,89 @@ list_container convex_hull( list_container input_list )
 
 	printf("p is %.6f %.6f\n", p.x, p.y);
 
-	map_current++;
+	++map_current;
+    }
+
+    // STEP FOUR: traverse the sorted list and eliminate everything
+    // not on the perimeter.
+    printf("Traversing list\n");
+
+    // double check list size ... this should never fail because a
+    // single runway will always generate four points.
+    if ( radians_map.size() < 3 ) {
+	printf("convex hull not possible with < 3 points\n");
+	exit(0);
+    }
+
+    // ensure that we run the while loop at least once
+    last_size = radians_map.size() + 1;
+
+    while ( last_size > radians_map.size() ) {
+	printf("Running an iteration of the graham scan algorithm\n"); 
+	last_size = radians_map.size();
+
+	map_current = radians_map.begin();
+	while ( map_current != radians_map.end() ) {
+	    // get first element
+	    Pa.theta = (*map_current).first;
+	    Pa.dist = (*map_current).second;
+
+	    // get second element
+	    map_next = map_current;
+	    ++map_next;
+	    if ( map_next == radians_map.end() ) {
+		map_next = radians_map.begin();
+	    }
+	    Pb.theta = (*map_next).first;
+	    Pb.dist = (*map_next).second;
+
+	    // get third element
+	    map_next_next = map_next;
+	    ++map_next_next;
+	    if ( map_next_next == radians_map.end() ) {
+		map_next_next = radians_map.begin();
+	    }
+	    Pc.theta = (*map_next_next).first;
+	    Pc.dist = (*map_next_next).second;
+
+	    // printf("Pa is %.6f %.6f\n", Pa.theta, Pa.dist);
+	    // printf("Pb is %.6f %.6f\n", Pb.theta, Pb.dist);
+	    // printf("Pc is %.6f %.6f\n", Pc.theta, Pc.dist);
+
+	    if ( test_point(Pa, Pb, Pc) ) {
+		printf("Accepted a point\n");
+		// accept point, advance Pa, Pb, and Pc.
+		++map_current;
+	    } else {
+		printf("REJECTED A POINT\n");
+		// reject point, delete it and advance only Pb and Pc
+		map_next = map_current;
+		++map_next;
+		if ( map_next == radians_map.end() ) {
+		    map_next = radians_map.begin();
+		}
+		radians_map.erase( map_next );
+	    }
+	}
+    }
+
+    // translate back to correct lon/lat
+    printf("Final sorted convex hull\n");
+    con_hull.erase( con_hull.begin(), con_hull.end() );
+    map_current = radians_map.begin();
+    map_last = radians_map.end();
+    while ( map_current != map_last ) {
+	p.theta = (*map_current).first;
+	p.dist = (*map_current).second;
+
+	result.x = cos(p.theta) * p.dist + average.x;
+	result.y = sin(p.theta) * p.dist + average.x;
+
+	printf("%.6f %.6f\n", result.x, result.y);
+
+	con_hull.push_back(result);
+
+	++map_current;
     }
 
     return con_hull;
@@ -114,6 +264,9 @@ list_container convex_hull( list_container input_list )
 
 
 // $Log$
+// Revision 1.2  1998/09/09 16:26:32  curt
+// Continued progress in implementing the convex hull algorithm.
+//
 // Revision 1.1  1998/09/04 23:04:51  curt
 // Beginning of convex hull genereration routine.
 //
diff --git a/GenAirports/convex_hull.hxx b/GenAirports/convex_hull.hxx
index ca0b1fc60..42bf0db83 100644
--- a/GenAirports/convex_hull.hxx
+++ b/GenAirports/convex_hull.hxx
@@ -28,7 +28,6 @@
 
 
 #include <list>
-#include <map>
 
 #ifdef NEEDNAMESPACESTD
 using namespace std;
@@ -41,13 +40,10 @@ using namespace std;
 typedef list < point2d > list_container;
 typedef list_container::iterator list_iterator;
 
-// stl mapp typedefs
-typedef map < double, double, less<double> > map_container;
-typedef map_container::iterator map_iterator;
-
 
 // calculate the convex hull of a set of points, return as a list of
-// point2d
+// point2d.  The algorithm description can be found at:
+// http://riot.ieor.berkeley.edu/riot/Applications/ConvexHull/CHDetails.html
 list_container convex_hull( list_container input_list );
 
 
@@ -55,6 +51,9 @@ list_container convex_hull( list_container input_list );
 
 
 // $Log$
+// Revision 1.2  1998/09/09 16:26:33  curt
+// Continued progress in implementing the convex hull algorithm.
+//
 // Revision 1.1  1998/09/04 23:04:51  curt
 // Beginning of convex hull genereration routine.
 //
diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index 9a42f9021..0aeee8d25 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -45,16 +45,25 @@
 
 
 // process and airport + runway list
-void process_airport( string last_airport, list < string > & runway_list ) {
-    list < point2d > rwy_list, apt_list;
-    list < point2d > :: iterator current;                          
-    list < point2d > :: iterator last;                    
+void process_airport( string last_airport, list < string > & runway_list,
+		      const string& root ) {
+    list_container rwy_list, apt_list, hull_list;
+    list_iterator current, last;
 
     string line_str;
     double lon, lat;
     int len, width, hdg, label_hdg, elev;
     char codes[10];
     char side;
+    point2d average;
+    double sum_x, sum_y;
+
+    FILE *fd;
+    fgBUCKET b;
+    long int index;
+    char base[256], tmp[256];
+    string path, command, exfile, file;
+    int i, count;
 
     printf( "(apt) %s", last_airport.c_str() );
 
@@ -76,21 +85,100 @@ void process_airport( string last_airport, list < string > & runway_list ) {
 	last = rwy_list.end();
 	while ( current != last ) {
 	    apt_list.push_back(*current);
-	    current++;
+	    ++current;
 	}
     }
 
-    printf("Final results in degrees\n");
+    printf("Runway points in degrees\n");
     current = apt_list.begin();
     last = apt_list.end();
     while ( current != last ) {
 	// printf( "(%.4f, %.4f)\n", 
 	printf( "%.5f %.5f\n", current->lon, current->lat );
-	current++;
+	++current;
     }
     printf("\n");
 
-    convex_hull(apt_list);
+    // generate convex hull
+    hull_list = convex_hull(apt_list);
+
+    // find average center point of convex hull
+    count = hull_list.size();
+
+    current = hull_list.begin();
+    last = hull_list.end();
+    sum_x = sum_y = 0.0;
+    while ( current != last ) {
+	sum_x += (*current).x;
+	sum_y += (*current).y;
+
+	++current;
+    }
+
+    average.x = sum_x / count;
+    average.y = sum_y / count;
+
+    // find bucket based on first point in hull list.  Eventually
+    // we'll need to handle cases where the area crosses bucket
+    // boundaries.
+    fgBucketFind( (*current).lon, (*current).lat, &b);
+    printf( "Bucket = lon,lat = %d,%d  x,y index = %d,%d\n", 
+	    b.lon, b.lat, b.x, b.y);
+
+    index = fgBucketGenIndex(&b);
+    fgBucketGenBasePath(&b, base);
+    path = root + "/Scenery/" + base;
+    command = "mkdir -p " + path;
+    system( command.c_str() );
+
+    sprintf(tmp, "%ld", index);
+    exfile = path + "/" + tmp + ".node.ex";
+    file =   path + "/" + tmp + ".poly";
+    printf( "extra node file = %s\n", exfile.c_str() );
+    printf( "poly file = %s\n", file.c_str() );
+
+    // output exclude nodes
+    printf("Output exclude nodes\n");
+    if ( (fd = fopen(exfile.c_str(), "w")) == NULL ) {
+        printf("Cannot open file: %s\n", exfile.c_str());
+        exit(-1);
+    }
+
+    fprintf( fd, "%d 2 0 0\n", count );
+
+    current = hull_list.begin();
+    last = hull_list.end();
+    i = 1;
+    while ( current != last ) {
+	// printf( "(%.4f, %.4f)\n", 
+	fprintf( fd, "%d %.2f %.2f %.2f\n", i, 
+		 (*current).lon * 3600.0, (*current).lat * 3600.0, elev);
+	++current;
+	++i;
+    }
+    fclose(fd);
+
+    // output poly
+    if ( (fd = fopen(file.c_str(), "w")) == NULL ) {
+        printf("Cannot open file: %s\n", file.c_str());
+        exit(-1);
+    }
+
+    // output empty node list
+    fprintf(fd, "0 2 0 0\n");
+
+    // output segments
+    fprintf( fd, "%d 0\n", count );
+    for ( i = 1; i < count; i++ ) {
+	fprintf( fd, "%d %d %d\n", i, i, i + 1 );
+    }
+    fprintf( fd, "%d %d %d\n", count, count, 1 );
+
+    // output hole center
+    fprintf( fd, "1\n");
+    fprintf( fd, "1 %.2f %.2f\n", average.x * 3600.0, average.y * 3600);
+
+    fclose(fd);
 }
 
 
@@ -142,7 +230,7 @@ int main( int argc, char **argv ) {
 
 	    if ( last_airport.length() ) {
 		// process previous record
-		process_airport(last_airport, runway_list);
+		process_airport(last_airport, runway_list, argv[2]);
 	    }
 
 	    last_airport = airport;
@@ -151,7 +239,7 @@ int main( int argc, char **argv ) {
 
     if ( last_airport.length() ) {
 	// process previous record
-	process_airport(last_airport, runway_list);
+	process_airport(last_airport, runway_list, argv[2]);
     }
 
     fgclose(f);

From a113722755d9cfd9cd400fb482c2f41a650cdbdd Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 9 Sep 1998 20:58:35 +0000
Subject: [PATCH 139/283] Fixes and tweaks to handle area cutouts for airports.

---
 Tools/process-dem.pl | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index a38be6d8d..ad791d10d 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -167,7 +167,7 @@ sub triangle_1 {
 	    print "$subdir/$fileroot\n";
 	    $command = "Triangle/triangle";
 	    if ( -r "$subdir/$fileroot.poly" ) {
-		$command = " -pc";
+		$command .= " -pc";
 	    }
 	    $command .= " -a$max_area -q10 $subdir/$file";
 	    $command = fix_command($command);
@@ -471,6 +471,15 @@ sub install {
 	    if ( $remove_tmps ) {
 		unlink("$subdir/$file");
 	    }
+	} elsif ( $file =~ m/\d\d.apt$/ ) {
+	    $command = "cp $subdir/$file $install_dir/$file";
+	    # $command = fix_command($command);
+	    print "Running '$command'\n";
+	    open(OUT, "$command |");
+	    while ( <OUT> ) {
+		print $_;
+	    }
+	    close(OUT);
 	}
     }
 }
@@ -478,6 +487,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.27  1998/09/09 20:58:35  curt
+# Fixes and tweaks to handle area cutouts for airports.
+#
 # Revision 1.26  1998/08/26 22:31:29  curt
 # Write out version and "meta" info into each dem's subdirectory containing
 # all the tiles.

From 2e30b5bdb65bcb377ea0941a3b683107c7ce3c70 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 9 Sep 1998 20:59:53 +0000
Subject: [PATCH 140/283] Loop construct tweaks for STL usage. Output airport
 file to be used to generate airport scenery on the fly   by the run time sim.

---
 GenAirports/area.cxx        |  14 ++--
 GenAirports/convex_hull.cxx |  45 +++++------
 GenAirports/main.cxx        | 152 ++++++++++++++----------------------
 3 files changed, 87 insertions(+), 124 deletions(-)

diff --git a/GenAirports/area.cxx b/GenAirports/area.cxx
index 3ceaf1b1e..aeb104552 100644
--- a/GenAirports/area.cxx
+++ b/GenAirports/area.cxx
@@ -80,10 +80,9 @@ batch_cart_to_polar_2d( list < point2d > in_list)
 
     current = in_list.begin();
     last = in_list.end();
-    while ( current != last ) {
+    for ( ; current != last ; ++current ) {
 	p = cart_to_polar_2d( *current );
 	out_list.push_back(p);
-	++current;
     }
 
     return out_list;
@@ -125,13 +124,12 @@ gen_area(point2d origin, double angle, list < point2d > cart_list)
     // printf("Rotating points by %.2f\n", angle);
     current = rad_list.begin();
     last = rad_list.end();
-    while ( current != last ) {
+    for ( ; current != last ; ++current ) {
 	current->theta -= angle;
 	while ( current->theta > FG_2PI ) {
 	    current->theta -= FG_2PI;
 	}
 	// printf("(%.2f, %.2f)\n", current->theta, current->dist);
-	++current;
     }
     // printf("\n");
 
@@ -140,14 +138,13 @@ gen_area(point2d origin, double angle, list < point2d > cart_list)
     //        origin.lon, origin.lat);
     current = rad_list.begin();
     last = rad_list.end();
-    while ( current != last ) {
+    for ( ; current != last ; ++current ) {
 	p = calc_lon_lat(origin_rad, *current);
 	// convert from radians to degress
 	p.lon *= RAD_TO_DEG;
 	p.lat *= RAD_TO_DEG;
 	// printf("(%.8f, %.8f)\n", p.lon, p.lat);
 	result_list.push_back(p);
-	++current;
     }
     // printf("\n");
 
@@ -218,6 +215,11 @@ gen_runway_area( double lon, double lat, double heading,
 
 
 // $Log$
+// Revision 1.4  1998/09/09 20:59:53  curt
+// Loop construct tweaks for STL usage.
+// Output airport file to be used to generate airport scenery on the fly
+//   by the run time sim.
+//
 // Revision 1.3  1998/09/09 16:26:31  curt
 // Continued progress in implementing the convex hull algorithm.
 //
diff --git a/GenAirports/convex_hull.cxx b/GenAirports/convex_hull.cxx
index 75c41c52a..aaa2f499e 100644
--- a/GenAirports/convex_hull.cxx
+++ b/GenAirports/convex_hull.cxx
@@ -94,7 +94,7 @@ bool test_point(point2d Pa, point2d Pb, point2d Pc) {
     a1 = calc_angle(a, b, origin);
     a2 = calc_angle(origin, b, c);
 
-    printf("a1 = %.2f  a2 = %.2f\n", a1 * RAD_TO_DEG, a2 * RAD_TO_DEG);
+    // printf("a1 = %.2f  a2 = %.2f\n", a1 * RAD_TO_DEG, a2 * RAD_TO_DEG);
 
     return ( (a1 + a2) < FG_PI );
 }
@@ -127,29 +127,26 @@ list_container convex_hull( list_container input_list )
     in_count = input_list.size();
     sum_x = sum_y = 0.0;
 
-    while ( current != last ) {
+    for ( ; current != last ; ++current ) {
 	sum_x += (*current).x;
 	sum_y += (*current).y;
-
-	++current;
     }
 
     average.x = sum_x / in_count;
     average.y = sum_y / in_count;
 
-    printf("Average center point is %.4f %.4f\n", average.x, average.y);
+    // printf("Average center point is %.4f %.4f\n", average.x, average.y);
 
     // STEP TWO:  Translate input points so average is at origin
     current = input_list.begin();
     last = input_list.end();
     trans_list.erase( trans_list.begin(), trans_list.end() );
 
-    while ( current != last ) {
+    for ( ; current != last ; ++current ) {
 	p.x = (*current).x - average.x;
 	p.y = (*current).y - average.y;
-	printf("%.6f %.6f\n", p.x, p.y);
+	// printf("%.6f %.6f\n", p.x, p.y);
 	trans_list.push_back(p);
-	++current;
     }
 
     // STEP THREE:  convert to radians and sort by theta
@@ -157,34 +154,31 @@ list_container convex_hull( list_container input_list )
     last = trans_list.end();
     radians_map.erase( radians_map.begin(), radians_map.end() );
 
-    while ( current != last ) {
+    for ( ; current != last ; ++current) {
 	p = cart_to_polar_2d(*current);
 	if ( p.dist > radians_map[p.theta] ) {
 	    radians_map[p.theta] = p.dist;
 	}
-	++current;
     }
 
-    printf("Sorted list\n");
+    // printf("Sorted list\n");
     map_current = radians_map.begin();
     map_last = radians_map.end();
-    while ( map_current != map_last ) {
+    for ( ; map_current != map_last ; ++map_current ) {
 	p.x = (*map_current).first;
 	p.y = (*map_current).second;
 
-	printf("p is %.6f %.6f\n", p.x, p.y);
-
-	++map_current;
+	// printf("p is %.6f %.6f\n", p.x, p.y);
     }
 
     // STEP FOUR: traverse the sorted list and eliminate everything
     // not on the perimeter.
-    printf("Traversing list\n");
+    // printf("Traversing list\n");
 
     // double check list size ... this should never fail because a
     // single runway will always generate four points.
     if ( radians_map.size() < 3 ) {
-	printf("convex hull not possible with < 3 points\n");
+	// printf("convex hull not possible with < 3 points\n");
 	exit(0);
     }
 
@@ -192,7 +186,7 @@ list_container convex_hull( list_container input_list )
     last_size = radians_map.size() + 1;
 
     while ( last_size > radians_map.size() ) {
-	printf("Running an iteration of the graham scan algorithm\n"); 
+	// printf("Running an iteration of the graham scan algorithm\n"); 
 	last_size = radians_map.size();
 
 	map_current = radians_map.begin();
@@ -224,11 +218,11 @@ list_container convex_hull( list_container input_list )
 	    // printf("Pc is %.6f %.6f\n", Pc.theta, Pc.dist);
 
 	    if ( test_point(Pa, Pb, Pc) ) {
-		printf("Accepted a point\n");
+		// printf("Accepted a point\n");
 		// accept point, advance Pa, Pb, and Pc.
 		++map_current;
 	    } else {
-		printf("REJECTED A POINT\n");
+		// printf("REJECTED A POINT\n");
 		// reject point, delete it and advance only Pb and Pc
 		map_next = map_current;
 		++map_next;
@@ -245,18 +239,16 @@ list_container convex_hull( list_container input_list )
     con_hull.erase( con_hull.begin(), con_hull.end() );
     map_current = radians_map.begin();
     map_last = radians_map.end();
-    while ( map_current != map_last ) {
+    for ( ; map_current != map_last ; ++map_current ) {
 	p.theta = (*map_current).first;
 	p.dist = (*map_current).second;
 
 	result.x = cos(p.theta) * p.dist + average.x;
-	result.y = sin(p.theta) * p.dist + average.x;
+	result.y = sin(p.theta) * p.dist + average.y;
 
 	printf("%.6f %.6f\n", result.x, result.y);
 
 	con_hull.push_back(result);
-
-	++map_current;
     }
 
     return con_hull;
@@ -264,6 +256,11 @@ list_container convex_hull( list_container input_list )
 
 
 // $Log$
+// Revision 1.3  1998/09/09 20:59:55  curt
+// Loop construct tweaks for STL usage.
+// Output airport file to be used to generate airport scenery on the fly
+//   by the run time sim.
+//
 // Revision 1.2  1998/09/09 16:26:32  curt
 // Continued progress in implementing the convex hull algorithm.
 //
diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index 0aeee8d25..a363472b8 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -62,14 +62,15 @@ void process_airport( string last_airport, list < string > & runway_list,
     fgBUCKET b;
     long int index;
     char base[256], tmp[256];
-    string path, command, exfile, file;
+    string path, command, exfile, file, aptfile;
     int i, count;
 
     printf( "(apt) %s", last_airport.c_str() );
 
-    while ( runway_list.size() ) {
-	line_str = runway_list.front();
-	runway_list.pop_front();
+    list < string >::iterator last_runway = runway_list.end();
+    for ( list < string >::iterator current_runway = runway_list.begin();
+	  current_runway != last_runway ; ++current_runway ) {
+	line_str = (*current_runway);
 	printf( "%s", line_str.c_str() );
 
 	sscanf( line_str.c_str(), "%lf %lf %d %d %d %s %d %c %d\n",
@@ -83,19 +84,17 @@ void process_airport( string last_airport, list < string > & runway_list,
 	// add rwy_list to apt_list
 	current = rwy_list.begin();
 	last = rwy_list.end();
-	while ( current != last ) {
+	for ( ; current != last ; ++current ) {
 	    apt_list.push_back(*current);
-	    ++current;
 	}
     }
 
     printf("Runway points in degrees\n");
     current = apt_list.begin();
     last = apt_list.end();
-    while ( current != last ) {
+    for ( ; current != last; ++current ) {
 	// printf( "(%.4f, %.4f)\n", 
 	printf( "%.5f %.5f\n", current->lon, current->lat );
-	++current;
     }
     printf("\n");
 
@@ -108,20 +107,19 @@ void process_airport( string last_airport, list < string > & runway_list,
     current = hull_list.begin();
     last = hull_list.end();
     sum_x = sum_y = 0.0;
-    while ( current != last ) {
+    for ( ; current != last; ++current ) {
+	// printf("return = %.6f %.6f\n", (*current).x, (*current).y);
 	sum_x += (*current).x;
 	sum_y += (*current).y;
-
-	++current;
     }
 
     average.x = sum_x / count;
     average.y = sum_y / count;
 
-    // find bucket based on first point in hull list.  Eventually
-    // we'll need to handle cases where the area crosses bucket
-    // boundaries.
-    fgBucketFind( (*current).lon, (*current).lat, &b);
+    // find bucket based on average center point of hull list.
+    // Eventually we'll need to handle cases where the area crosses
+    // bucket boundaries.
+    fgBucketFind( average.lon, average.lat, &b);
     printf( "Bucket = lon,lat = %d,%d  x,y index = %d,%d\n", 
 	    b.lon, b.lat, b.x, b.y);
 
@@ -132,10 +130,12 @@ void process_airport( string last_airport, list < string > & runway_list,
     system( command.c_str() );
 
     sprintf(tmp, "%ld", index);
-    exfile = path + "/" + tmp + ".node.ex";
-    file =   path + "/" + tmp + ".poly";
+    exfile =  path + "/" + tmp + ".node.ex";
+    file =    path + "/" + tmp + ".poly";
+    aptfile = path + "/" + tmp + ".apt";
     printf( "extra node file = %s\n", exfile.c_str() );
     printf( "poly file = %s\n", file.c_str() );
+    printf( "apt file = %s\n", aptfile.c_str() );
 
     // output exclude nodes
     printf("Output exclude nodes\n");
@@ -149,16 +149,17 @@ void process_airport( string last_airport, list < string > & runway_list,
     current = hull_list.begin();
     last = hull_list.end();
     i = 1;
-    while ( current != last ) {
+    for ( ; current != last ; ++current ) {
 	// printf( "(%.4f, %.4f)\n", 
 	fprintf( fd, "%d %.2f %.2f %.2f\n", i, 
-		 (*current).lon * 3600.0, (*current).lat * 3600.0, elev);
-	++current;
+		 (*current).lon * 3600.0, (*current).lat * 3600.0, 
+		 (double)elev * FEET_TO_METER );
 	++i;
     }
     fclose(fd);
 
     // output poly
+    printf("Output poly\n");
     if ( (fd = fopen(file.c_str(), "w")) == NULL ) {
         printf("Cannot open file: %s\n", file.c_str());
         exit(-1);
@@ -179,6 +180,34 @@ void process_airport( string last_airport, list < string > & runway_list,
     fprintf( fd, "1 %.2f %.2f\n", average.x * 3600.0, average.y * 3600);
 
     fclose(fd);
+
+    // output "apt" file
+    printf("Output airport\n");
+    if ( (fd = fopen(aptfile.c_str(), "w")) == NULL ) {
+        printf("Cannot open file: %s\n", aptfile.c_str());
+        exit(-1);
+    }
+
+    // write main airport identifier
+    fprintf(fd, "a %s", last_airport.c_str() );
+
+    // write perimeter polygon
+    current = hull_list.begin();
+    last = hull_list.end();
+    for ( ; current != last ; ++current ) {
+	fprintf( fd, "p %.7f %.7f %.2f\n", (*current).lon, (*current).lat, 
+		 (double)elev * FEET_TO_METER );
+    }
+
+    // write runway info
+    for ( list < string >::iterator current_runway = runway_list.begin();
+	  current_runway != last_runway ; ++current_runway ) {
+	line_str = (*current_runway);
+	line_str = line_str.substr(1, line_str.size());
+	fprintf(fd, "r %s", line_str.c_str() );
+    }
+
+    fclose(fd);
 }
 
 
@@ -233,6 +262,9 @@ int main( int argc, char **argv ) {
 		process_airport(last_airport, runway_list, argv[2]);
 	    }
 
+	    // clear runway list for start of next airport
+	    runway_list.erase(runway_list.begin(), runway_list.end());
+
 	    last_airport = airport;
 	}
     }
@@ -248,78 +280,10 @@ int main( int argc, char **argv ) {
 }
 
 
-#if 0
-    // P13 (Globe, AZ)
-    // lon = -110.6642442;
-    // lat = 33.3528903;
-    // heading = 102.0 * DEG_TO_RAD;
-    // length = 1769;
-    // width = 23;
-
-    // KANE
-    lon = -93.2113889;
-    lat = 45.145;
-    elevation = 912 * FEET_TO_METER;
-    heading = 270.0 * DEG_TO_RAD;
-    length = 1220;
-    width = 23;
-
-    gen_runway_area( lon * DEG_TO_RAD, lat * DEG_TO_RAD, 
-		     heading, length, width, nodes, &count );
-
-    fgBucketFind(lon, lat, &b);
-    printf( "Bucket = lon,lat = %d,%d  x,y index = %d,%d\n", 
-	    b.lon, b.lat, b.x, b.y);
-
-    index = fgBucketGenIndex(&b);
-    fgBucketGenBasePath(&b, base);
-    sprintf(path, "%s/Scenery/%s", argv[1], base);
-    sprintf(command, "mkdir -p %s\n", path);
-    system(command);
-    
-    sprintf(exfile, "%s/%ld.node.ex", path, index);
-    sprintf(file, "%s/%ld.poly", path, index);
-    printf( "extra node file = %s\n", exfile);
-    printf( "poly file = %s\n", file);
-
-    // output extra nodes
-    if ( (fd = fopen(exfile, "w")) == NULL ) {
-        printf("Cannot open file: %s\n", exfile);
-        exit(-1);
-    }
-
-    fprintf(fd, "%d 2 0 0\n", count);
-    for ( i = 0; i < count; i++ ) {
-	fprintf( fd, "%d %.2f %.2f %.2f\n", i + 1, 
-		 nodes[i].lon * RAD_TO_ARCSEC, nodes[i].lat * RAD_TO_ARCSEC, 
-		 elevation);
-    }
-    fclose(fd);
-
-    // output poly
-    if ( (fd = fopen(file, "w")) == NULL ) {
-        printf("Cannot open file: %s\n", file);
-        exit(-1);
-    }
-
-    // output empty node list
-    fprintf(fd, "0 2 0 0\n");
-
-    // output segments
-    fprintf(fd, "%d 0\n", count);
-    for ( i = 0; i < count - 1; i++ ) {
-	fprintf( fd, "%d %d %d\n", i + 1, i + 1, i + 2 );
-    }
-    fprintf( fd, "%d %d %d\n", count, count, 1 );
-
-    // output hole center
-    fprintf( fd, "1\n");
-    fprintf( fd, "1 %.2f %.2f\n", lon * 3600.0, lat * 3600);
-
-    fclose(fd);
-
-#endif
-
-
-// $Log: main.c,v
+// $Log$
+// Revision 1.4  1998/09/09 20:59:56  curt
+// Loop construct tweaks for STL usage.
+// Output airport file to be used to generate airport scenery on the fly
+//   by the run time sim.
+//
 //

From 52a1d87c1c367e854adb8c89cf11a6ea3a5a058d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 17 Sep 1998 18:40:15 +0000
Subject: [PATCH 141/283] Changes to allow multiple copies of the scenery
 processing tools to be run concurrently.

---
 Stripe_w/bands.c     | 36 +++++++++++++++++++-----------------
 Stripe_w/options.c   |  2 +-
 Tools/process-dem.pl | 34 ++++++++++++++++++++--------------
 3 files changed, 40 insertions(+), 32 deletions(-)

diff --git a/Stripe_w/bands.c b/Stripe_w/bands.c
index 981c13255..1992795a6 100644
--- a/Stripe_w/bands.c
+++ b/Stripe_w/bands.c
@@ -93,7 +93,7 @@ void get_time()
 
 int main (int argc,char *argv[])
 {
-  char	*fname,*all,buff[255], *ptr, *ptr2;
+  char	*fname, *oname, *all,buff[255], *ptr, *ptr2;
 	FILE	*file, *bands;
 	int face_id=0;
   int vert_count=0;
@@ -125,27 +125,29 @@ int main (int argc,char *argv[])
 
   get_time();
 
-  /*   File that will contain the triangle strip data */
-  bands = fopen("stripe.objf","w");
-
   /*
-	Scan the file once to find out the number of vertices,
-	vertice normals, and faces so we can set up some memory
-	structures 
-	*/
-	/* Interpret the options specified */
-	norm_difference = get_options(argc,argv,&f,&t,&tr,&g);
+    Scan the file once to find out the number of vertices,
+    vertice normals, and faces so we can set up some memory
+    structures 
+    */
+  /* Interpret the options specified */
+  norm_difference = get_options(argc,argv,&f,&t,&tr,&g);
   if (f == BINARY)
-    file_open = "rb";
+      file_open = "rb";
   else
-    file_open = "r";
-
-	fname = argv[argc-1];
-
-  printf ("File: %s\n",fname);
-	printf ("Scanning...%s ",file_open);
+      file_open = "r";
+  
+  fname = argv[argc-2];
+  oname = argv[argc-1];
+  
+  printf ("Input file: %s  Output file: %s\n", fname, oname);
+  printf ("Scanning...%s ",file_open);
 
 	    
+  /*   File that will contain the triangle strip data */
+  
+  bands = fopen(oname, "w");
+
   /*   File can be in binary for faster reading */
   if (file = fopen (fname,file_open))
 	{
diff --git a/Stripe_w/options.c b/Stripe_w/options.c
index cbc9d4e15..7e1243e24 100644
--- a/Stripe_w/options.c
+++ b/Stripe_w/options.c
@@ -84,7 +84,7 @@ double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group)
      /*      User has the wrong number of options */
 	if ((argc > 5) || (argc < 2))
 	{
-		printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] file_name\n");
+		printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] in_file_name out_file_name\n");
 		exit(0);
 	}
 	
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index ad791d10d..d81f53b4a 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -30,7 +30,7 @@
 $scenery_format_version = "0.1";
 
 $max_area = 10000;            # maximum triangle area
-$remove_tmps = 0;
+$remove_tmps = 1;
 
 $| = 1;                         # flush buffers after every write
 
@@ -360,16 +360,18 @@ sub tri2obj {
 #     Strip the file.1.obj's.  Note, strips doesn't handle the minimal
 #     case of striping a square correctly.
 #
-# 7.  cp bands.d file.2.obj
+# 7.  cp stripe.objf file.2.obj
 #
-#     strips produces a file called "bands.d" ... copy this to file.2.obj
+#     strips produces a file called "stripe.objf" ... copy this to file.2.obj
 
 sub strips {
     @FILES = `ls $subdir`;
     foreach $file ( @FILES ) {
 	chop($file);
 	if ( $file =~ m/\.1\.obj$/ ) {
-	    $command = "Stripe_w/strips $subdir/$file";
+	    $newfile = $file;
+	    $newfile =~ s/\.1\.obj$//;
+	    $command = "Stripe_w/strips $subdir/$file $subdir/$newfile.2.obj";
 	    $command = fix_command($command);
 	    print "Running '$command'\n";
     	    # $input = <STDIN>;
@@ -380,17 +382,17 @@ sub strips {
 	    close(OUT);
 	    
 	    # copy to destination file
-	    $newfile = $file;
-	    $newfile =~ s/\.1\.obj$//;
-	    print "Copying to $subdir/$newfile.2.obj\n";
+	    # $newfile = $file;
+	    # $newfile =~ s/\.1\.obj$//;
+	    # print "Copying to $subdir/$newfile.2.obj\n";
 	    # open(IN, "<bands.d");
-	    open(IN, "<stripe.objf");
-	    open(OUT, ">$subdir/$newfile.2.obj");
-	    while ( <IN> ) {
-		print OUT $_;
-	    }
-	    close(IN);
-	    close(OUT);
+	    # open(IN, "<stripe.objf");
+	    # open(OUT, ">$subdir/$newfile.2.obj");
+	    # while ( <IN> ) {
+		# print OUT $_;
+	    # }
+	    # close(IN);
+	    # close(OUT);
 	    
 	    if ( $remove_tmps ) {
 		unlink("$subdir/$file");
@@ -487,6 +489,10 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.28  1998/09/17 18:40:15  curt
+# Changes to allow multiple copies of the scenery processing tools
+# to be run concurrently.
+#
 # Revision 1.27  1998/09/09 20:58:35  curt
 # Fixes and tweaks to handle area cutouts for airports.
 #

From a0a32fccea6dd4612da7eab8ec549d7d5fd5a507 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 17 Sep 1998 18:40:42 +0000
Subject: [PATCH 142/283] Debug message tweaks.

---
 GenAirports/convex_hull.cxx |  7 +++++--
 GenAirports/main.cxx        | 10 ++++++----
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/GenAirports/convex_hull.cxx b/GenAirports/convex_hull.cxx
index aaa2f499e..5905c4922 100644
--- a/GenAirports/convex_hull.cxx
+++ b/GenAirports/convex_hull.cxx
@@ -235,7 +235,7 @@ list_container convex_hull( list_container input_list )
     }
 
     // translate back to correct lon/lat
-    printf("Final sorted convex hull\n");
+    // printf("Final sorted convex hull\n");
     con_hull.erase( con_hull.begin(), con_hull.end() );
     map_current = radians_map.begin();
     map_last = radians_map.end();
@@ -246,7 +246,7 @@ list_container convex_hull( list_container input_list )
 	result.x = cos(p.theta) * p.dist + average.x;
 	result.y = sin(p.theta) * p.dist + average.y;
 
-	printf("%.6f %.6f\n", result.x, result.y);
+	// printf("%.6f %.6f\n", result.x, result.y);
 
 	con_hull.push_back(result);
     }
@@ -256,6 +256,9 @@ list_container convex_hull( list_container input_list )
 
 
 // $Log$
+// Revision 1.4  1998/09/17 18:40:42  curt
+// Debug message tweaks.
+//
 // Revision 1.3  1998/09/09 20:59:55  curt
 // Loop construct tweaks for STL usage.
 // Output airport file to be used to generate airport scenery on the fly
diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index a363472b8..475ae10ea 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -89,14 +89,13 @@ void process_airport( string last_airport, list < string > & runway_list,
 	}
     }
 
-    printf("Runway points in degrees\n");
+    // printf("Runway points in degrees\n");
     current = apt_list.begin();
     last = apt_list.end();
     for ( ; current != last; ++current ) {
-	// printf( "(%.4f, %.4f)\n", 
-	printf( "%.5f %.5f\n", current->lon, current->lat );
+	// printf( "%.5f %.5f\n", current->lon, current->lat );
     }
-    printf("\n");
+    // printf("\n");
 
     // generate convex hull
     hull_list = convex_hull(apt_list);
@@ -281,6 +280,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.5  1998/09/17 18:40:43  curt
+// Debug message tweaks.
+//
 // Revision 1.4  1998/09/09 20:59:56  curt
 // Loop construct tweaks for STL usage.
 // Output airport file to be used to generate airport scenery on the fly

From 4b0aa0e3a65b27a6ce6868cf53626fc7bc0e212b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 19 Sep 1998 17:59:45 +0000
Subject: [PATCH 143/283] Use c++ streams (fg_gzifstream).  Also converted many
 character arrays to the string class.

---
 DEM/dem.cxx | 281 ++++++++++++++++++++++++++--------------------------
 DEM/dem.hxx |  35 +++++--
 2 files changed, 166 insertions(+), 150 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 21e8ebc1d..73bce2be1 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -36,7 +36,11 @@
 #include <sys/stat.h> // stat()
 #include <unistd.h>   // stat()
 
-#include <zlib/zlib.h>
+#include <string>
+
+// #include <zlib/zlib.h>
+#include <Misc/fgstream.hxx>
+#include <Misc/strutils.hxx>
 
 #include "dem.hxx"
 #include "leastsqs.hxx"
@@ -61,7 +65,7 @@ fgDEM::fgDEM( void ) {
 #ifdef WIN32
 
 // return the file path name ( foo/bar/file.ext = foo/bar )
-void extract_path (char *in, char *base) {
+static void extract_path (char *in, char *base) {
     int len, i;
     
     len = strlen (in);
@@ -77,7 +81,7 @@ void extract_path (char *in, char *base) {
 
 
 // Make a subdirectory
-int my_mkdir (char *dir) {
+static int my_mkdir (char *dir) {
     struct stat stat_buf;
     int result;
 
@@ -104,89 +108,81 @@ int my_mkdir (char *dir) {
 
 
 // open a DEM file
-int fgDEM::open ( char *file ) {
+int fgDEM::open ( const string& file ) {
     // open input file (or read from stdin)
-    if ( strcmp(file, "-") == 0 ) {
+    if ( file ==  "-" ) {
 	printf("Loading DEM data file: stdin\n");
 	// fd = stdin;
-	fd = gzdopen(STDIN_FILENO, "r");
+	// fd = gzdopen(STDIN_FILENO, "r");
+	printf("Not yet ported ...\n");
+	return 0;
     } else {
-	if ( (fd = gzopen(file, "rb")) == NULL ) {
-	    printf("Cannot gzopen %s\n", file);
-	    return(0);
+	in = new fg_gzifstream( file );
+	if ( !in ) {
+	    cout << "Cannot open " + file + "\n";
+	    return 0;
 	}
-	printf("Loading DEM data file: %s\n", file);
+	cout << "Loading DEM data file: " + file + "\n";
     }
 
-    return(1);
+    return 1;
 }
 
 
 // close a DEM file
-int fgDEM::close ( void ) {
-    gzclose(fd);
+int fgDEM::close () {
+    // the fg_gzifstream doesn't seem to have a close()
 
-    return(1);
+    delete(in);
+
+    return 1;
 }
 
 
 // return next token from input stream
-static void next_token(gzFile fd, char *token) {
-    int i, result;
-    char c;
+string fgDEM::next_token() {
+    string token;
 
-    i = 0;
-    c = gzgetc(fd);
-    // skip past spaces
-    while ( (c != -1) && (c == ' ') ) {
-	c = gzgetc(fd);
-    }
-    while ( (c != -1) && (c != ' ') && (c != '\n') ){
-	token[i] = c;
-	i++;
-	c = gzgetc(fd);
-    }
-    token[i] = '\0';
+    in->stream() >> token;
 
-    if ( c == -1 ) {
-	strcpy(token, "__END_OF_FILE__");
-	printf("    Warning:  Reached end of file!\n");
-    }
+    cout << "    returning " + token + "\n";
 
-    // printf("    returning %s\n", token);
+    return token;
 }
 
 
 // return next integer from input stream
-static int next_int(gzFile fd) {
-    char token[80];
+int fgDEM::next_int() {
+    int result;
 
-    next_token(fd, token);
-    return ( atoi(token) );
+    in->stream() >> result;
+
+    return result;
 }
 
 
 // return next double from input stream
-static double next_double(gzFile fd) {
-    char token[80];
+double fgDEM::next_double() {
+    double result;
 
-    next_token(fd, token);
-    return ( atof(token) );
+    in->stream() >> result;
+
+    return result;
 }
 
 
 // return next exponential num from input stream
-static int next_exp(gzFile fd) {
-    char token[80];
+int fgDEM::next_exp() {
+    string token;
     double mantissa;
     int exp, acc;
     int i;
 
-    next_token(fd, token);
+    token = next_token();
 
-    sscanf(token, "%lfD%d", &mantissa, &exp);
+    sscanf(token.c_str(), "%lfD%d", &mantissa, &exp);
 
-    // printf("    Mantissa = %.4f  Exp = %d\n", mantissa, exp);
+    cout << "    Mantissa = " << mantissa << "  Exp = " << exp << "\n";
 
     acc = 1;
     if ( exp > 0 ) {
@@ -204,103 +200,97 @@ static int next_exp(gzFile fd) {
 
 
 // read and parse DEM "A" record
-int fgDEM::read_a_record( void ) {
+int fgDEM::read_a_record() {
     int i, inum;
     double dnum;
-    char name[256];
-    char token[80];
+    string name, token;
+    char c;
     char *ptr;
 
     // get the name field (144 characters)
     for ( i = 0; i < 144; i++ ) {
-	name[i] = gzgetc(fd);
+	in->get(c);
+	name += c;
     }
-    name[i+1] = '\0';
-
-    // clean off the whitespace at the end
-    for ( i = strlen(name)-2; i > 0; i-- ) {
-	if ( !isspace(name[i]) ) {
-	    i=0;
-	} else {
-	    name[i] = '\0'; 
-	}
-    }
-    printf("    Quad name field: %s\n", name);
+  
+    // clean off the trailing whitespace
+    name = trimleft(name);
+    cout << "    Quad name field: " + name + "\n";
 
     // DEM level code, 3 reflects processing by DMA
-    inum = next_int(fd);
-    printf("    DEM level code = %d\n", inum);
+    inum = next_int();
+    cout << "    DEM level code = " << inum << "\n";
 
     if ( inum > 3 ) {
-	return(0);
+	return 0;
     }
 
     // Pattern code, 1 indicates a regular elevation pattern
-    inum = next_int(fd);
-    printf("    Pattern code = %d\n", inum);
+    inum = next_int();
+    cout << "    Pattern code = " << inum << "\n";
 
     // Planimetric reference system code, 0 indicates geographic
     // coordinate system.
-    inum = next_int(fd);
-    printf("    Planimetric reference code = %d\n", inum);
+    inum = next_int();
+    cout << "    Planimetric reference code = " << inum << "\n";
 
     // Zone code
-    inum = next_int(fd);
-    printf("    Zone code = %d\n", inum);
+    inum = next_int();
+    cout << "    Zone code = " << inum << "\n";
 
     // Map projection parameters (ignored)
     for ( i = 0; i < 15; i++ ) {
-	dnum = next_double(fd);
+	dnum = next_double();
 	// printf("%d: %f\n",i,dnum);
     }
 
     // Units code, 3 represents arc-seconds as the unit of measure for
     // ground planimetric coordinates throughout the file.
-    inum = next_int(fd);
+    inum = next_int();
     if ( inum != 3 ) {
-	printf("    Unknown (X,Y) units code = %d!\n", inum);
+	cout << "    Unknown (X,Y) units code = " << inum << "!\n";
 	exit(-1);
     }
 
     // Units code; 2 represents meters as the unit of measure for
     // elevation coordinates throughout the file.
-    inum = next_int(fd);
+    inum = next_int();
     if ( inum != 2 ) {
-	printf("    Unknown (Z) units code = %d!\n", inum);
+	cout << "    Unknown (Z) units code = " << inum << "!\n";
 	exit(-1);
     }
 
     // Number (n) of sides in the polygon which defines the coverage of
     // the DEM file (usually equal to 4).
-    inum = next_int(fd);
+    inum = next_int();
     if ( inum != 4 ) {
-	printf("    Unknown polygon dimension = %d!\n", inum);
+	cout << "    Unknown polygon dimension = " << inum << "!\n";
 	exit(-1);
     }
 
     // Ground coordinates of bounding box in arc-seconds
-    dem_x1 = originx = next_exp(fd);
-    dem_y1 = originy = next_exp(fd);
-    printf("    Origin = (%.2f,%.2f)\n", originx, originy);
+    dem_x1 = originx = next_exp();
+    dem_y1 = originy = next_exp();
+    cout << "    Origin = (" << originx << "," << originy << ")\n";
 
-    dem_x2 = next_exp(fd);
-    dem_y2 = next_exp(fd);
+    dem_x2 = next_exp();
+    dem_y2 = next_exp();
 
-    dem_x3 = next_exp(fd);
-    dem_y3 = next_exp(fd);
+    dem_x3 = next_exp();
+    dem_y3 = next_exp();
 
-    dem_x4 = next_exp(fd);
-    dem_y4 = next_exp(fd);
+    dem_x4 = next_exp();
+    dem_y4 = next_exp();
 
     // Minimum/maximum elevations in meters
-    dem_z1 = next_exp(fd);
-    dem_z2 = next_exp(fd);
-    printf("    Elevation range %.4f %.4f\n", dem_z1, dem_z2);
+    dem_z1 = next_exp();
+    dem_z2 = next_exp();
+    cout << "    Elevation range " << dem_z1 << dem_z2 << "\n";
 
     // Counterclockwise angle from the primary axis of ground
     // planimetric referenced to the primary axis of the DEM local
     // reference system.
-    next_token(fd, token);
+    token = next_token();
 
     // Accuracy code; 0 indicates that a record of accuracy does not
     // exist and that no record type C will follow.
@@ -310,81 +300,83 @@ int fgDEM::read_a_record( void ) {
 
     // I will eventually have to do something with this for data at
     // higher latitudes */
-    next_token(fd, token);
-    printf("    accuracy & spacial resolution string = %s\n", token);
-    i = strlen(token);
-    printf("    length = %d\n", i);
+    token = next_token();
+    cout << "    accuracy & spacial resolution string = " + token + "\n";
+    i = token.length();
+    cout << "    length = " << i << "\n";
 
-    ptr = token + i - 12;
-    printf("    last field = %s = %.2f\n", ptr, atof(ptr));
+    ptr = token.c_str() + i - 12;
+    cout << "    last field = " << ptr << " = " << atof(ptr) << "\n";
     ptr[0] = '\0';
 
     ptr = ptr - 12;
     col_step = atof(ptr);
-    printf("    last field = %s = %.2f\n", ptr, col_step);
+    cout << "    last field = " << ptr << " = " << col_step << "\n";
     ptr[0] = '\0';
 
     ptr = ptr - 12;
     row_step = atof(ptr);
-    printf("    last field = %s = %.2f\n", ptr, row_step);
+    cout << "    last field = " << ptr << " = " << row_step << "\n";
     ptr[0] = '\0';
 
     // accuracy code = atod(token)
-    inum = atoi(token);
-    printf("    Accuracy code = %d\n", inum);
+    ptr = ptr - 12;
+    inum = atoi(ptr);
+    cout << "    Accuracy code = " << inum << "\n";
+
+    cout << "    column step = " << col_step << 
+	"  row step = " << row_step << "\n";
 
-    printf("    column step = %.2f  row step = %.2f\n", 
-	   col_step, row_step);
     // dimension of arrays to follow (1)
-    next_token(fd, token);
+    token = next_token();
 
     // number of profiles
-    dem_num_profiles = cols = next_int(fd);
-    printf("    Expecting %d profiles\n", dem_num_profiles);
+    dem_num_profiles = cols = next_int();
+    cout << "    Expecting " << dem_num_profiles << " profiles\n";
 
-    return(1);
+    return 1;
 }
 
 
 // read and parse DEM "B" record
-void fgDEM::read_b_record( void ) {
-    char token[80];
+void fgDEM::read_b_record( ) {
+    string token;
     int i;
 
     // row / column id of this profile
-    prof_row = next_int(fd);
-    prof_col = next_int(fd);
+    prof_row = next_int();
+    prof_col = next_int();
     // printf("col id = %d  row id = %d\n", prof_col, prof_row);
 
     // Number of columns and rows (elevations) in this profile
-    prof_num_rows = rows = next_int(fd);
-    prof_num_cols = next_int(fd);
+    prof_num_rows = rows = next_int();
+    prof_num_cols = next_int();
     // printf("    profile num rows = %d\n", prof_num_rows);
 
     // Ground planimetric coordinates (arc-seconds) of the first
     // elevation in the profile
-    prof_x1 = next_exp(fd);
-    prof_y1 = next_exp(fd);
+    prof_x1 = next_exp();
+    prof_y1 = next_exp();
     // printf("    Starting at %.2f %.2f\n", prof_x1, prof_y1);
 
     // Elevation of local datum for the profile.  Always zero for
     // 1-degree DEM, the reference is mean sea level.
-    next_token(fd, token);
+    token = next_token();
 
     // Minimum and maximum elevations for the profile.
-    next_token(fd, token);
-    next_token(fd, token);
+    token = next_token();
+    token = next_token();
 
     // One (usually) dimensional array (prof_num_cols,1) of elevations
     for ( i = 0; i < prof_num_rows; i++ ) {
-	prof_data = next_int(fd);
+	prof_data = next_int();
 	dem_data[cur_col][i] = (float)prof_data;
     }
 }
 
 
 // parse dem file
-int fgDEM::parse( void ) {
+int fgDEM::parse( ) {
     int i;
 
     cur_col = 0;
@@ -399,13 +391,13 @@ int fgDEM::parse( void ) {
 	cur_col++;
 
 	if ( cur_col % 100 == 0 ) {
-	    printf("    loaded %d profiles of data\n", cur_col);
+	    cout << "    loaded " << cur_col << "profiles of data\n";
 	}
     }
 
-    printf("    Done parsing\n");
+    cout << "    Done parsing\n";
 
-    return(1);
+    return 1;
 }
 
 
@@ -687,15 +679,16 @@ void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
 // Check for an optional "index.node.ex" file in case there is a .poly
 // file to go along with this node file.  Include these nodes first
 // since they are referenced by position from the .poly file.
-void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
+void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
     double exnodes[MAX_EX_NODES][3];
     double junk1, junk2, junk3;
     struct stat stat_buf;
-    char base_path[256], dir[256], file[256], exfile[256];
+    string dir;
+    char base_path[256], file[256], exfile[256];
 #ifdef WIN32
     char tmp_path[256];
 #endif
-    char command[256];
+    string command;
     FILE *fd;
     long int index;
     int colmin, colmax, rowmin, rowmax;
@@ -706,24 +699,24 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
     colmax = colmin + ( (cols - 1) / 8);
     rowmin = p->y * ( (rows - 1) / 8);
     rowmax = rowmin + ( (rows - 1) / 8);
-    printf("  dumping region = %d,%d to %d,%d\n", 
-	   colmin, rowmin, colmax, rowmax);
+    cout << "  dumping region = " << colmin << "," << rowmin << " to " <<
+	colmax << "," << rowmax << "\n";
 
     // generate the base directory
     fgBucketGenBasePath(p, base_path);
-    printf("fg_root = %s  Base Path = %s\n", fg_root, base_path);
-    sprintf(dir, "%s/Scenery/%s", fg_root, base_path);
-    printf("Dir = %s\n", dir);
+    cout << "fg_root = " + fg_root + "  Base Path = " + base_path + "\n";
+    dir = fg_root + "/Scenery/" + base_path;
+    cout << "Dir = " + dir + "\n";
     
     // stat() directory and create if needed
-    result = stat(dir, &stat_buf);
+    result = stat(dir.c_str(), &stat_buf);
     if ( result != 0 ) {
-	printf("Stat error need to create directory\n");
+	cout << "Stat error need to create directory\n";
 
 #ifndef WIN32
 
-	sprintf(command, "mkdir -p %s\n", dir);
-	system(command);
+	command = "mkdir -p " + dir + "\n";
+	system( command.c_str() );
 
 #else // WIN32
 
@@ -732,14 +725,14 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
 
 	extract_path (base_path, tmp_path);
 
-	sprintf (dir, "%s/Scenery", fg_root);
-	if (my_mkdir (dir)) { exit (-1); }
+	dir = fg_root + "/Scenery";
+	if (my_mkdir ( dir.c_str() )) { exit (-1); }
 
-	sprintf (dir, "%s/Scenery/%s", fg_root, tmp_path);
-	if (my_mkdir (dir)) { exit (-1); }
+	dir += fg_root + "/Scenery/" + tmp_path;
+	if (my_mkdir ( dir.c_str() )) { exit (-1); }
 
-	sprintf (dir, "%s/Scenery/%s", fg_root, base_path);
-	if (my_mkdir (dir)) { exit (-1); }
+	dir += fg_root + "/Scenery/" + base_path;
+	if (my_mkdir ( dir.c_str() )) { exit (-1); }
 
 #endif // WIN32
 
@@ -749,7 +742,7 @@ void fgDEM::outputmesh_output_nodes( char *fg_root, fgBUCKET *p ) {
 
     // get index and generate output file name
     index = fgBucketGenIndex(p);
-    sprintf(file, "%s/%ld.node", dir, index);
+    sprintf(file, "%s/%ld.node", dir.c_str(), index);
 
     // get (optional) extra node file name (in case there is matching
     // .poly file.
@@ -825,6 +818,10 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.14  1998/09/19 17:59:45  curt
+// Use c++ streams (fg_gzifstream).  Also converted many character arrays to
+// the string class.
+//
 // Revision 1.13  1998/09/09 16:24:04  curt
 // Fixed a bug in the handling of exclude files which was causing
 // a crash by calling fclose() on an invalid file handle.
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 33eefc248..de96a3700 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -36,7 +36,9 @@
 #include <stdio.h>
 
 #include <Bucket/bucketutils.h>
-#include <zlib/zlib.h>
+
+//#include <zlib/zlib.h>
+#include <Misc/fgstream.hxx>
 
 
 #define DEM_SIZE 1200
@@ -45,7 +47,8 @@
 
 class fgDEM {
     // file pointer for input
-    gzFile fd;
+    // gzFile fd;
+    fg_gzifstream *in;
 
     // coordinates (in arc seconds) of south west corner
     double originx, originy;
@@ -77,25 +80,37 @@ class fgDEM {
     int do_data;
     int cur_col, cur_row;
 
+    // return next token from input stream
+    string next_token();
+
+    // return next integer from input stream
+    int next_int();
+
+    // return next double from input stream
+    double next_double();
+
+    // return next exponential num from input stream
+    int next_exp();
+
 public:
 
     // Constructor
     fgDEM( void );
 
     // open a DEM file (use "-" if input is coming from stdin)
-    int open ( char *file );
+    int open ( const string& file );
 
     // close a DEM file
-    int close ( void );
+    int close ();
 
     // parse a DEM file
-    int parse( void );
+    int parse();
 
     // read and parse DEM "A" record
-    int read_a_record( void );
+    int read_a_record();
 
     // read and parse DEM "B" record
-    void read_b_record( void );
+    void read_b_record();
 
     // Informational methods
     double info_originx( void ) { return(originx); }
@@ -119,7 +134,7 @@ public:
     void outputmesh_set_pt( int i, int j, double value );
 
     // Write out a node file that can be used by the "triangle" program
-    void outputmesh_output_nodes( char *fg_root, fgBUCKET *p );
+    void outputmesh_output_nodes( const string& fg_root, fgBUCKET *p );
 
     // Destructor
     ~fgDEM( void );
@@ -130,6 +145,10 @@ public:
 
 
 // $Log$
+// Revision 1.8  1998/09/19 17:59:46  curt
+// Use c++ streams (fg_gzifstream).  Also converted many character arrays to
+// the string class.
+//
 // Revision 1.7  1998/07/04 00:47:19  curt
 // typedef'd struct fgBUCKET.
 //

From 192edc5eaf5d8185aed2501aa0a0454d5b2c2cd4 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 19 Sep 1998 18:01:21 +0000
Subject: [PATCH 144/283] Support for changes to libDEM.a

---
 DemInfo/Makefile.am |  4 ++++
 DemInfo/deminfo.cxx | 18 ++++++++++--------
 FixNode/Makefile.am |  4 ++++
 FixNode/main.cxx    | 34 ++++++++++++++++++----------------
 4 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/DemInfo/Makefile.am b/DemInfo/Makefile.am
index 0ec8323d0..aa73af873 100644
--- a/DemInfo/Makefile.am
+++ b/DemInfo/Makefile.am
@@ -32,6 +32,7 @@ deminfo_SOURCES = \
 deminfo_LDADD = \
 	$(top_builddir)/Lib/DEM/libDEM.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
@@ -44,6 +45,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/09/19 18:01:21  curt
+# Support for changes to libDEM.a
+#
 # Revision 1.2  1998/07/30 23:49:24  curt
 # Removed libtool support.
 #
diff --git a/DemInfo/deminfo.cxx b/DemInfo/deminfo.cxx
index 9af81a9dd..27f1f4357 100644
--- a/DemInfo/deminfo.cxx
+++ b/DemInfo/deminfo.cxx
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <string>
 
 #include <DEM/dem.hxx>
 
@@ -37,8 +38,7 @@
 int main(int argc, char **argv) {
     // DEM data
     fgDEM dem;
-    char fg_root[256];
-    char filename[256];
+    string filename;
     double error;
     int i, j;
 
@@ -48,17 +48,16 @@ int main(int argc, char **argv) {
     }
 
     // set input dem file name
-    strcpy(filename, argv[1]);
+    filename = argv[1];
 
     dem.open(filename);
 
     if ( dem.read_a_record() ) {
-	printf("Results = %s  %.1f %.1f\n", 
-	       filename, 
-	       dem.info_originx() / 3600.0,
-	       dem.info_originy() / 3600.0 ) ;
+	cout << "Results = " << filename << "  "
+	     << dem.info_originx() / 3600.0 << " "
+	     << dem.info_originy() / 3600.0 << "\n";
     } else {
-	printf("Error parsing DEM file.\n");
+	cout << "Error parsing DEM file.\n";
     }
 
     dem.close();
@@ -68,6 +67,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.2  1998/09/19 18:01:22  curt
+// Support for changes to libDEM.a
+//
 // Revision 1.1  1998/06/04 19:18:05  curt
 // Initial revision.
 //
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index b44b9b6d7..f9224f1a3 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -34,6 +34,7 @@ fixnode_SOURCES = \
 fixnode_LDADD = \
 	$(top_builddir)/Lib/DEM/libDEM.a \
         $(top_builddir)/Lib/Bucket/libBucket.a \
+        $(top_builddir)/Lib/Misc/libMisc.a \
         $(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
@@ -46,6 +47,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/09/19 18:01:26  curt
+# Support for changes to libDEM.a
+#
 # Revision 1.4  1998/07/30 23:49:24  curt
 # Removed libtool support.
 #
diff --git a/FixNode/main.cxx b/FixNode/main.cxx
index 92441ec8e..4adaa97d0 100644
--- a/FixNode/main.cxx
+++ b/FixNode/main.cxx
@@ -1,5 +1,5 @@
-// main.c -- read in a .node file and fix the z values of the interpolated 
-//           points
+// main.cxx -- read in a .node file and fix the z values of the interpolated 
+//             points
 //
 // Written by Curtis Olson, started November 1997.
 //
@@ -28,6 +28,7 @@
 #include <dirent.h>
 #include <stdio.h>
 #include <string.h>
+#include <string>
 
 #ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
@@ -47,15 +48,15 @@ static double nodes[MAX_NODES][3];
 
 
 // find all the matching files in the specified directory and fix them
-void process_files(char *root_path) {
+void process_files(const string& root_path) {
     DIR *d;
     struct dirent *de;
-    char file_path[256];
+    string file_path;
     char *ptr;
     int len;
 
-    if ( (d = opendir(root_path)) == NULL ) {
-        printf("cannot open directory '%s'.", root_path);
+    if ( (d = opendir( root_path.c_str() )) == NULL ) {
+        cout << "cannot open directory " + root_path + "\n";
 	exit(-1);
     }
 
@@ -67,15 +68,13 @@ void process_files(char *root_path) {
 	    // printf("--> %s \n", ptr);
 
 	    if ( strcmp(ptr, ".1.node") == 0 ) {
-		strcpy(file_path, root_path);
-		strcat(file_path, "/");
-		strcat(file_path, de->d_name);
-		printf("File = %s\n", file_path);
+		file_path =  root_path + "/" + de->d_name;
+		cout << "File = " + file_path + "\n";
 
 		// load the input data files
-		triload(file_path, nodes);
+		triload(file_path.c_str(), nodes);
 
-		fixnodes(file_path, &dem, nodes);
+		fixnodes(file_path.c_str(), &dem, nodes);
 	    }
 	}
     }
@@ -84,17 +83,17 @@ void process_files(char *root_path) {
 
 // main
 int main(int argc, char **argv) {
-    char demfile[256], root_path[256];
+    string demfile, root_path;
 
     if ( argc != 3 ) {
 	printf("Usage %s demfile root_path\n", argv[0]);
 	exit(-1);
     }
 
-    printf("Starting fixnode\n");
+    cout << "Starting fixnode\n";
 
-    strcpy(demfile, argv[1]);
-    strcpy(root_path, argv[2]);
+    demfile = argv[1];
+    root_path = argv[2];
 
     // load the corresponding dem file so we can interpolate elev values
     dem.open(demfile);
@@ -109,6 +108,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.6  1998/09/19 18:01:27  curt
+// Support for changes to libDEM.a
+//
 // Revision 1.5  1998/07/22 21:46:41  curt
 // Fixed a bug that was triggering a seg fault.
 //

From fba995d01a73811bacc80c231887984feb31b901 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 19 Sep 1998 20:43:50 +0000
Subject: [PATCH 145/283] C++-ified and STL-ified the code.  Combined triload.*
 and fixnode.* into a single file.

---
 FixNode/Makefile.am |   7 +-
 FixNode/fixnode.cxx | 192 +++++++++++++++++++++++++++-----------------
 FixNode/fixnode.hxx |  28 ++++++-
 FixNode/main.cxx    |  27 +++----
 FixNode/triload.cxx |  86 --------------------
 FixNode/triload.hxx |  63 ---------------
 6 files changed, 158 insertions(+), 245 deletions(-)
 delete mode 100644 FixNode/triload.cxx
 delete mode 100644 FixNode/triload.hxx

diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index f9224f1a3..a72e8b22c 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -28,8 +28,7 @@ bin_PROGRAMS = fixnode
 
 fixnode_SOURCES = \
 	fixnode.cxx fixnode.hxx \
-	main.cxx \
-	triload.cxx triload.hxx
+	main.cxx
 
 fixnode_LDADD = \
 	$(top_builddir)/Lib/DEM/libDEM.a \
@@ -47,6 +46,10 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1998/09/19 20:43:50  curt
+# C++-ified and STL-ified the code.  Combined triload.* and fixnode.* into
+# a single file.
+#
 # Revision 1.5  1998/09/19 18:01:26  curt
 # Support for changes to libDEM.a
 #
diff --git a/FixNode/fixnode.cxx b/FixNode/fixnode.cxx
index 86e6ac8cd..0a39452e2 100644
--- a/FixNode/fixnode.cxx
+++ b/FixNode/fixnode.cxx
@@ -1,105 +1,147 @@
-/* fixnode.c -- traverse the node file and fix the elevation of all the new
- *              interpolated points.
- *
- * Written by Curtis Olson, started November 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
+// fixnode.cxx -- traverse the node file and fix the elevation of all the new
+//                interpolated points.
+//
+// Written by Curtis Olson, started November 1997.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
 
 
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <string>
+
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif // HAVE_STDLIB_H
+
+#include <Misc/fgstream.hxx>
 
 #include "fixnode.hxx"
 #include "triload.hxx"
 
 
-/* load the node information */
-void fixnodes( char *filename, fgDEM *dem, double nodes[MAX_NODES][3] )
+// load the node information
+void load_nodes(const string& filename, container& node_list) {
+    fgPoint3d node;
+    int dim, junk1, junk2;
+    int i, nodecount;
+
+    cout << "Loading node file:  " + filename + " ...\n";
+
+    fg_gzifstream in( filename );
+    if ( !in ) {
+	cout << "Cannot open " + filename + "\n";
+	// exit immediately assuming an airport file for this tile
+	// doesn't exist.
+	exit(-1);
+    }
+
+    // Read header line
+    in.stream() >> nodecount >> dim >> junk1 >> junk2;
+    cout << "    Expecting " << nodecount << " nodes\n";
+
+    // start with an empty list :-)
+    node_list.erase( node_list.begin(), node_list.end() );
+
+    in.eat_comments();
+    while ( ! in.eof() ) {
+	in.stream() >> junk1 >> node.x >> node.y >> node.z >> junk2;
+	in.eat_comments();
+	node_list.push_back(node);
+    }
+}
+
+
+// fix the node elevations
+void fix_nodes( const string& filename, fgDEM& dem, container& node_list )
 {
-    char toname[256];
+    string toname;
     FILE *fd;
     int i;
 
-    printf("Fixing up node elevations\n");
+    cout << "Fixing up node elevations\n";
 
-    /* we could just fix the new nodes as the first "for" statement
-     * would do, but that leads to funny results (I need to figure out
-     * why.)  So, let's try fixing all of them */
+    iterator current;
+    iterator last = node_list.end();
+    for ( current = node_list.begin() ; current != last ; ++current ) {
+	// printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0],
+	//        nodes[i][1], nodes[i][2]);
 
-    /* for ( i = origcount + 1; i <= nodecount; i++ ) { */
-    for ( i = 1; i <= nodecount; i++ ) {
-	/* printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0],
-	       nodes[i][1], nodes[i][2]); */
+	(*current).z = 
+	    dem.interpolate_altitude( (*current).x, (*current).y );
 
-	nodes[i][2] = 
-	    dem->interpolate_altitude(nodes[i][0], nodes[i][1]);
-
-	/* printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
-	       nodes[i][1], nodes[i][2]); */
+	// printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
+	//        nodes[i][1], nodes[i][2]);
     }
 
 
-    sprintf(toname, "%s.orig", filename);
-    printf("Moving %s to %s\n", filename, toname);
-    rename(filename, toname);
+    toname = filename + ".orig";
+    cout << "Moving " + filename + " to " + toname + "\n";
+    rename( filename.c_str(), toname.c_str() );
 
-    printf("Saving new node file: %s\n", filename);
+    cout << "Saving new node file: " + filename + "\n";
 
-    fd = fopen(filename, "w");
+    fd = fopen(filename.c_str(), "w");
 
-    fprintf(fd, "%d 2 1 0\n", nodecount);
+    fprintf( fd, "%d 2 1 0\n", node_list.size() );
 
-    for ( i = 1; i <= nodecount; i++ ) {
-	fprintf(fd, "%d %.2f %.2f %.2f 0\n", i, nodes[i][0],
-	       nodes[i][1], nodes[i][2]);
+    i = 1;
+    for ( current = node_list.begin() ; current != last ; ++current ) {
+	fprintf( fd, "%d %.2f %.2f %.2f 0\n", i,
+		 (*current).x, (*current).y, (*current).z );
+	++i;
     }
 
     fclose(fd);
 }
 
 
-/* $Log$
-/* Revision 1.3  1998/07/22 21:46:40  curt
-/* Fixed a bug that was triggering a seg fault.
-/*
- * Revision 1.2  1998/04/14 02:26:03  curt
- * Code reorganizations.  Added a Lib/ directory for more general libraries.
- *
- * Revision 1.1  1998/04/08 23:05:56  curt
- * Adopted Gnu automake/autoconf system.
- *
- * Revision 1.5  1998/03/19 02:50:19  curt
- * Updated to support -lDEM class.
- *
- * Revision 1.4  1998/03/03 16:00:57  curt
- * More c++ compile tweaks.
- *
- * Revision 1.3  1998/01/09 23:03:08  curt
- * Restructured to split 1deg x 1deg dem's into 64 subsections.
- *
- * Revision 1.2  1997/12/02 13:12:07  curt
- * Updated to fix every node.
- *
- * Revision 1.1  1997/11/27 00:17:33  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.4  1998/09/19 20:43:52  curt
+// C++-ified and STL-ified the code.  Combined triload.* and fixnode.* into
+// a single file.
+//
+// Revision 1.3  1998/07/22 21:46:40  curt
+// Fixed a bug that was triggering a seg fault.
+//
+// Revision 1.2  1998/04/14 02:26:03  curt
+// Code reorganizations.  Added a Lib/ directory for more general libraries.
+//
+// Revision 1.1  1998/04/08 23:05:56  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.5  1998/03/19 02:50:19  curt
+// Updated to support -lDEM class.
+//
+// Revision 1.4  1998/03/03 16:00:57  curt
+// More c++ compile tweaks.
+//
+// Revision 1.3  1998/01/09 23:03:08  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.2  1997/12/02 13:12:07  curt
+// Updated to fix every node.
+//
+// Revision 1.1  1997/11/27 00:17:33  curt
+// Initial revision.
+//
+
diff --git a/FixNode/fixnode.hxx b/FixNode/fixnode.hxx
index 236875fab..0bcc9b2c3 100644
--- a/FixNode/fixnode.hxx
+++ b/FixNode/fixnode.hxx
@@ -1,5 +1,5 @@
-// fixnode.h -- traverse the node file and fix the elevation of all the new
-//              interpolated points.
+// fixnode.hxx -- traverse the node file and fix the elevation of all the new
+//                interpolated points.
 //
 // Written by Curtis Olson, started November 1997.
 //
@@ -30,20 +30,40 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <string>
+
+#include <vector>
+#include "Include/fg_stl_config.h"
+
+#ifdef NEEDNAMESPACESTD
+using namespace std;
+#endif
 
 #include <DEM/dem.hxx>
+#include <Include/fg_types.h>
 
-#include "triload.hxx"
+
+typedef vector < fgPoint3d > container;
+typedef container::iterator iterator;
+typedef container::const_iterator const_iterator;
+
+
+// Initialize a new mesh structure
+void load_nodes(const string& basename, container& node_list);
 
 
 // load the node information
-void fixnodes( char *basename, fgDEM *dem, double nodes[MAX_NODES][3] );
+void fix_nodes( const string& basename, fgDEM& dem, container& node_list );
 
 
 #endif // _FIXNODE_H
 
 
 // $Log$
+// Revision 1.3  1998/09/19 20:43:53  curt
+// C++-ified and STL-ified the code.  Combined triload.* and fixnode.* into
+// a single file.
+//
 // Revision 1.2  1998/07/22 21:46:41  curt
 // Fixed a bug that was triggering a seg fault.
 //
diff --git a/FixNode/main.cxx b/FixNode/main.cxx
index 4adaa97d0..68e540802 100644
--- a/FixNode/main.cxx
+++ b/FixNode/main.cxx
@@ -26,7 +26,7 @@
 
 #include <sys/types.h>
 #include <dirent.h>
-#include <stdio.h>
+// #include <stdio.h>
 #include <string.h>
 #include <string>
 
@@ -37,18 +37,11 @@
 #include <DEM/dem.hxx>
 
 #include "fixnode.hxx"
-#include "triload.hxx"
-
-
-// Storage for the original DEM data which is used to interpolate z values
-fgDEM dem;
-
-// Node list
-static double nodes[MAX_NODES][3];
 
 
 // find all the matching files in the specified directory and fix them
-void process_files(const string& root_path) {
+void process_files(const string& root_path, fgDEM& dem) {
+    container node_list;
     DIR *d;
     struct dirent *de;
     string file_path;
@@ -72,9 +65,9 @@ void process_files(const string& root_path) {
 		cout << "File = " + file_path + "\n";
 
 		// load the input data files
-		triload(file_path.c_str(), nodes);
+		load_nodes(file_path, node_list);
 
-		fixnodes(file_path.c_str(), &dem, nodes);
+		fix_nodes(file_path, dem, node_list);
 	    }
 	}
     }
@@ -83,10 +76,11 @@ void process_files(const string& root_path) {
 
 // main
 int main(int argc, char **argv) {
+    fgDEM dem;
     string demfile, root_path;
 
     if ( argc != 3 ) {
-	printf("Usage %s demfile root_path\n", argv[0]);
+	cout << "Usage " << argv[0] << " demfile root_path\n";
 	exit(-1);
     }
 
@@ -101,13 +95,17 @@ int main(int argc, char **argv) {
     dem.close();
 
     // process all the *.1.node files in the specified directory
-    process_files(root_path);
+    process_files(root_path, dem);
 
     return(0);
 }
 
 
 // $Log$
+// Revision 1.7  1998/09/19 20:43:54  curt
+// C++-ified and STL-ified the code.  Combined triload.* and fixnode.* into
+// a single file.
+//
 // Revision 1.6  1998/09/19 18:01:27  curt
 // Support for changes to libDEM.a
 //
@@ -146,4 +144,3 @@ int main(int argc, char **argv) {
 // Revision 1.1  1997/11/27 00:17:34  curt
 // Initial revision.
 //
-//
diff --git a/FixNode/triload.cxx b/FixNode/triload.cxx
deleted file mode 100644
index 6852f643d..000000000
--- a/FixNode/triload.cxx
+++ /dev/null
@@ -1,86 +0,0 @@
-// triload.cxx -- read in a .node file and fix the z values of the 
-//                interpolated points
-//
-// Written by Curtis Olson, started November 1997.
-//
-// Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-// (Log is kept at end of this file)
-
-
-#include <stdio.h>
-#include <string.h>
-
-#ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif // HAVE_STDLIB_H
-
-#include "triload.hxx"
-
-
-int nodecount;
-
-
-// load the node information
-void triload(char *filename, double nodes[MAX_NODES][3]) {
-    FILE *node;
-    int dim, junk1, junk2;
-    int i;
-
-    printf("Loading node file:  %s ...\n", filename);
-    if ( (node = fopen(filename, "r")) == NULL ) {
-	printf("Cannot open file '%s'\n", filename);
-	exit(-1);
-    }
-
-    fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
-
-    if ( nodecount > MAX_NODES - 1 ) {
-	printf("Error, too many nodes, need to increase array size\n");
-	exit(-1);
-    } else {
-	printf("    Expecting %d nodes\n", nodecount);
-    }
-
-    for ( i = 1; i <= nodecount; i++ ) {
-	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
-	       &nodes[i][0], &nodes[i][1], &nodes[i][2], &junk2);
-	// printf("%d %.2f %.2f %.2f\n", junk1, nodes[i][0], nodes[i][1], 
-	// nodes[i][2]);
-    }
-
-    fclose(node);
-}
-
-
-// $Log$
-// Revision 1.2  1998/04/26 05:02:06  curt
-// Added #ifdef HAVE_STDLIB_H
-//
-// Revision 1.1  1998/04/08 23:05:58  curt
-// Adopted Gnu automake/autoconf system.
-//
-// Revision 1.3  1998/03/03 16:00:59  curt
-// More c++ compile tweaks.
-//
-// Revision 1.2  1998/01/09 23:03:09  curt
-// Restructured to split 1deg x 1deg dem's into 64 subsections.
-//
-// Revision 1.1  1997/11/27 00:17:35  curt
-// Initial revision.
-//
diff --git a/FixNode/triload.hxx b/FixNode/triload.hxx
deleted file mode 100644
index de40c1b31..000000000
--- a/FixNode/triload.hxx
+++ /dev/null
@@ -1,63 +0,0 @@
-// triload.hxx -- read in a .node file and fix the z values of the 
-//                interpolated points
-//
-// Written by Curtis Olson, started November 1997.
-//
-// Copyright (C) 1997 - 1998  Curtis L. Olson  - curt@me.umn.edu
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-// (Log is kept at end of this file)
-
-
-#ifndef _TRILOAD_H
-#define _TRILOAD_H
-
-
-#include <stdio.h>
-#include <string.h>
-
-
-#define MAX_NODES 200000
-#define MAX_TRIS  400000
-
-
-extern int nodecount, tricount;
-
-
-// Initialize a new mesh structure
-void triload(char *basename, double nodes[MAX_NODES][3]);
-
-
-#endif // _TRILOAD_H
-
-
-// $Log$
-// Revision 1.1  1998/04/08 23:06:00  curt
-// Adopted Gnu automake/autoconf system.
-//
-// Revision 1.4  1998/03/19 02:50:20  curt
-// Updated to support -lDEM class.
-//
-// Revision 1.3  1998/03/03 16:00:59  curt
-// More c++ compile tweaks.
-//
-// Revision 1.2  1998/01/09 23:03:09  curt
-// Restructured to split 1deg x 1deg dem's into 64 subsections.
-//
-// Revision 1.1  1997/11/27 00:17:35  curt
-// Initial revision.
-//

From ef1e08e474b6e89ba4e607f19051ecfa1f739439 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 21 Sep 1998 20:53:59 +0000
Subject: [PATCH 146/283] minor tweaks to clean a few additional things up
 after the rewrite.

---
 DEM/dem.cxx | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 73bce2be1..ed55e1efd 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -145,7 +145,7 @@ string fgDEM::next_token() {
 
     in->stream() >> token;
 
-    cout << "    returning " + token + "\n";
+    // cout << "    returning " + token + "\n";
 
     return token;
 }
@@ -182,7 +182,7 @@ int fgDEM::next_exp() {
 
     sscanf(token.c_str(), "%lfD%d", &mantissa, &exp);
 
-    cout << "    Mantissa = " << mantissa << "  Exp = " << exp << "\n";
+    // cout << "    Mantissa = " << mantissa << "  Exp = " << exp << "\n";
 
     acc = 1;
     if ( exp > 0 ) {
@@ -214,7 +214,7 @@ int fgDEM::read_a_record() {
     }
   
     // clean off the trailing whitespace
-    name = trimleft(name);
+    name = trim(name);
     cout << "    Quad name field: " + name + "\n";
 
     // DEM level code, 3 reflects processing by DMA
@@ -285,7 +285,7 @@ int fgDEM::read_a_record() {
     // Minimum/maximum elevations in meters
     dem_z1 = next_exp();
     dem_z2 = next_exp();
-    cout << "    Elevation range " << dem_z1 << dem_z2 << "\n";
+    cout << "    Elevation range " << dem_z1 << " to " << dem_z2 << "\n";
 
     // Counterclockwise angle from the primary axis of ground
     // planimetric referenced to the primary axis of the DEM local
@@ -391,7 +391,7 @@ int fgDEM::parse( ) {
 	cur_col++;
 
 	if ( cur_col % 100 == 0 ) {
-	    cout << "    loaded " << cur_col << "profiles of data\n";
+	    cout << "    loaded " << cur_col << " profiles of data\n";
 	}
     }
 
@@ -520,8 +520,9 @@ void fgDEM::fit( double error, fgBUCKET *p ) {
     double x[DEM_SIZE_1], y[DEM_SIZE_1];
     double m, b, ave_error, max_error;
     double cury, lasty;
-    int n, row, start, end, good_fit;
+    int n, row, start, end;
     int colmin, colmax, rowmin, rowmax;
+    bool good_fit;
     // FILE *dem, *fit, *fit1;
 
     printf("Initializing output mesh structure\n");
@@ -552,7 +553,7 @@ void fgDEM::fit( double error, fgBUCKET *p ) {
 
 	while ( start < colmax ) {
 	    end = start + 1;
-	    good_fit = 1;
+	    good_fit = true;
 
 	    x[(end - start) - 1] = 0.0 + ( start * col_step );
 	    y[(end - start) - 1] = dem_data[start][row];
@@ -585,7 +586,7 @@ void fgDEM::fit( double error, fgBUCKET *p ) {
 		*/
 
 		if ( max_error > error ) {
-		    good_fit = 0;
+		    good_fit = false;
 		}
 		
 		end++;
@@ -818,6 +819,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.15  1998/09/21 20:53:59  curt
+// minor tweaks to clean a few additional things up after the rewrite.
+//
 // Revision 1.14  1998/09/19 17:59:45  curt
 // Use c++ streams (fg_gzifstream).  Also converted many character arrays to
 // the string class.

From df4a7ed01a42b56ad17a38de58cdf7c10f323e47 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 21 Sep 1998 20:56:30 +0000
Subject: [PATCH 147/283] Changes to avoid setting airport area nodes back to
 their original elevations if they have been changed.

---
 AssemTris/assemtris.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.c
index ea16e68d3..c6e4edeb7 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.c
@@ -97,7 +97,7 @@ int is_extra_node(double *n) {
 	// along the way
 	if ( (fabs(n[0] - exnodes[i][0]) < FG_EPSILON) &&
 	     (fabs(n[1] - exnodes[i][1]) < FG_EPSILON) ) {
-	    return(1);
+	    return(i);
 	}
     }
 
@@ -372,6 +372,7 @@ FILE *my_open(char *basename, char *basepath, char *ext) {
 void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
     double n[3];
     char line[256];
+    int ex_index;
 
     offset_lon = offset_lat = 0.0;
 
@@ -379,7 +380,10 @@ void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
 	if ( strncmp(line, "gdn ", 4) == 0 ) {
 	    sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]);
 
-	    if ( ! is_extra_node(n) ) {
+	    ex_index = is_extra_node(n);
+
+	    if ( ex_index == 0 ) {
+		// not an extra node
 		nodes[nodecount][0] = n[0] + offset_lon;
 		nodes[nodecount][1] = n[1] + offset_lat;
 		nodes[nodecount][2] = n[2];
@@ -392,7 +396,10 @@ void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
 
 		nodecount++;
 	    } else {
+		// is an extra node
 		printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]);
+		// preserve the DEM altitude for now
+		exnodes[ex_index][2] = n[2];
 	    }
 	}
     }
@@ -539,11 +546,16 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.12  1998/09/09 16:24:51  curt
-/* Fixed a bug in the handling of exclude files which was causing
-/*   a crash by calling fclose() on an invalid file handle.
-/* Removed overlapping offsets.
+/* Revision 1.13  1998/09/21 20:56:30  curt
+/* Changes to avoid setting airport area nodes back to their original
+/* elevations if they have been changed.
 /*
+ *
+ * Revision 1.12  1998/09/09 16:24:51  curt
+ * Fixed a bug in the handling of exclude files which was causing
+ *   a crash by calling fclose() on an invalid file handle.
+ * Removed overlapping offsets.
+ *
  * Revision 1.11  1998/08/06 12:47:59  curt
  * Removed overlap in tiles as a test.
  *

From 86a832bd665fc5e51b24147e8f837968f5ef3ecf Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 21 Sep 1998 23:16:23 +0000
Subject: [PATCH 148/283] Converted to c++ style comments.

---
 SplitTris/splittris.cxx | 233 ++++++++++++++++++++--------------------
 SplitTris/splittris.hxx |  83 +++++++-------
 2 files changed, 161 insertions(+), 155 deletions(-)

diff --git a/SplitTris/splittris.cxx b/SplitTris/splittris.cxx
index 27ad59954..c4f1e9985 100644
--- a/SplitTris/splittris.cxx
+++ b/SplitTris/splittris.cxx
@@ -1,36 +1,36 @@
-/* splittris.c -- read in a .ele/.node file pair generated by the
- *                triangle program and output a simple Wavefront .obj
- *                file for the north, south, east, and west edge
- *                verticies ... including the normals.
- *
- * Written by Curtis Olson, started January 1998.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file) */
+// splittris.cxx -- read in a .ele/.node file pair generated by the
+//                  triangle program and output a simple Wavefront .obj
+//                  file for the north, south, east, and west edge
+//                  verticies ... including the normals.
+//
+// Written by Curtis Olson, started January 1998.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
 
 
 #include <math.h>
 #include <stdio.h>
-#include <stdlib.h>   /* for atoi() */
+#include <stdlib.h>   // for atoi()
 #include <string.h>
-#include <sys/stat.h> /* for stat() */
-#include <unistd.h>   /* for stat() */
+#include <sys/stat.h> // for stat()
+#include <unistd.h>   // for stat()
 
 #include "splittris.hxx"
 
@@ -47,41 +47,41 @@ double xmin, xmax, ymin, ymax;
 
 static double nodes_orig[MAX_NODES][3];
 static int tris[MAX_TRIS][3];
-/* static int new_tris[MAX_TRIS][3]; */
+// static int new_tris[MAX_TRIS][3];
 
 static fgPoint3d nodes_cart[MAX_NODES];
 
 fgBUCKET ne_index, nw_index, sw_index, se_index;
 fgBUCKET north_index, south_index, east_index, west_index;
 
-/* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
- * a cartesian point */
+// convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to a
+// cartesian point
 fgPoint3d geod_to_cart(double geod[3]) {
     fgPoint3d cp;
     fgPoint3d pp;
     double gc_lon, gc_lat, sl_radius;
 
-    /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
-	   geod[0], geod[1], geod[2]); */
+    // printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
+    //        geod[0], geod[1], geod[2]);
 
     gc_lon = geod[0]*ARCSEC_TO_RAD;
     fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
 
-    /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
-	   gc_lat, sl_radius+geod[2]); */
+    // printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
+    //        gc_lat, sl_radius+geod[2]);
 
     pp.lon = gc_lon;
     pp.lat = gc_lat;
     pp.radius = sl_radius + geod[2];
     cp = fgPolarToCart3d(pp);
     
-    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z); */
+    // printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z);
 
     return(cp);
 }
 
 
-/* given three points defining a triangle, calculate the normal */
+// given three points defining a triangle, calculate the normal
 void calc_normal(fgPoint3d p1, fgPoint3d p2, 
 		 fgPoint3d p3, double normal[3])
 {
@@ -94,11 +94,11 @@ void calc_normal(fgPoint3d p1, fgPoint3d p2,
     MAT3cross_product(normal, v1, v2);
     MAT3_NORMALIZE_VEC(normal,temp);
 
-/*  printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
+    // printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]);
 }
 
 
-/* return the file base name ( foo/bar/file.ext = file.ext ) */
+// return the file base name ( foo/bar/file.ext = file.ext )
 void extract_file(char *in, char *base) {
     int len, i;
 
@@ -114,7 +114,7 @@ void extract_file(char *in, char *base) {
 }
 
 
-/* return the file path name ( foo/bar/file.ext = foo/bar ) */
+// return the file path name ( foo/bar/file.ext = foo/bar )
 void extract_path(char *in, char *base) {
     int len, i;
 
@@ -130,7 +130,7 @@ void extract_path(char *in, char *base) {
 }
 
 
-/* return the index of all triangles containing the specified node */
+// return the index of all triangles containing the specified node
 void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
     int i;
 
@@ -156,7 +156,7 @@ void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
 }
 
 
-/* Initialize a new mesh structure */
+// Initialize a new mesh structure
 void triload(char *basename) {
     char nodename[256], elename[256];
     FILE *node, *ele;
@@ -186,10 +186,10 @@ void triload(char *basename) {
     for ( i = 1; i <= nodecount; i++ ) {
 	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
 	       &nodes_orig[i][0], &nodes_orig[i][1], &nodes_orig[i][2], &junk2);
-	/* printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); */
+	// printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]);
 	nodes_cart[i] = geod_to_cart(nodes_orig[i]);
-	/* printf("%d %.2f %.2f %.2f\n", 
-	       junk1, nodes_cart[i].x, nodes_cart[i].y, nodes_cart[i].z); */
+	// printf("%d %.2f %.2f %.2f\n", 
+	//        junk1, nodes_cart[i].x, nodes_cart[i].y, nodes_cart[i].z);
 
 	if ( i == 1 ) {
 	    xmin = xmax = nodes_orig[i][0];
@@ -230,14 +230,14 @@ void triload(char *basename) {
     for ( i = 1; i <= tricount; i++ ) {
 	fscanf(ele, "%d %d %d %d\n", &junk1, 
 	       &tris[i][0], &tris[i][1], &tris[i][2]);
-	/* printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
+	// printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);
     }
 
     fclose(ele);
 }
 
 
-/* check if a file exists */
+// check if a file exists
 int file_exists(char *file) {
     struct stat stat_buf;
     int result;
@@ -247,18 +247,18 @@ int file_exists(char *file) {
     result = stat(file, &stat_buf);
 
     if ( result != 0 ) {
-	/* stat failed, no file */
+	// stat failed, no file
 	printf("not found.\n");
 	return(0);
     } else {
-	/* stat succeeded, file exists */
+	// stat succeeded, file exists
 	printf("exists.\n");
 	return(1);
     }
 }
 
 
-/* check to see if a shared object exists */
+// check to see if a shared object exists
 int shared_object_exists(char *basepath, char *ext) {
     char file[256], scene_path[256];
     long int index;
@@ -387,25 +387,25 @@ int shared_object_exists(char *basepath, char *ext) {
 }
 
 
-/* my custom file opening routine ... don't open if a shared edge or
- * vertex alread exists */
+// my custom file opening routine ... don't open if a shared edge or
+// vertex alread exists
 FILE *my_open(char *basename, char *basepath, char *ext) {
     FILE *fp;
     char filename[256];
 
-    /* create the output file name */
+    // create the output file name
     strcpy(filename, basename);
     strcat(filename, ext);
 
-    /* check if a shared object already exist from a different tile */
+    // check if a shared object already exist from a different tile
 
     if ( shared_object_exists(basepath, ext) ) {
-	/* not an actual file open error, but we've already got the
-         * shared edge, so we don't want to create another one */
+	// not an actual file open error, but we've already got the
+        // shared edge, so we don't want to create another one
 	printf("not opening\n");
 	return(NULL);
     } else {
-	/* open the file */
+	// open the file
 	fp = fopen(filename, "w");
 	printf("Opening %s\n", filename);
 	return(fp);
@@ -413,7 +413,7 @@ FILE *my_open(char *basename, char *basepath, char *ext) {
 }
 
 
-/* dump in WaveFront .obj format */
+// dump in WaveFront .obj format
 void dump_obj(char *basename, char *basepath) {
     double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
     FILE *fp, *sw, *se, *ne, *nw, *north, *south, *east, *west, *body;
@@ -433,7 +433,7 @@ void dump_obj(char *basename, char *basepath) {
 
     printf("Dumping edges file basename:  %s ...\n", basename);
 
-    /* dump vertices */
+    // dump vertices
     printf("  writing vertices\n");
     for ( i = 1; i <= nodecount; i++ ) {
 
@@ -468,9 +468,9 @@ void dump_obj(char *basename, char *basepath) {
     }
 
     printf("  calculating and writing normals\n");
-    /* calculate and generate normals */
+    // calculate and generate normals
     for ( i = 1; i <= nodecount; i++ ) {
-/* 	printf("Finding normal\n"); */
+	// printf("Finding normal\n");
 
 	find_tris(i, &t1, &t2, &t3, &t4, &t5);
 
@@ -508,17 +508,18 @@ void dump_obj(char *basename, char *basepath) {
 	    count = 5;
 	}
 
-/* 	printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
+	// printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]);
 
 	norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count;
 	norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count;
 	norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count;
 	
-/* 	printf("  count = %d\n", count); */
-/* 	printf("  Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);*/
+	// printf("  count = %d\n", count);
+	// printf("  Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], 
+	//        norm[2]);
 	MAT3_NORMALIZE_VEC(norm, temp);
-/* 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
-/* 	       norm[0], norm[1], norm[2]); */
+	// printf("  Normalized ave. normal = %.4f %.4f %.4f\n", 
+	//        norm[0], norm[1], norm[2]);
 	
 	fp = NULL;
 
@@ -570,13 +571,13 @@ int main(int argc, char **argv) {
 
     strcpy(basename, argv[1]);
 
-    /* find the base path of the file */
+    // find the base path of the file
     extract_path(basename, basepath);
     extract_path(basepath, basepath);
     extract_path(basepath, basepath);
     printf("%s\n", basepath);
 
-    /* find the index of the current file */
+    // find the index of the current file
     extract_file(basename, temp);
     len = strlen(temp);
     if ( len >= 2 ) {
@@ -587,7 +588,7 @@ int main(int argc, char **argv) {
     fgBucketParseIndex(index, &p);
 
     printf("bucket = %d %d %d %d\n", p.lon, p.lat, p.x, p.y);
-    /* generate the indexes of the neighbors */
+    // generate the indexes of the neighbors
     fgBucketOffset(&p, &ne_index,  1,  1);
     fgBucketOffset(&p, &nw_index, -1,  1);
     fgBucketOffset(&p, &se_index,  1, -1);
@@ -598,58 +599,60 @@ int main(int argc, char **argv) {
     fgBucketOffset(&p, &east_index,  1,  0);
     fgBucketOffset(&p, &west_index, -1,  0);
 
-    /*
-    printf("Corner indexes = %ld %ld %ld %ld\n", 
-	   ne_index, nw_index, sw_index, se_index);
-    printf("Edge indexes = %ld %ld %ld %ld\n",
-	   north_index, south_index, east_index, west_index);
-	   */
+    // printf("Corner indexes = %ld %ld %ld %ld\n", 
+    //        ne_index, nw_index, sw_index, se_index);
+    // printf("Edge indexes = %ld %ld %ld %ld\n",
+    //        north_index, south_index, east_index, west_index);
+	  
 
-    /* load the input data files */
+    // load the input data files
     triload(basename);
 
-    /* dump in WaveFront .obj format */
+    // dump in WaveFront .obj format
     dump_obj(basename, basepath);
 
     return(0);
 }
 
 
-/* $Log$
-/* Revision 1.1  1998/07/08 14:59:13  curt
-/* *.[ch] renamed to *.[ch]xx
-/*
- * Revision 1.11  1998/07/04 00:56:40  curt
- * typedef'd struct fgBUCKET.
- *
- * Revision 1.10  1998/05/02 01:54:37  curt
- * Converting to polar3d.h routines.
- *
- * Revision 1.9  1998/04/18 04:01:20  curt
- * Now use libMath rather than having local copies of math routines.
- *
- * Revision 1.8  1998/04/14 02:26:08  curt
- * Code reorganizations.  Added a Lib/ directory for more general libraries.
- *
- * Revision 1.7  1998/04/08 23:21:13  curt
- * Adopted Gnu automake/autoconf system.
- *
- * Revision 1.6  1998/03/03 15:36:13  curt
- * Tweaks for compiling with g++
- *
- * Revision 1.5  1998/03/03 03:37:04  curt
- * Cumulative tweaks.
- *
- * Revision 1.4  1998/01/31 00:41:26  curt
- * Made a few changes converting floats to doubles.
- *
- * Revision 1.3  1998/01/27 18:37:04  curt
- * Lots of updates to get back in sync with changes made over in .../Src/
- *
- * Revision 1.2  1998/01/14 15:54:43  curt
- * Initial revision completed.
- *
- * Revision 1.1  1998/01/14 02:11:31  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.2  1998/09/21 23:16:23  curt
+// Converted to c++ style comments.
+//
+// Revision 1.1  1998/07/08 14:59:13  curt
+// *.[ch] renamed to *.[ch]xx
+//
+// Revision 1.11  1998/07/04 00:56:40  curt
+// typedef'd struct fgBUCKET.
+//
+// Revision 1.10  1998/05/02 01:54:37  curt
+// Converting to polar3d.h routines.
+//
+// Revision 1.9  1998/04/18 04:01:20  curt
+// Now use libMath rather than having local copies of math routines.
+//
+// Revision 1.8  1998/04/14 02:26:08  curt
+// Code reorganizations.  Added a Lib/ directory for more general libraries.
+//
+// Revision 1.7  1998/04/08 23:21:13  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.6  1998/03/03 15:36:13  curt
+// Tweaks for compiling with g++
+//
+// Revision 1.5  1998/03/03 03:37:04  curt
+// Cumulative tweaks.
+//
+// Revision 1.4  1998/01/31 00:41:26  curt
+// Made a few changes converting floats to doubles.
+//
+// Revision 1.3  1998/01/27 18:37:04  curt
+// Lots of updates to get back in sync with changes made over in .../Src/
+//
+// Revision 1.2  1998/01/14 15:54:43  curt
+// Initial revision completed.
+//
+// Revision 1.1  1998/01/14 02:11:31  curt
+// Initial revision.
+//
+
diff --git a/SplitTris/splittris.hxx b/SplitTris/splittris.hxx
index 60d6dba99..011109754 100644
--- a/SplitTris/splittris.hxx
+++ b/SplitTris/splittris.hxx
@@ -1,27 +1,27 @@
-/* splittris.hxx -- read in a .ele/.node file pair generated by the triangle 
- *                  program and output edge vertices w/ normals.
- *
- * Written by Curtis Olson, started January 1998.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
+// splittris.hxx -- read in a .ele/.node file pair generated by the triangle 
+//                  program and output edge vertices w/ normals.
+//
+// Written by Curtis Olson, started January 1998.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
 
 
 #ifndef SPLITTRIS_HXX
@@ -39,24 +39,27 @@
 extern int nodecount, tricount;
 
 
-/* Initialize a new mesh structure */
+// Initialize a new mesh structure
 void triload(char *basename);
 
 
-#endif /* SPLITTRIS_HXX */
+#endif // SPLITTRIS_HXX
 
 
-/* $Log$
-/* Revision 1.1  1998/07/08 14:59:14  curt
-/* *.[ch] renamed to *.[ch]xx
-/*
- * Revision 1.3  1998/03/03 15:36:13  curt
- * Tweaks for compiling with g++
- *
- * Revision 1.2  1998/01/15 02:49:25  curt
- * Misc. housekeeping.
- *
- * Revision 1.1  1998/01/14 02:11:32  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.2  1998/09/21 23:16:24  curt
+// Converted to c++ style comments.
+//
+// Revision 1.1  1998/07/08 14:59:14  curt
+// *.[ch] renamed to *.[ch]xx
+//
+// Revision 1.3  1998/03/03 15:36:13  curt
+// Tweaks for compiling with g++
+//
+// Revision 1.2  1998/01/15 02:49:25  curt
+// Misc. housekeeping.
+//
+// Revision 1.1  1998/01/14 02:11:32  curt
+// Initial revision.
+//
+

From a5eb87dc06a609d00203386549de2c7aab14bb3f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 22 Sep 1998 23:49:10 +0000
Subject: [PATCH 149/283] eliminated a left over #include

---
 FixNode/fixnode.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/FixNode/fixnode.cxx b/FixNode/fixnode.cxx
index 0a39452e2..f8819e30c 100644
--- a/FixNode/fixnode.cxx
+++ b/FixNode/fixnode.cxx
@@ -36,7 +36,7 @@
 #include <Misc/fgstream.hxx>
 
 #include "fixnode.hxx"
-#include "triload.hxx"
+// #include "triload.hxx"
 
 
 // load the node information
@@ -116,6 +116,9 @@ void fix_nodes( const string& filename, fgDEM& dem, container& node_list )
 
 
 // $Log$
+// Revision 1.5  1998/09/22 23:49:10  curt
+// eliminated a left over #include
+//
 // Revision 1.4  1998/09/19 20:43:52  curt
 // C++-ified and STL-ified the code.  Combined triload.* and fixnode.* into
 // a single file.

From c27d116ccea08528b62a2f82a9613cfe098a40ee Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 22 Sep 1998 23:49:56 +0000
Subject: [PATCH 150/283] C++-ified, STL-ified, and string-ified.

---
 SplitTris/splittris.cxx | 338 +++++++++++++++++++++-------------------
 SplitTris/splittris.hxx |  29 +++-
 2 files changed, 204 insertions(+), 163 deletions(-)

diff --git a/SplitTris/splittris.cxx b/SplitTris/splittris.cxx
index c4f1e9985..e9ec2ff57 100644
--- a/SplitTris/splittris.cxx
+++ b/SplitTris/splittris.cxx
@@ -42,21 +42,23 @@
 #include <Math/mat3.h>
 #include <Math/polar3d.hxx>
 
-int nodecount, tricount;
+// int nodecount, tricount;
 double xmin, xmax, ymin, ymax;
 
-static double nodes_orig[MAX_NODES][3];
-static int tris[MAX_TRIS][3];
-// static int new_tris[MAX_TRIS][3];
+// static double nodes_orig[MAX_NODES][3];
+// static fgPoint3d nodes_cart[MAX_NODES];
+// static int tris[MAX_TRIS][3];
 
-static fgPoint3d nodes_cart[MAX_NODES];
+container_3d nodes_orig;
+container_3d nodes_cart;
+container_tri tri_list;
 
 fgBUCKET ne_index, nw_index, sw_index, se_index;
 fgBUCKET north_index, south_index, east_index, west_index;
 
 // convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to a
 // cartesian point
-fgPoint3d geod_to_cart(double geod[3]) {
+fgPoint3d geod_to_cart(fgPoint3d geod) {
     fgPoint3d cp;
     fgPoint3d pp;
     double gc_lon, gc_lat, sl_radius;
@@ -64,15 +66,15 @@ fgPoint3d geod_to_cart(double geod[3]) {
     // printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
     //        geod[0], geod[1], geod[2]);
 
-    gc_lon = geod[0]*ARCSEC_TO_RAD;
-    fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
+    gc_lon = geod.lon * ARCSEC_TO_RAD;
+    fgGeodToGeoc(geod.lat * ARCSEC_TO_RAD, geod.radius, &sl_radius, &gc_lat);
 
     // printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
     //        gc_lat, sl_radius+geod[2]);
 
     pp.lon = gc_lon;
     pp.lat = gc_lat;
-    pp.radius = sl_radius + geod[2];
+    pp.radius = sl_radius + geod.radius;
     cp = fgPolarToCart3d(pp);
     
     // printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z);
@@ -99,34 +101,23 @@ void calc_normal(fgPoint3d p1, fgPoint3d p2,
 
 
 // return the file base name ( foo/bar/file.ext = file.ext )
-void extract_file(char *in, char *base) {
-    int len, i;
+string extract_file(const string& input) {
+    int pos;
 
-    len = strlen(in);
+    pos = input.rfind("/");
+    ++pos;
 
-    i = len - 1;
-    while ( (i >= 0) && (in[i] != '/') ) {
-	i--;
-    }
-
-    in += (i + 1);
-    strcpy(base, in);
+    return input.substr(pos);
 }
 
 
 // return the file path name ( foo/bar/file.ext = foo/bar )
-void extract_path(char *in, char *base) {
-    int len, i;
+string extract_path(const string& input) {
+    int pos;
 
-    len = strlen(in);
-    strcpy(base, in);
+    pos = input.rfind("/");
 
-    i = len - 1;
-    while ( (i >= 0) && (in[i] != '/') ) {
-	i--;
-    }
-
-    base[i] = '\0';
+    return input.substr(0, pos);
 }
 
 
@@ -137,8 +128,17 @@ void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
     *t1 = *t2 = *t3 = *t4 = *t5 = 0;
 
     i = 1;
-    while ( i <= tricount ) {
-        if ( (n == tris[i][0]) || (n == tris[i][1]) || (n == tris[i][2]) ) {
+    iterator_tri last = tri_list.end();
+    iterator_tri current = tri_list.begin();
+
+    // skip first null record
+    ++current;
+
+    for ( ; current != last; ++current )
+    {
+        if ( (n == (*current).n1) || (n == (*current).n2) || 
+	     (n == (*current).n3) )
+	{
             if ( *t1 == 0 ) {
 		*t1 = i;
             } else if ( *t2 == 0 ) {
@@ -151,89 +151,86 @@ void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
 		*t5 = i;
 	    }
         }
-        i++;
+        ++i;
     }
 }
 
 
 // Initialize a new mesh structure
-void triload(char *basename) {
-    char nodename[256], elename[256];
-    FILE *node, *ele;
-    int dim, junk1, junk2;
+void triload(const string& basename) {
+    string nodename, elename;
+    fgPoint3d node1, node2;
+    triangle tri;
+    FILE *node_file, *ele_file;
+    int nodecount, tricount, dim, junk1, junk2;
     int i;
 
-    strcpy(nodename, basename);
-    strcat(nodename, ".node");
-    strcpy(elename, basename);
-    strcat(elename, ".ele");
+    nodename = basename + ".node";
+    elename  = basename + ".ele";
 
-    printf("Loading node file:  %s ...\n", nodename);
-    if ( (node = fopen(nodename, "r")) == NULL ) {
-	printf("Cannot open file '%s'\n", nodename);
+    cout << "Loading node file:  " + nodename + " ...\n";
+    if ( (node_file = fopen(nodename.c_str(), "r")) == NULL ) {
+	cout << "Cannot open file " + nodename + "\n";
 	exit(-1);
     }
 
-    fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
+    // the triangle program starts counting at 1 by default which is
+    // pretty obnoxious.  Let's just push null record zero's onto our
+    // list to compensate
+    nodes_orig.push_back(node1);
+    nodes_cart.push_back(node1);
+    tri_list.push_back(tri);
 
-    if ( nodecount > MAX_NODES - 1 ) {
-	printf("Error, too many nodes, need to increase array size\n");
-	exit(-1);
-    } else {
-	printf("    Expecting %d nodes\n", nodecount);
-    }
+    fscanf(node_file, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
+    cout << "    Expecting " << nodecount << " nodes\n";
 
     for ( i = 1; i <= nodecount; i++ ) {
-	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
-	       &nodes_orig[i][0], &nodes_orig[i][1], &nodes_orig[i][2], &junk2);
-	// printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]);
-	nodes_cart[i] = geod_to_cart(nodes_orig[i]);
-	// printf("%d %.2f %.2f %.2f\n", 
-	//        junk1, nodes_cart[i].x, nodes_cart[i].y, nodes_cart[i].z);
+	fscanf(node_file, "%d %lf %lf %lf %d\n", &junk1, 
+	       &(node1.x), &(node1.y), &(node1.z), &junk2);
+	printf("%d %.2f %.2f %.2f\n", junk1, node1.x, node1.y, node1.z);
+	nodes_orig.push_back(node1);
+	node2 = geod_to_cart(node1);
+	nodes_cart.push_back(node2);
+	printf("%d %.2f %.2f %.2f\n", junk1, node2.x, node2.y, node2.z);
 
 	if ( i == 1 ) {
-	    xmin = xmax = nodes_orig[i][0];
-	    ymin = ymax = nodes_orig[i][1];
+	    xmin = xmax = node1.x;
+	    ymin = ymax = node1.y;
 	} else {
-	    if ( nodes_orig[i][0] < xmin ) {
-		xmin = nodes_orig[i][0];
+	    if ( node1.x < xmin ) {
+		xmin = node1.x;
 	    }
-	    if ( nodes_orig[i][0] > xmax ) {
-		xmax = nodes_orig[i][0];
+	    if ( node1.x > xmax ) {
+		xmax = node1.x;
 	    }
-	    if ( nodes_orig[i][1] < ymin ) {
-		ymin = nodes_orig[i][1];
+	    if ( node1.y < ymin ) {
+		ymin = node1.y;
 	    }
-	    if ( nodes_orig[i][1] > ymax ) {
-		ymax = nodes_orig[i][1];
+	    if ( node1.y > ymax ) {
+		ymax = node1.y;
 	    }
 	}
     }
 
-    fclose(node);
+    fclose(node_file);
 
-    printf("Loading element file:  %s ...\n", elename);
-    if ( (ele = fopen(elename, "r")) == NULL ) {
-	printf("Cannot open file '%s'\n", elename);
+    cout << "Loading element file:  " + elename + " ...\n";
+    if ( (ele_file = fopen(elename.c_str(), "r")) == NULL ) {
+	cout << "Cannot open file " + elename + "\n";
 	exit(-1);
     }
 
-    fscanf(ele, "%d %d %d", &tricount, &junk1, &junk2);
-
-    if ( tricount > MAX_TRIS - 1 ) {
-	printf("Error, too many elements, need to increase array size\n");
-	exit(-1);
-    } else {
-	printf("    Expecting %d elements\n", tricount);
-    }
+    fscanf(ele_file, "%d %d %d", &tricount, &junk1, &junk2);
+    cout << "    Expecting " << tricount << " elements\n";
 
     for ( i = 1; i <= tricount; i++ ) {
-	fscanf(ele, "%d %d %d %d\n", &junk1, 
-	       &tris[i][0], &tris[i][1], &tris[i][2]);
-	// printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);
+	fscanf(ele_file, "%d %d %d %d\n", &junk1, 
+	       &(tri.n1), &(tri.n2), &(tri.n3));
+	printf("%d %d %d %d\n", junk1, tri.n1, tri.n2, tri.n3);
+	tri_list.push_back(tri);
     }
 
-    fclose(ele);
+    fclose(ele_file);
 }
 
 
@@ -242,28 +239,28 @@ int file_exists(char *file) {
     struct stat stat_buf;
     int result;
 
-    printf("checking %s ... ", file);
+    cout << "checking " << file << " ... ";
 
     result = stat(file, &stat_buf);
 
     if ( result != 0 ) {
 	// stat failed, no file
-	printf("not found.\n");
-	return(0);
+	cout << "not found.\n";
+	return 0;
     } else {
 	// stat succeeded, file exists
-	printf("exists.\n");
-	return(1);
+	cout << "exists.\n";
+	return 1;
     }
 }
 
 
 // check to see if a shared object exists
-int shared_object_exists(char *basepath, char *ext) {
+int shared_object_exists(const char *basepath, const string& ext) {
     char file[256], scene_path[256];
     long int index;
 
-    if ( strcmp(ext, ".sw") == 0 ) {
+    if ( ext == ".sw" ) {
 	fgBucketGenBasePath(&west_index, scene_path);
 	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
@@ -284,7 +281,7 @@ int shared_object_exists(char *basepath, char *ext) {
 	}
     }
 
-    if ( strcmp(ext, ".se") == 0 ) {
+    if ( ext == ".se" ) {
 	fgBucketGenBasePath(&east_index, scene_path);
 	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
@@ -305,7 +302,7 @@ int shared_object_exists(char *basepath, char *ext) {
 	}
     }
 
-    if ( strcmp(ext, ".ne") == 0 ) {
+    if ( ext == ".ne" ) {
 	fgBucketGenBasePath(&east_index, scene_path);
 	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
@@ -326,7 +323,7 @@ int shared_object_exists(char *basepath, char *ext) {
 	}
     }
 
-    if ( strcmp(ext, ".nw") == 0 ) {
+    if ( ext == ".nw" ) {
 	fgBucketGenBasePath(&west_index, scene_path);
 	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
@@ -347,7 +344,7 @@ int shared_object_exists(char *basepath, char *ext) {
 	}
     }
 
-    if ( strcmp(ext, ".south") == 0 ) {
+    if ( ext == ".south" ) {
 	fgBucketGenBasePath(&south_index, scene_path);
 	index = fgBucketGenIndex(&south_index);
 	sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
@@ -356,7 +353,7 @@ int shared_object_exists(char *basepath, char *ext) {
 	}
     }
 
-    if ( strcmp(ext, ".north") == 0 ) {
+    if ( ext == ".north" ) {
 	fgBucketGenBasePath(&north_index, scene_path);
 	index = fgBucketGenIndex(&north_index);
 	sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
@@ -365,7 +362,7 @@ int shared_object_exists(char *basepath, char *ext) {
 	}
     }
 
-    if ( strcmp(ext, ".west") == 0 ) {
+    if ( ext == ".west" ) {
 	fgBucketGenBasePath(&west_index, scene_path);
 	index = fgBucketGenIndex(&west_index);
 	sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
@@ -374,7 +371,7 @@ int shared_object_exists(char *basepath, char *ext) {
 	}
     }
 
-    if ( strcmp(ext, ".east") == 0 ) {
+    if ( ext == ".east" ) {
 	fgBucketGenBasePath(&east_index, scene_path);
 	index = fgBucketGenIndex(&east_index);
 	sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
@@ -389,35 +386,37 @@ int shared_object_exists(char *basepath, char *ext) {
 
 // my custom file opening routine ... don't open if a shared edge or
 // vertex alread exists
-FILE *my_open(char *basename, char *basepath, char *ext) {
+FILE *my_open(const string& basename, const string& basepath, 
+	      const string& ext)
+{
     FILE *fp;
-    char filename[256];
+    string filename;
 
     // create the output file name
-    strcpy(filename, basename);
-    strcat(filename, ext);
+    filename = basename + ext;
 
     // check if a shared object already exist from a different tile
 
-    if ( shared_object_exists(basepath, ext) ) {
+    if ( shared_object_exists(basepath.c_str(), ext) ) {
 	// not an actual file open error, but we've already got the
         // shared edge, so we don't want to create another one
-	printf("not opening\n");
+	cout << "not opening\n";
 	return(NULL);
     } else {
 	// open the file
-	fp = fopen(filename, "w");
-	printf("Opening %s\n", filename);
+	fp = fopen(filename.c_str(), "w");
+	cout << "Opening " + filename + "\n";
 	return(fp);
     }
 }
 
 
 // dump in WaveFront .obj format
-void dump_obj(char *basename, char *basepath) {
+void dump_obj(const string& basename, const string& basepath) {
+    fgPoint3d node;
     double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
     FILE *fp, *sw, *se, *ne, *nw, *north, *south, *east, *west, *body;
-    int i, t1, t2, t3, t4, t5, count;
+    int i, t1, t2, t3, t4, t5, count, size;
 
     sw = my_open(basename, basepath, ".sw");
     se = my_open(basename, basepath, ".se");
@@ -431,45 +430,51 @@ void dump_obj(char *basename, char *basepath) {
 
     body = my_open(basename, basepath, ".body");
 
-    printf("Dumping edges file basename:  %s ...\n", basename);
+    cout << "Dumping edges file basename:  " + basename + " ...\n";
 
     // dump vertices
-    printf("  writing vertices\n");
-    for ( i = 1; i <= nodecount; i++ ) {
+    cout << "  writing vertices\n";
 
-	if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) && 
-	     (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+    iterator_3d last = nodes_orig.end();
+    iterator_3d current = nodes_orig.begin();
+    ++current;
+    for ( ; current != last; ++current) {
+	node = *current;
+
+	if ( (fabs(node.y - ymin) < FG_EPSILON) && 
+	     (fabs(node.x - xmin) < FG_EPSILON) ) {
 	    fp = sw;
-	} else if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON) ) {
+	} else if ( (fabs(node.y - ymin) < FG_EPSILON) &&
+		    (fabs(node.x - xmax) < FG_EPSILON) ) {
 	    fp = se;
-	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON)) {
+	} else if ( (fabs(node.y - ymax) < FG_EPSILON) &&
+		    (fabs(node.x - xmax) < FG_EPSILON)) {
 	    fp = ne;
-	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+	} else if ( (fabs(node.y - ymax) < FG_EPSILON) &&
+		    (fabs(node.x - xmin) < FG_EPSILON) ) {
 	    fp = nw;
-	} else if ( fabs(nodes_orig[i][0] - xmin) < FG_EPSILON ) {
+	} else if ( fabs(node.x - xmin) < FG_EPSILON ) {
 	    fp = west;
-	} else if ( fabs(nodes_orig[i][0] - xmax) < FG_EPSILON ) {
+	} else if ( fabs(node.x - xmax) < FG_EPSILON ) {
 	    fp = east;
-	} else if ( fabs(nodes_orig[i][1] - ymin) < FG_EPSILON ) {
+	} else if ( fabs(node.y - ymin) < FG_EPSILON ) {
 	    fp = south;
-	} else if ( fabs(nodes_orig[i][1] - ymax) < FG_EPSILON ) {
+	} else if ( fabs(node.y - ymax) < FG_EPSILON ) {
 	    fp = north;
 	} else {
 	    fp = body;
 	}
 
 	if ( fp != NULL ) {
-	    fprintf(fp, "gdn %.2f %.2f %.2f\n", 
-		    nodes_orig[i][0], nodes_orig[i][1], nodes_orig[i][2]);
+	    fprintf(fp, "gdn %.2f %.2f %.2f\n", node.x, node.y, node.z);
 	}
     }
 
-    printf("  calculating and writing normals\n");
+    cout << "  calculating and writing normals\n";
+
     // calculate and generate normals
-    for ( i = 1; i <= nodecount; i++ ) {
+    size = nodes_orig.size();
+    for ( i = 1; i < size; i++ ) {
 	// printf("Finding normal\n");
 
 	find_tris(i, &t1, &t2, &t3, &t4, &t5);
@@ -481,30 +486,40 @@ void dump_obj(char *basename, char *basepath) {
 	n5[0] = n5[1] = n5[2] = 0.0;
 
 	count = 1;
-	calc_normal(nodes_cart[tris[t1][0]], nodes_cart[tris[t1][1]], 
-		    nodes_cart[tris[t1][2]], n1);
+	calc_normal(nodes_cart[tri_list[t1].n1],
+		    nodes_cart[tri_list[t1].n2], 
+		    nodes_cart[tri_list[t1].n3],
+		    n1);
 
 	if ( t2 > 0 ) {
-	    calc_normal(nodes_cart[tris[t2][0]], nodes_cart[tris[t2][1]], 
-			nodes_cart[tris[t2][2]], n2);
+	    calc_normal(nodes_cart[tri_list[t2].n1], 
+			nodes_cart[tri_list[t2].n2], 
+			nodes_cart[tri_list[t2].n3],
+			n2);
 	    count = 2;
 	}
 
 	if ( t3 > 0 ) {
-	    calc_normal(nodes_cart[tris[t3][0]], nodes_cart[tris[t3][1]],
-			nodes_cart[tris[t3][2]], n3);
+	    calc_normal(nodes_cart[tri_list[t3].n1],
+			nodes_cart[tri_list[t3].n2],
+			nodes_cart[tri_list[t3].n3],
+			n3);
 	    count = 3;
 	}
 
 	if ( t4 > 0 ) {
-	    calc_normal(nodes_cart[tris[t4][0]], nodes_cart[tris[t4][1]],
-			nodes_cart[tris[t4][2]], n4);
+	    calc_normal(nodes_cart[tri_list[t4].n1],
+			nodes_cart[tri_list[t4].n2],
+			nodes_cart[tri_list[t4].n3],
+			n4);
 	    count = 4;
 	}
 
 	if ( t5 > 0 ) {
-	    calc_normal(nodes_cart[tris[t5][0]], nodes_cart[tris[t5][1]],
-			nodes_cart[tris[t5][2]], n5);
+	    calc_normal(nodes_cart[tri_list[t5].n1],
+			nodes_cart[tri_list[t5].n2],
+			nodes_cart[tri_list[t5].n3],
+			n5);
 	    count = 5;
 	}
 
@@ -523,25 +538,25 @@ void dump_obj(char *basename, char *basepath) {
 	
 	fp = NULL;
 
-	if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) && 
-	     (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+	if ( (fabs(nodes_orig[i].y - ymin) < FG_EPSILON) && 
+	     (fabs(nodes_orig[i].x - xmin) < FG_EPSILON) ) {
 	    fp = sw;
-	} else if ( (fabs(nodes_orig[i][1] - ymin) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON) ) {
+	} else if ( (fabs(nodes_orig[i].y - ymin) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i].x - xmax) < FG_EPSILON) ) {
 	    fp = se;
-	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i][0] - xmax) < FG_EPSILON)) {
+	} else if ( (fabs(nodes_orig[i].y - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i].x - xmax) < FG_EPSILON)) {
 	    fp = ne;
-	} else if ( (fabs(nodes_orig[i][1] - ymax) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i][0] - xmin) < FG_EPSILON) ) {
+	} else if ( (fabs(nodes_orig[i].y - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i].x - xmin) < FG_EPSILON) ) {
 	    fp = nw;
-	} else if ( fabs(nodes_orig[i][0] - xmin) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].x - xmin) < FG_EPSILON ) {
 	    fp = west;
-	} else if ( fabs(nodes_orig[i][0] - xmax) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].x - xmax) < FG_EPSILON ) {
 	    fp = east;
-	} else if ( fabs(nodes_orig[i][1] - ymin) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].y - ymin) < FG_EPSILON ) {
 	    fp = south;
-	} else if ( fabs(nodes_orig[i][1] - ymax) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].y - ymax) < FG_EPSILON ) {
 	    fp = north;
 	}
 	if ( fp != NULL ) {
@@ -564,30 +579,32 @@ void dump_obj(char *basename, char *basepath) {
 
 
 int main(int argc, char **argv) {
-    char basename[256], basepath[256], temp[256];
+    string basename, basepath, temp;
     fgBUCKET p;
     long int index;
     int len;
 
-    strcpy(basename, argv[1]);
+    basename = argv[1];
 
     // find the base path of the file
-    extract_path(basename, basepath);
-    extract_path(basepath, basepath);
-    extract_path(basepath, basepath);
-    printf("%s\n", basepath);
+    basepath = extract_path(basename);
+    basepath = extract_path(basepath);
+    basepath = extract_path(basepath);
+    cout << "basepath = " + basepath + "\n";
 
     // find the index of the current file
-    extract_file(basename, temp);
-    len = strlen(temp);
+    temp = extract_file(basename);
+    len = temp.length();
     if ( len >= 2 ) {
-	temp[len-2] = '\0';
+	temp = temp.substr(0, len-2);
     }
-    index = atoi(temp);
-    printf("%ld\n", index);
+    index = atoi( temp.c_str() );
+    cout << "index = " << index << "\n";
     fgBucketParseIndex(index, &p);
 
-    printf("bucket = %d %d %d %d\n", p.lon, p.lat, p.x, p.y);
+    cout << "bucket = " << p.lon << " " << p.lat << " " << 
+	p.x << " " << p.y << "\n";
+
     // generate the indexes of the neighbors
     fgBucketOffset(&p, &ne_index,  1,  1);
     fgBucketOffset(&p, &nw_index, -1,  1);
@@ -616,6 +633,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.3  1998/09/22 23:49:56  curt
+// C++-ified, STL-ified, and string-ified.
+//
 // Revision 1.2  1998/09/21 23:16:23  curt
 // Converted to c++ style comments.
 //
diff --git a/SplitTris/splittris.hxx b/SplitTris/splittris.hxx
index 011109754..9a4e058e8 100644
--- a/SplitTris/splittris.hxx
+++ b/SplitTris/splittris.hxx
@@ -30,23 +30,44 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <string>
+
+#include <vector>
+#include "Include/fg_stl_config.h"
+
+#ifdef NEEDNAMESPACESTD
+using namespace std;
+#endif
+
+#include <Include/fg_types.h>
 
 
-#define MAX_NODES 200000
-#define MAX_TRIS  400000
+// A triangle (indices of the three nodes)
+typedef struct {
+    int n1, n2, n3;
+} triangle;
 
 
-extern int nodecount, tricount;
+typedef vector < fgPoint3d > container_3d;
+typedef container_3d::iterator iterator_3d;
+typedef container_3d::const_iterator const_iterator_3d;
+
+typedef vector < triangle > container_tri;
+typedef container_tri::iterator iterator_tri;
+typedef container_tri::const_iterator const_iterator_tri;
 
 
 // Initialize a new mesh structure
-void triload(char *basename);
+void triload(const string& basename);
 
 
 #endif // SPLITTRIS_HXX
 
 
 // $Log$
+// Revision 1.3  1998/09/22 23:49:58  curt
+// C++-ified, STL-ified, and string-ified.
+//
 // Revision 1.2  1998/09/21 23:16:24  curt
 // Converted to c++ style comments.
 //

From 216be72f34e64185f6c12560e971c6e08eee7006 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 25 Sep 1998 19:35:25 +0000
Subject: [PATCH 151/283] Renamed assemtris.[ch] to assemtris.[ch]xx

---
 AssemTris/Makefile.am                    |   5 +-
 AssemTris/{assemtris.c => assemtris.cxx} | 241 +++++++++++------------
 AssemTris/assemtris.h                    |  45 -----
 AssemTris/assemtris.hxx                  |  48 +++++
 4 files changed, 172 insertions(+), 167 deletions(-)
 rename AssemTris/{assemtris.c => assemtris.cxx} (72%)
 delete mode 100644 AssemTris/assemtris.h
 create mode 100644 AssemTris/assemtris.hxx

diff --git a/AssemTris/Makefile.am b/AssemTris/Makefile.am
index f1cb9f24e..2398c9371 100644
--- a/AssemTris/Makefile.am
+++ b/AssemTris/Makefile.am
@@ -26,7 +26,7 @@
 
 bin_PROGRAMS = assemtris
 
-assemtris_SOURCES = assemtris.c assemtris.h
+assemtris_SOURCES = assemtris.cxx assemtris.hxx
 
 assemtris_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.a
@@ -36,6 +36,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/09/25 19:35:25  curt
+# Renamed assemtris.[ch] to assemtris.[ch]xx
+#
 # Revision 1.3  1998/07/30 23:49:23  curt
 # Removed libtool support.
 #
diff --git a/AssemTris/assemtris.c b/AssemTris/assemtris.cxx
similarity index 72%
rename from AssemTris/assemtris.c
rename to AssemTris/assemtris.cxx
index c6e4edeb7..481943f2e 100644
--- a/AssemTris/assemtris.c
+++ b/AssemTris/assemtris.cxx
@@ -1,33 +1,33 @@
-/* splittris.c -- reassemble the pieces produced by splittris
- *
- * Written by Curtis Olson, started January 1998.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file) */
+// assemtris.c -- reassemble the pieces produced by splittris
+//
+// Written by Curtis Olson, started January 1998.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
 
 
 #include <math.h>
 #include <stdio.h>
-#include <stdlib.h>   /* for atoi() */
+#include <stdlib.h>   // for atoi()
 #include <string.h>
-#include <sys/stat.h> /* for stat() */
-#include <unistd.h>   /* for stat() */
+#include <sys/stat.h> // for stat()
+#include <unistd.h>   // for stat()
 
 #include "assemtris.h"
 
@@ -36,10 +36,8 @@
 #include <Bucket/bucketutils.h>
 
 
-/*
-#define OFFSET_LON 0.1
-#define OFFSET_LAT 0.1
-*/
+// #define OFFSET_LON 0.1
+// #define OFFSET_LAT 0.1
 
 #define OFFSET_LON 0.0
 #define OFFSET_LAT 0.0
@@ -56,7 +54,7 @@ fgBUCKET ne_index, nw_index, sw_index, se_index;
 fgBUCKET north_index, south_index, east_index, west_index;
 
 
-/* return the file base name ( foo/bar/file.ext = file.ext ) */
+// return the file base name ( foo/bar/file.ext = file.ext )
 void extract_file(char *in, char *base) {
     int len, i;
 
@@ -72,7 +70,7 @@ void extract_file(char *in, char *base) {
 }
 
 
-/* return the file path name ( foo/bar/file.ext = foo/bar ) */
+// return the file path name ( foo/bar/file.ext = foo/bar )
 void extract_path(char *in, char *base) {
     int len, i;
 
@@ -88,7 +86,7 @@ void extract_path(char *in, char *base) {
 }
 
 
-/* check to see if specified node is in the extra list */
+// check to see if specified node is in the extra list
 int is_extra_node(double *n) {
     int i;
 
@@ -104,10 +102,10 @@ int is_extra_node(double *n) {
     return(0);
 }
 
-/* Read all the extra nodes.  These typically define inner areas to
-   exclude from triangulations.  There will be a .poly file that
-   refers to these by position number which assumes all the extra
-   nodes come first in the generated .node file. */
+// Read all the extra nodes.  These typically define inner areas to
+// exclude from triangulations.  There will be a .poly file that
+// refers to these by position number which assumes all the extra
+// nodes come first in the generated .node file.
 void read_extra_nodes(char *exfile) {
     FILE *fd;
     int i, junk1, junk2, junk3;
@@ -136,7 +134,7 @@ void read_extra_nodes(char *exfile) {
 }
 
 
-/* check if a file exists */
+// check if a file exists
 int file_exists(char *file) {
     struct stat stat_buf;
     int result;
@@ -146,18 +144,18 @@ int file_exists(char *file) {
     result = stat(file, &stat_buf);
 
     if ( result != 0 ) {
-	/* stat failed, no file */
+	// stat failed, no file
 	printf("not found.\n");
 	return(0);
     } else {
-	/* stat succeeded, file exists */
+	// stat succeeded, file exists
 	printf("exists.\n");
 	return(1);
     }
 }
 
 
-/* check to see if a shared object exists */
+// check to see if a shared object exists
 int shared_object_exists(char *basepath, char *ext, char *file) {
     char scene_path[256];
     long int index;
@@ -343,32 +341,32 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
 }
 
 
-/* my custom file opening routine ... don't open if a shared edge or
- * vertex alread exists */
+// my custom file opening routine ... don't open if a shared edge or
+// vertex alread exists
 FILE *my_open(char *basename, char *basepath, char *ext) {
     FILE *fp;
     char filename[256];
 
-    /* check if a shared object already exists */
+    // check if a shared object already exists
     if ( shared_object_exists(basepath, ext, filename) ) {
-	/* not an actual file open error, but we've already got the
-         * shared edge, so we don't want to create another one */
+	// not an actual file open error, but we've already got the
+        // shared edge, so we don't want to create another one
 	fp = fopen(filename, "r");
 	printf("Opening %s\n", filename);
 	return(fp);
     } else {
-	/* open the file */
+	// open the file
 	printf("not opening\n");
 	return(NULL);
     }
 }
 
 
-/* given a file pointer, read all the gdn (geodetic nodes from it.)
-   The specified offset values (in arcsec) are used to overlap the
-   edges of the tile slightly to cover gaps induced by floating point
-   precision problems.  1 arcsec == about 100 feet so 0.01 arcsec ==
-   about 1 foot */
+// given a file pointer, read all the gdn (geodetic nodes from it.)
+// The specified offset values (in arcsec) are used to overlap the
+// edges of the tile slightly to cover gaps induced by floating point
+// precision problems.  1 arcsec == about 100 feet so 0.01 arcsec ==
+// about 1 foot
 void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
     double n[3];
     char line[256];
@@ -388,11 +386,10 @@ void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
 		nodes[nodecount][1] = n[1] + offset_lat;
 		nodes[nodecount][2] = n[2];
 
-		/*
-		  printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
-		      nodes[nodecount][0], nodes[nodecount][1], 
-		      nodes[nodecount][2], line);
-		      */
+		// printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
+		//        nodes[nodecount][0], nodes[nodecount][1], 
+		//        nodes[nodecount][2], line);
+		     
 
 		nodecount++;
 	    } else {
@@ -406,8 +403,8 @@ void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
 }
 
 
-/* load in nodes from the various split and shared pieces to
- * reconstruct a tile */
+// load in nodes from the various split and shared pieces to
+// reconstruct a tile
 void build_node_list(char *basename, char *basepath) {
     char exfile[256];
     FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
@@ -455,19 +452,19 @@ void build_node_list(char *basename, char *basepath) {
 }
 
 
-/* dump in WaveFront .obj format */
+// dump in WaveFront .obj format
 void dump_nodes(char *basename) {
     char file[256];
     FILE *fd;
     int i;
 
-    /* generate output file name */
+    // generate output file name
     strcpy(file, basename);
     // len = strlen(file);
     // file[len-2] = '\0';
     strcat(file, ".node");
     
-    /* dump vertices */
+    // dump vertices
     printf("Creating node file:  %s\n", file);
     printf("  writing vertices in .node format.\n");
     fd = fopen(file, "w");
@@ -480,7 +477,7 @@ void dump_nodes(char *basename) {
 		i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
     }
 
-    /* now write out actual node data */
+    // now write out actual node data
     for ( i = 0; i < nodecount; i++ ) {
 	fprintf(fd, "%d %.2f %.2f %.2f 0\n", excount + i + 1,
 	       nodes[i][0], nodes[i][1], nodes[i][2]);
@@ -499,13 +496,13 @@ int main(int argc, char **argv) {
     strcpy(basename, argv[1]);
     len = strlen(basename);
 
-    /* find the base path of the file */
+    // find the base path of the file
     extract_path(basename, basepath);
     extract_path(basepath, basepath);
     extract_path(basepath, basepath);
     printf("%s\n", basepath);
 
-    /* find the index of the current file */
+    // find the index of the current file
     extract_file(basename, temp);
     // len = strlen(temp);
     // if ( len >= 2 ) {
@@ -517,7 +514,7 @@ int main(int argc, char **argv) {
 
     printf("bucket = %d %d %d %d\n", 
 	   my_index.lon, my_index.lat, my_index.x, my_index.y);
-    /* generate the indexes of the neighbors */
+    // generate the indexes of the neighbors
     fgBucketOffset(&my_index, &ne_index,  1,  1);
     fgBucketOffset(&my_index, &nw_index, -1,  1);
     fgBucketOffset(&my_index, &se_index,  1, -1);
@@ -528,68 +525,70 @@ int main(int argc, char **argv) {
     fgBucketOffset(&my_index, &east_index,  1,  0);
     fgBucketOffset(&my_index, &west_index, -1,  0);
 
-    /*
-    printf("Corner indexes = %ld %ld %ld %ld\n", 
-	   ne_index, nw_index, sw_index, se_index);
-    printf("Edge indexes = %ld %ld %ld %ld\n",
-	   north_index, south_index, east_index, west_index);
-	   */
+    // printf("Corner indexes = %ld %ld %ld %ld\n", 
+    //        ne_index, nw_index, sw_index, se_index);
+    // printf("Edge indexes = %ld %ld %ld %ld\n",
+    //        north_index, south_index, east_index, west_index);
+	  
 
-    /* load the input data files */
+    // load the input data files
     build_node_list(basename, basepath);
 
-    /* dump in WaveFront .obj format */
+    // dump in WaveFront .obj format
     dump_nodes(basename);
 
     return(0);
 }
 
 
-/* $Log$
-/* Revision 1.13  1998/09/21 20:56:30  curt
-/* Changes to avoid setting airport area nodes back to their original
-/* elevations if they have been changed.
-/*
- *
- * Revision 1.12  1998/09/09 16:24:51  curt
- * Fixed a bug in the handling of exclude files which was causing
- *   a crash by calling fclose() on an invalid file handle.
- * Removed overlapping offsets.
- *
- * Revision 1.11  1998/08/06 12:47:59  curt
- * Removed overlap in tiles as a test.
- *
- * Revision 1.10  1998/07/21 04:34:20  curt
- * Mods to handle extra nodes (i.e. preserve cutouts).
- *
- * Revision 1.9  1998/07/04 00:55:39  curt
- * typedef'd struct fgBUCKET.
- *
- * Revision 1.8  1998/06/01 17:58:19  curt
- * Added a slight border overlap to try to minimize pixel wide gaps between
- * tiles due to round off error.  This is not a perfect solution, but helps.
- *
- * Revision 1.7  1998/04/14 02:26:00  curt
- * Code reorganizations.  Added a Lib/ directory for more general libraries.
- *
- * Revision 1.6  1998/04/08 22:54:58  curt
- * Adopted Gnu automake/autoconf system.
- *
- * Revision 1.5  1998/03/03 16:00:52  curt
- * More c++ compile tweaks.
- *
- * Revision 1.4  1998/01/31 00:41:23  curt
- * Made a few changes converting floats to doubles.
- *
- * Revision 1.3  1998/01/27 18:37:00  curt
- * Lots of updates to get back in sync with changes made over in .../Src/
- *
- * Revision 1.2  1998/01/15 21:33:36  curt
- * Assembling triangles and building a new .node file with the proper shared
- * vertices now works.  Now we just have to use the shared normals and we'll
- * be all set.
- *
- * Revision 1.1  1998/01/15 02:45:26  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.1  1998/09/25 19:35:29  curt
+// Renamed assemtris.[ch] to assemtris.[ch]xx
+//
+// Revision 1.13  1998/09/21 20:56:30  curt
+// Changes to avoid setting airport area nodes back to their original
+// elevations if they have been changed.
+//
+//
+// Revision 1.12  1998/09/09 16:24:51  curt
+// Fixed a bug in the handling of exclude files which was causing
+//   a crash by calling fclose() on an invalid file handle.
+// Removed overlapping offsets.
+//
+// Revision 1.11  1998/08/06 12:47:59  curt
+// Removed overlap in tiles as a test.
+//
+// Revision 1.10  1998/07/21 04:34:20  curt
+// Mods to handle extra nodes (i.e. preserve cutouts).
+//
+// Revision 1.9  1998/07/04 00:55:39  curt
+// typedef'd struct fgBUCKET.
+//
+// Revision 1.8  1998/06/01 17:58:19  curt
+// Added a slight border overlap to try to minimize pixel wide gaps between
+// tiles due to round off error.  This is not a perfect solution, but helps.
+//
+// Revision 1.7  1998/04/14 02:26:00  curt
+// Code reorganizations.  Added a Lib/ directory for more general libraries.
+//
+// Revision 1.6  1998/04/08 22:54:58  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.5  1998/03/03 16:00:52  curt
+// More c++ compile tweaks.
+//
+// Revision 1.4  1998/01/31 00:41:23  curt
+// Made a few changes converting floats to doubles.
+//
+// Revision 1.3  1998/01/27 18:37:00  curt
+// Lots of updates to get back in sync with changes made over in .../Src/
+//
+// Revision 1.2  1998/01/15 21:33:36  curt
+// Assembling triangles and building a new .node file with the proper shared
+// vertices now works.  Now we just have to use the shared normals and we'll
+// be all set.
+//
+// Revision 1.1  1998/01/15 02:45:26  curt
+// Initial revision.
+//
+
diff --git a/AssemTris/assemtris.h b/AssemTris/assemtris.h
deleted file mode 100644
index 44900c4c7..000000000
--- a/AssemTris/assemtris.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* splittris.h -- reassemble the pieces produced by splittris
- *
- * Written by Curtis Olson, started January 1998.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
-
-
-#ifndef ASSEMTRIS_H
-#define ASSEMTRIS_H
-
-
-#include <stdio.h>
-#include <string.h>
-
-
-#define MAX_NODES 200000
-#define MAX_TRIS  400000
-
-
-#endif /* SPLITTRIS_H */
-
-
-/* $Log$
-/* Revision 1.1  1998/01/15 02:45:26  curt
-/* Initial revision.
-/*
- */
diff --git a/AssemTris/assemtris.hxx b/AssemTris/assemtris.hxx
new file mode 100644
index 000000000..ad22792a0
--- /dev/null
+++ b/AssemTris/assemtris.hxx
@@ -0,0 +1,48 @@
+// splittris.h -- reassemble the pieces produced by splittris
+//
+// Written by Curtis Olson, started January 1998.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+
+#ifndef ASSEMTRIS_H
+#define ASSEMTRIS_H
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+#define MAX_NODES 200000
+#define MAX_TRIS  400000
+
+
+#endif // SPLITTRIS_H
+
+
+// $Log$
+// Revision 1.1  1998/09/25 19:35:31  curt
+// Renamed assemtris.[ch] to assemtris.[ch]xx
+//
+// Revision 1.1  1998/01/15 02:45:26  curt
+// Initial revision.
+//
+

From bc6d579c5c71b781189807ee7e5eb743c1439475 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 25 Sep 1998 19:38:01 +0000
Subject: [PATCH 152/283] Minor tweaks so that this actually compiles.

---
 AssemTris/assemtris.cxx | 9 ++++++---
 AssemTris/assemtris.hxx | 5 ++++-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/AssemTris/assemtris.cxx b/AssemTris/assemtris.cxx
index 481943f2e..332a670d8 100644
--- a/AssemTris/assemtris.cxx
+++ b/AssemTris/assemtris.cxx
@@ -1,8 +1,8 @@
-// assemtris.c -- reassemble the pieces produced by splittris
+// assemtris.cxx -- reassemble the pieces produced by splittris
 //
 // Written by Curtis Olson, started January 1998.
 //
-// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+// Copyright (C) 1997  Curtis L. Olson  - curt@me.umn.edu
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@
 #include <sys/stat.h> // for stat()
 #include <unistd.h>   // for stat()
 
-#include "assemtris.h"
+#include "assemtris.hxx"
 
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
@@ -542,6 +542,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.2  1998/09/25 19:38:01  curt
+// Minor tweaks so that this actually compiles.
+//
 // Revision 1.1  1998/09/25 19:35:29  curt
 // Renamed assemtris.[ch] to assemtris.[ch]xx
 //
diff --git a/AssemTris/assemtris.hxx b/AssemTris/assemtris.hxx
index ad22792a0..3c96881f4 100644
--- a/AssemTris/assemtris.hxx
+++ b/AssemTris/assemtris.hxx
@@ -1,4 +1,4 @@
-// splittris.h -- reassemble the pieces produced by splittris
+// splittris.hxx -- reassemble the pieces produced by splittris
 //
 // Written by Curtis Olson, started January 1998.
 //
@@ -39,6 +39,9 @@
 
 
 // $Log$
+// Revision 1.2  1998/09/25 19:38:03  curt
+// Minor tweaks so that this actually compiles.
+//
 // Revision 1.1  1998/09/25 19:35:31  curt
 // Renamed assemtris.[ch] to assemtris.[ch]xx
 //

From 2e1f12b96e83878f3bc38e39945be69aeb1241c2 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 2 Oct 1998 21:40:56 +0000
Subject: [PATCH 153/283] Initial revision.

---
 Makedir/Makefile.am |   7 +++
 Makedir/makedir.cxx | 120 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100644 Makedir/Makefile.am
 create mode 100644 Makedir/makedir.cxx

diff --git a/Makedir/Makefile.am b/Makedir/Makefile.am
new file mode 100644
index 000000000..c83672258
--- /dev/null
+++ b/Makedir/Makefile.am
@@ -0,0 +1,7 @@
+bin_PROGRAMS = makedir
+
+makedir_SOURCES = makedir.cxx
+
+makedir_LDADD = $(top_builddir)/Lib/Bucket/libBucket.a
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
diff --git a/Makedir/makedir.cxx b/Makedir/makedir.cxx
new file mode 100644
index 000000000..96563cf1a
--- /dev/null
+++ b/Makedir/makedir.cxx
@@ -0,0 +1,120 @@
+#include <ctype.h>    // isspace()
+#include <stdlib.h>   // atoi()
+#include <math.h>     // rint()
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h> // stat()
+#include <unistd.h>   // stat()
+
+#include <string>
+
+#include <Bucket/bucketutils.h>
+
+#ifdef __CYGWIN32__
+#  define MKDIR(a) mkdir(a,S_IRWXU)     // I am just guessing at this flag
+(NHV)
+#endif // __CYGWIN32__
+
+#ifdef __CYGWIN32__
+
+// return the file path name ( foo/bar/file.ext = foo/bar )
+static void extract_path (char *in, char *base) {
+    int len, i;
+
+    len = strlen (in);
+    strcpy (base, in);
+
+    i = len - 1;
+    while ( (i >= 0) && (in[i] != '/') ) {
+	i--;
+    }
+
+    base[i] = '\0';
+}
+
+
+// Make a subdirectory
+static int my_mkdir (char *dir) {
+    struct stat stat_buf;
+    int result;
+
+    printf ("mk_dir() ");
+
+    result = stat (dir, &stat_buf);
+
+    if (result != 0) {
+	MKDIR (dir);
+	result = stat (dir, &stat_buf);
+	if (result != 0) {
+	    printf ("problem creating %s\n", dir);
+	} else {
+	    printf ("%s created\n", dir);
+	}
+    } else {
+	printf ("%s already exists\n", dir);
+    }
+
+    return (result);
+}
+
+#endif // __CYGWIN32__
+
+
+void scenery_dir( const string& dir ) {
+    struct stat stat_buf;
+    char base_path[256], file[256], exfile[256];
+#ifdef __CYGWIN32__
+    char tmp_path[256];
+#endif
+    string command;
+    FILE *fd;
+	fgBUCKET p;
+	int result;
+
+    cout << "Dir = " + dir + "\n";
+
+    // stat() directory and create if needed
+    result = stat(dir.c_str(), &stat_buf);
+    if ( result != 0 ) {
+	cout << "Stat error need to create directory\n";
+
+#ifndef __CYGWIN32__
+
+	command = "mkdir -p " + dir + "\n";
+	system( command.c_str() );
+
+#else // __CYGWIN32__
+
+	// Cygwin crashes when trying to output to node file
+	// explicitly making directory structure seems OK on Win95
+
+	extract_path (base_path, tmp_path);
+
+	dir = tmp_path;
+	if (my_mkdir ( dir.c_str() )) {	exit (-1); }
+
+	dir = base_path;
+	if (my_mkdir ( dir.c_str() )) {	exit (-1); }
+
+#endif // __CYGWIN32__
+
+    } else {
+	// assume directory exists
+		cout << "  Allready Exists !\n";
+    }
+}
+
+int main(int argc, char **argv)
+{
+	string root;
+
+	if(argc != 2)
+	{
+		cout << "Makedir failed\n";
+		return(10);
+	}
+	root = argv[1];
+	scenery_dir(root);
+
+	return(0);
+}

From b7da079ecc52c4c61a343bf9bd1d39603f0271f1 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 2 Oct 1998 21:41:39 +0000
Subject: [PATCH 154/283] Fixes for win32.

---
 DEM/dem.cxx | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index ed55e1efd..8b474c955 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -729,10 +729,10 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
 	dir = fg_root + "/Scenery";
 	if (my_mkdir ( dir.c_str() )) { exit (-1); }
 
-	dir += fg_root + "/Scenery/" + tmp_path;
+	dir = fg_root + "/Scenery/" + tmp_path;
 	if (my_mkdir ( dir.c_str() )) { exit (-1); }
 
-	dir += fg_root + "/Scenery/" + base_path;
+	dir = fg_root + "/Scenery/" + base_path;
 	if (my_mkdir ( dir.c_str() )) { exit (-1); }
 
 #endif // WIN32
@@ -819,6 +819,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.16  1998/10/02 21:41:39  curt
+// Fixes for win32.
+//
 // Revision 1.15  1998/09/21 20:53:59  curt
 // minor tweaks to clean a few additional things up after the rewrite.
 //

From 621b7a117bf2a4620ffb62c27f567b5de5702012 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 2 Oct 1998 21:41:55 +0000
Subject: [PATCH 155/283] Added Makedir + fixes for win32.

---
 Tools/Makefile.am    |  1 +
 Tools/process-dem.pl | 31 ++++++++++++++++++++++++++++---
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 7fd79620f..41cc40b7c 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -9,6 +9,7 @@ SUBDIRS = \
 	FixNode \
 	FixObj \
 	GenAirports \
+	Makedir \
 	SplitTris \
 	Stripe_w \
 	Tri2obj \
diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index d81f53b4a..5751ec498 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -99,7 +99,8 @@ sub fix_command {
     chop($system);
 
     if ( $system =~ m/CYGWIN32/ ) { 
-	$in =~ s/\//\\\\/;
+        $in =~ s/\/+/\//g;
+        $in =~ s/\//\\/g;
     }
 
     return($in);
@@ -440,8 +441,26 @@ sub install {
     $tmp =~ s/$work_dir//;
     # print "Temp dir = $tmp\n";
     $install_dir = "$fg_root/$tmp";
+
+    # try to get rid of double //
+    $install_dir =~ s/\/+/\//g;
     print "Install dir = $install_dir\n";
-    system("mkdir -p $install_dir");
+
+    if ( $system !~ m/CYGWIN32/ ) {
+	$command = "mkdir -p $install_dir";
+    } else {
+        $command = "Makedir/makedir $install_dir";
+	$command = fix_command($command);
+    }
+
+    # system($command);
+
+    open(OUT, "$command |");
+    while ( <OUT> ) {
+	print $_;
+    }
+    close(OUT);
+
 
     # write out version and info record
     open(VERSION, ">$install_dir/VERSION") || 
@@ -461,7 +480,10 @@ sub install {
 	if ( $file =~ m/\d\d.obj$/ ) {
 	    $new_file = file_root($file);
 	    
-	    $command = "gzip -v --best < $subdir/$file > $install_dir/$new_file.gz";
+	    $command = 
+		"gzip -v --best < $subdir/$file > $install_dir/$new_file.gz";
+	    $command = fix_command($command);
+
 	    # $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
@@ -489,6 +511,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.29  1998/10/02 21:41:56  curt
+# Added Makedir + fixes for win32.
+#
 # Revision 1.28  1998/09/17 18:40:15  curt
 # Changes to allow multiple copies of the scenery processing tools
 # to be run concurrently.

From 24c9bdb71338f399c554953629dbbfab3af2bb1c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 16 Oct 1998 19:08:12 +0000
Subject: [PATCH 156/283] Portability updates from Bernie Bright.

---
 DEM/dem.cxx | 80 ++++++++++++++++++++++++++++++++++++++---------------
 DEM/dem.hxx |  5 +++-
 2 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 8b474c955..27497f2d8 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -34,13 +34,17 @@
 #include <stdio.h>
 #include <string.h>
 #include <sys/stat.h> // stat()
-#include <unistd.h>   // stat()
-
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>   // stat()
+#endif
 #include <string>
 
 // #include <zlib/zlib.h>
 #include <Misc/fgstream.hxx>
 #include <Misc/strutils.hxx>
+#include <Include/compiler.h>
+FG_USING_NAMESPACE(std);
 
 #include "dem.hxx"
 #include "leastsqs.hxx"
@@ -51,7 +55,12 @@
 #define MAX_EX_NODES 10000
 
 #ifdef WIN32
-#  define MKDIR(a) mkdir(a,S_IRWXU)     // I am just guessing at this flag (NHV)
+# ifdef __BORLANDC__
+#  include <dir.h>
+#  define MKDIR(a) mkdir(a)
+# else
+#  define MKDIR(a) mkdir(a,S_IRWXU)  // I am just guessing at this flag (NHV)
+# endif // __BORLANDC__
 #endif // WIN32
 
 
@@ -65,7 +74,7 @@ fgDEM::fgDEM( void ) {
 #ifdef WIN32
 
 // return the file path name ( foo/bar/file.ext = foo/bar )
-static void extract_path (char *in, char *base) {
+static void extract_path ( const char *in, char *base) {
     int len, i;
     
     len = strlen (in);
@@ -81,7 +90,7 @@ static void extract_path (char *in, char *base) {
 
 
 // Make a subdirectory
-static int my_mkdir (char *dir) {
+static int my_mkdir (const char *dir) {
     struct stat stat_buf;
     int result;
 
@@ -118,11 +127,11 @@ int fgDEM::open ( const string& file ) {
 	return 0;
     } else {
 	in = new fg_gzifstream( file );
-	if ( !in ) {
-	    cout << "Cannot open " + file + "\n";
+	if ( !(*in) ) {
+	    cout << "Cannot open " << file << endl;
 	    return 0;
 	}
-	cout << "Loading DEM data file: " + file + "\n";
+	cout << "Loading DEM data file: " << file << endl;
     }
 
     return 1;
@@ -133,7 +142,7 @@ int fgDEM::open ( const string& file ) {
 int fgDEM::close () {
     // the fg_gzifstream doesn't seem to have a close()
 
-    delete(in);
+    delete in;
 
     return 1;
 }
@@ -172,7 +181,7 @@ double fgDEM::next_double() {
 
 
 // return next exponential num from input stream
-int fgDEM::next_exp() {
+double fgDEM::next_exp() {
     string token;
     double mantissa;
     int exp, acc;
@@ -180,6 +189,21 @@ int fgDEM::next_exp() {
 
     token = next_token();
 
+#if 1
+    const char* p = token.c_str();
+    char buf[64];
+    char* bp = buf;
+    
+    for ( ; *p != 0; ++p )
+    {
+	if ( *p == 'D' )
+	    *bp++ = 'E';
+	else
+	    *bp++ = *p;
+    }
+    *bp = 0;
+    return ::atof( buf );
+#else
     sscanf(token.c_str(), "%lfD%d", &mantissa, &exp);
 
     // cout << "    Mantissa = " << mantissa << "  Exp = " << exp << "\n";
@@ -196,6 +220,7 @@ int fgDEM::next_exp() {
     }
 
     return( (int)rint(mantissa * (double)acc) );
+#endif
 }
 
 
@@ -214,8 +239,8 @@ int fgDEM::read_a_record() {
     }
   
     // clean off the trailing whitespace
-    name = trim(name);
-    cout << "    Quad name field: " + name + "\n";
+    name = trim(name, " ");
+    cout << "    Quad name field: " << name << endl;
 
     // DEM level code, 3 reflects processing by DMA
     inum = next_int();
@@ -301,10 +326,16 @@ int fgDEM::read_a_record() {
     // I will eventually have to do something with this for data at
     // higher latitudes */
     token = next_token();
-    cout << "    accuracy & spacial resolution string = " + token + "\n";
+    cout << "    accuracy & spacial resolution string = " << token << endl;
     i = token.length();
     cout << "    length = " << i << "\n";
 
+#if 1
+    inum = atoi( token.substr( 0, 1 ) );
+    row_step = atof( token.substr( 1, 12 ) );
+    col_step = atof( token.substr( 13, 12 ) );
+    //token.substr( 25, 12 )
+#else
     ptr = token.c_str() + i - 12;
     cout << "    last field = " << ptr << " = " << atof(ptr) << "\n";
     ptr[0] = '\0';
@@ -322,6 +353,7 @@ int fgDEM::read_a_record() {
     // accuracy code = atod(token)
     ptr = ptr - 12;
     inum = atoi(ptr);
+#endif
     cout << "    Accuracy code = " << inum << "\n";
 
     cout << "    column step = " << col_step << 
@@ -682,7 +714,6 @@ void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
 // since they are referenced by position from the .poly file.
 void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
     double exnodes[MAX_EX_NODES][3];
-    double junk1, junk2, junk3;
     struct stat stat_buf;
     string dir;
     char base_path[256], file[256], exfile[256];
@@ -705,14 +736,15 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
 
     // generate the base directory
     fgBucketGenBasePath(p, base_path);
-    cout << "fg_root = " + fg_root + "  Base Path = " + base_path + "\n";
+    cout << "fg_root = " << fg_root << "  Base Path = " << base_path << endl;
     dir = fg_root + "/Scenery/" + base_path;
-    cout << "Dir = " + dir + "\n";
+    cout << "Dir = " << dir << endl;
     
     // stat() directory and create if needed
+    errno = 0;
     result = stat(dir.c_str(), &stat_buf);
-    if ( result != 0 ) {
-	cout << "Stat error need to create directory\n";
+    if ( result != 0 && errno == ENOENT ) {
+	cout << "Creating directory\n";
 
 #ifndef WIN32
 
@@ -753,7 +785,8 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
     // load extra nodes if they exist
     excount = 0;
     if ( (fd = fopen(exfile, "r")) != NULL ) {
-	fscanf(fd, "%d %d %d %d", &excount, &junk1, &junk2, &junk3);
+	int junki;
+	fscanf(fd, "%d %d %d %d", &excount, &junki, &junki, &junki);
 
 	if ( excount > MAX_EX_NODES - 1 ) {
 	    printf("Error, too many 'extra' nodes, increase array size\n");
@@ -763,7 +796,7 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
 	}
 
 	for ( i = 1; i <= excount; i++ ) {
-	    fscanf(fd, "%d %lf %lf %lf\n", &junk1, 
+	    fscanf(fd, "%d %lf %lf %lf\n", &junki, 
 		   &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]);
 	    printf("(extra) %d %.2f %.2f %.2f\n", 
 		    i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
@@ -813,12 +846,15 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
 
 fgDEM::~fgDEM( void ) {
     // printf("class fgDEM DEstructor called.\n");
-    delete(dem_data);
-    delete(output_data);
+    delete [] dem_data;
+    delete [] output_data;
 }
 
 
 // $Log$
+// Revision 1.17  1998/10/16 19:08:12  curt
+// Portability updates from Bernie Bright.
+//
 // Revision 1.16  1998/10/02 21:41:39  curt
 // Fixes for win32.
 //
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index de96a3700..1b24b6a29 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -90,7 +90,7 @@ class fgDEM {
     double next_double();
 
     // return next exponential num from input stream
-    int next_exp();
+    double next_exp();
 
 public:
 
@@ -145,6 +145,9 @@ public:
 
 
 // $Log$
+// Revision 1.9  1998/10/16 19:08:14  curt
+// Portability updates from Bernie Bright.
+//
 // Revision 1.8  1998/09/19 17:59:46  curt
 // Use c++ streams (fg_gzifstream).  Also converted many character arrays to
 // the string class.

From b0d67bf6b956dd8014344bc4b4934fa4f7861ef4 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 18 Oct 1998 01:17:09 +0000
Subject: [PATCH 157/283] Point3D tweaks.

---
 DEM/dem.cxx             |   5 +-
 SplitTris/Makefile.am   |   4 ++
 SplitTris/splittris.cxx | 156 ++++++++++++++++++----------------------
 SplitTris/splittris.hxx |   7 +-
 Tri2obj/tri2obj.cxx     |  56 +++++----------
 5 files changed, 101 insertions(+), 127 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 27497f2d8..fbadcecda 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -239,7 +239,7 @@ int fgDEM::read_a_record() {
     }
   
     // clean off the trailing whitespace
-    name = trim(name, " ");
+    name = trim(name);
     cout << "    Quad name field: " << name << endl;
 
     // DEM level code, 3 reflects processing by DMA
@@ -852,6 +852,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.18  1998/10/18 01:17:09  curt
+// Point3D tweaks.
+//
 // Revision 1.17  1998/10/16 19:08:12  curt
 // Portability updates from Bernie Bright.
 //
diff --git a/SplitTris/Makefile.am b/SplitTris/Makefile.am
index f43a3081f..8e4c2df64 100644
--- a/SplitTris/Makefile.am
+++ b/SplitTris/Makefile.am
@@ -32,6 +32,7 @@ splittris_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Math/libMath.a \
         $(top_builddir)/Lib/Debug/libDebug.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
         $(top_builddir)/Lib/zlib/libz.a
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
@@ -39,6 +40,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.7  1998/10/18 01:17:25  curt
+# Point3D tweaks.
+#
 # Revision 1.6  1998/07/30 23:49:26  curt
 # Removed libtool support.
 #
diff --git a/SplitTris/splittris.cxx b/SplitTris/splittris.cxx
index e9ec2ff57..5892aa467 100644
--- a/SplitTris/splittris.cxx
+++ b/SplitTris/splittris.cxx
@@ -35,18 +35,19 @@
 #include "splittris.hxx"
 
 #include <Include/fg_constants.h>
-#include <Include/fg_types.h>
 #include <Bucket/bucketutils.h>
 
-#include <Math/fg_geodesy.h>
+#include <Math/fg_geodesy.hxx>
 #include <Math/mat3.h>
+#include <Math/point3d.hxx>
 #include <Math/polar3d.hxx>
+#include <Misc/fgstream.hxx>
 
 // int nodecount, tricount;
 double xmin, xmax, ymin, ymax;
 
 // static double nodes_orig[MAX_NODES][3];
-// static fgPoint3d nodes_cart[MAX_NODES];
+// static Point3D nodes_cart[MAX_NODES];
 // static int tris[MAX_TRIS][3];
 
 container_3d nodes_orig;
@@ -56,42 +57,16 @@ container_tri tri_list;
 fgBUCKET ne_index, nw_index, sw_index, se_index;
 fgBUCKET north_index, south_index, east_index, west_index;
 
-// convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to a
-// cartesian point
-fgPoint3d geod_to_cart(fgPoint3d geod) {
-    fgPoint3d cp;
-    fgPoint3d pp;
-    double gc_lon, gc_lat, sl_radius;
-
-    // printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
-    //        geod[0], geod[1], geod[2]);
-
-    gc_lon = geod.lon * ARCSEC_TO_RAD;
-    fgGeodToGeoc(geod.lat * ARCSEC_TO_RAD, geod.radius, &sl_radius, &gc_lat);
-
-    // printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
-    //        gc_lat, sl_radius+geod[2]);
-
-    pp.lon = gc_lon;
-    pp.lat = gc_lat;
-    pp.radius = sl_radius + geod.radius;
-    cp = fgPolarToCart3d(pp);
-    
-    // printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z);
-
-    return(cp);
-}
-
 
 // given three points defining a triangle, calculate the normal
-void calc_normal(fgPoint3d p1, fgPoint3d p2, 
-		 fgPoint3d p3, double normal[3])
+void calc_normal(const Point3D& p1, const Point3D& p2, 
+		 const Point3D& p3, double normal[3])
 {
     double v1[3], v2[3];
     double temp;
 
-    v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
-    v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
+    v1[0] = p2.x() - p1.x(); v1[1] = p2.y() - p1.y(); v1[2] = p2.z() - p1.z();
+    v2[0] = p3.x() - p1.x(); v2[1] = p3.y() - p1.y(); v2[2] = p3.z() - p1.z();
 
     MAT3cross_product(normal, v1, v2);
     MAT3_NORMALIZE_VEC(normal,temp);
@@ -159,9 +134,8 @@ void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
 // Initialize a new mesh structure
 void triload(const string& basename) {
     string nodename, elename;
-    fgPoint3d node1, node2;
+    Point3D node1, node2;
     triangle tri;
-    FILE *node_file, *ele_file;
     int nodecount, tricount, dim, junk1, junk2;
     int i;
 
@@ -169,7 +143,9 @@ void triload(const string& basename) {
     elename  = basename + ".ele";
 
     cout << "Loading node file:  " + nodename + " ...\n";
-    if ( (node_file = fopen(nodename.c_str(), "r")) == NULL ) {
+
+    fg_gzifstream node_in( nodename );
+    if ( !node_in ) {
 	cout << "Cannot open file " + nodename + "\n";
 	exit(-1);
     }
@@ -181,56 +157,54 @@ void triload(const string& basename) {
     nodes_cart.push_back(node1);
     tri_list.push_back(tri);
 
-    fscanf(node_file, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
+    node_in.stream() >> nodecount >> dim >> junk1 >> junk2;
     cout << "    Expecting " << nodecount << " nodes\n";
 
     for ( i = 1; i <= nodecount; i++ ) {
-	fscanf(node_file, "%d %lf %lf %lf %d\n", &junk1, 
-	       &(node1.x), &(node1.y), &(node1.z), &junk2);
-	printf("%d %.2f %.2f %.2f\n", junk1, node1.x, node1.y, node1.z);
+	node_in.stream() >> junk1 >> node1 >> junk2;
 	nodes_orig.push_back(node1);
-	node2 = geod_to_cart(node1);
+	// printf("%d %.2f %.2f %.2f\n", junk1, node1.x, node1.y, node1.z);
+
+	node2 = fgGeodToCart(node1);
 	nodes_cart.push_back(node2);
-	printf("%d %.2f %.2f %.2f\n", junk1, node2.x, node2.y, node2.z);
+	// printf("%d %.2f %.2f %.2f\n", junk1, node2.x, node2.y, node2.z);
 
 	if ( i == 1 ) {
-	    xmin = xmax = node1.x;
-	    ymin = ymax = node1.y;
+	    xmin = xmax = node1.x();
+	    ymin = ymax = node1.y();
 	} else {
-	    if ( node1.x < xmin ) {
-		xmin = node1.x;
+	    if ( node1.x() < xmin ) {
+		xmin = node1.x();
 	    }
-	    if ( node1.x > xmax ) {
-		xmax = node1.x;
+	    if ( node1.x() > xmax ) {
+		xmax = node1.x();
 	    }
-	    if ( node1.y < ymin ) {
-		ymin = node1.y;
+	    if ( node1.y() < ymin ) {
+		ymin = node1.y();
 	    }
-	    if ( node1.y > ymax ) {
-		ymax = node1.y;
+	    if ( node1.y() > ymax ) {
+		ymax = node1.y();
 	    }
 	}
     }
 
-    fclose(node_file);
-
     cout << "Loading element file:  " + elename + " ...\n";
-    if ( (ele_file = fopen(elename.c_str(), "r")) == NULL ) {
+    fg_gzifstream ele_in( elename );
+    if ( !ele_in ) {
 	cout << "Cannot open file " + elename + "\n";
 	exit(-1);
     }
 
-    fscanf(ele_file, "%d %d %d", &tricount, &junk1, &junk2);
+    ele_in.stream() >> tricount >> junk1 >> junk2;
     cout << "    Expecting " << tricount << " elements\n";
 
     for ( i = 1; i <= tricount; i++ ) {
-	fscanf(ele_file, "%d %d %d %d\n", &junk1, 
-	       &(tri.n1), &(tri.n2), &(tri.n3));
-	printf("%d %d %d %d\n", junk1, tri.n1, tri.n2, tri.n3);
+	// fscanf(ele_file, "%d %d %d %d\n", &junk1, 
+	//        &(tri.n1), &(tri.n2), &(tri.n3));
+	ele_in.stream() >> junk1 >> tri.n1 >> tri.n2 >> tri.n3;
+	// printf("%d %d %d %d\n", junk1, tri.n1, tri.n2, tri.n3);
 	tri_list.push_back(tri);
     }
-
-    fclose(ele_file);
 }
 
 
@@ -413,10 +387,11 @@ FILE *my_open(const string& basename, const string& basepath,
 
 // dump in WaveFront .obj format
 void dump_obj(const string& basename, const string& basepath) {
-    fgPoint3d node;
+    Point3D node;
     double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
     FILE *fp, *sw, *se, *ne, *nw, *north, *south, *east, *west, *body;
     int i, t1, t2, t3, t4, t5, count, size;
+    double x, y, z;
 
     sw = my_open(basename, basepath, ".sw");
     se = my_open(basename, basepath, ".se");
@@ -441,32 +416,36 @@ void dump_obj(const string& basename, const string& basepath) {
     for ( ; current != last; ++current) {
 	node = *current;
 
-	if ( (fabs(node.y - ymin) < FG_EPSILON) && 
-	     (fabs(node.x - xmin) < FG_EPSILON) ) {
+	if ( (fabs(node.y() - ymin) < FG_EPSILON) && 
+	     (fabs(node.x() - xmin) < FG_EPSILON) ) {
 	    fp = sw;
-	} else if ( (fabs(node.y - ymin) < FG_EPSILON) &&
-		    (fabs(node.x - xmax) < FG_EPSILON) ) {
+	} else if ( (fabs(node.y() - ymin) < FG_EPSILON) &&
+		    (fabs(node.x() - xmax) < FG_EPSILON) ) {
 	    fp = se;
-	} else if ( (fabs(node.y - ymax) < FG_EPSILON) &&
-		    (fabs(node.x - xmax) < FG_EPSILON)) {
+	} else if ( (fabs(node.y() - ymax) < FG_EPSILON) &&
+		    (fabs(node.x() - xmax) < FG_EPSILON)) {
 	    fp = ne;
-	} else if ( (fabs(node.y - ymax) < FG_EPSILON) &&
-		    (fabs(node.x - xmin) < FG_EPSILON) ) {
+	} else if ( (fabs(node.y() - ymax) < FG_EPSILON) &&
+		    (fabs(node.x() - xmin) < FG_EPSILON) ) {
 	    fp = nw;
-	} else if ( fabs(node.x - xmin) < FG_EPSILON ) {
+	} else if ( fabs(node.x() - xmin) < FG_EPSILON ) {
 	    fp = west;
-	} else if ( fabs(node.x - xmax) < FG_EPSILON ) {
+	} else if ( fabs(node.x() - xmax) < FG_EPSILON ) {
 	    fp = east;
-	} else if ( fabs(node.y - ymin) < FG_EPSILON ) {
+	} else if ( fabs(node.y() - ymin) < FG_EPSILON ) {
 	    fp = south;
-	} else if ( fabs(node.y - ymax) < FG_EPSILON ) {
+	} else if ( fabs(node.y() - ymax) < FG_EPSILON ) {
 	    fp = north;
 	} else {
 	    fp = body;
 	}
 
+	x = node.x();
+	y = node.y();
+	z = node.z();
+
 	if ( fp != NULL ) {
-	    fprintf(fp, "gdn %.2f %.2f %.2f\n", node.x, node.y, node.z);
+	    fprintf(fp, "gdn %.2f %.2f %.2f\n", x, y, z);
 	}
     }
 
@@ -538,25 +517,25 @@ void dump_obj(const string& basename, const string& basepath) {
 	
 	fp = NULL;
 
-	if ( (fabs(nodes_orig[i].y - ymin) < FG_EPSILON) && 
-	     (fabs(nodes_orig[i].x - xmin) < FG_EPSILON) ) {
+	if ( (fabs(nodes_orig[i].y() - ymin) < FG_EPSILON) && 
+	     (fabs(nodes_orig[i].x() - xmin) < FG_EPSILON) ) {
 	    fp = sw;
-	} else if ( (fabs(nodes_orig[i].y - ymin) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i].x - xmax) < FG_EPSILON) ) {
+	} else if ( (fabs(nodes_orig[i].y() - ymin) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i].x() - xmax) < FG_EPSILON) ) {
 	    fp = se;
-	} else if ( (fabs(nodes_orig[i].y - ymax) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i].x - xmax) < FG_EPSILON)) {
+	} else if ( (fabs(nodes_orig[i].y() - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i].x() - xmax) < FG_EPSILON)) {
 	    fp = ne;
-	} else if ( (fabs(nodes_orig[i].y - ymax) < FG_EPSILON) &&
-		    (fabs(nodes_orig[i].x - xmin) < FG_EPSILON) ) {
+	} else if ( (fabs(nodes_orig[i].y() - ymax) < FG_EPSILON) &&
+		    (fabs(nodes_orig[i].x() - xmin) < FG_EPSILON) ) {
 	    fp = nw;
-	} else if ( fabs(nodes_orig[i].x - xmin) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].x() - xmin) < FG_EPSILON ) {
 	    fp = west;
-	} else if ( fabs(nodes_orig[i].x - xmax) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].x() - xmax) < FG_EPSILON ) {
 	    fp = east;
-	} else if ( fabs(nodes_orig[i].y - ymin) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].y() - ymin) < FG_EPSILON ) {
 	    fp = south;
-	} else if ( fabs(nodes_orig[i].y - ymax) < FG_EPSILON ) {
+	} else if ( fabs(nodes_orig[i].y() - ymax) < FG_EPSILON ) {
 	    fp = north;
 	}
 	if ( fp != NULL ) {
@@ -633,6 +612,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.4  1998/10/18 01:17:27  curt
+// Point3D tweaks.
+//
 // Revision 1.3  1998/09/22 23:49:56  curt
 // C++-ified, STL-ified, and string-ified.
 //
diff --git a/SplitTris/splittris.hxx b/SplitTris/splittris.hxx
index 9a4e058e8..12787872d 100644
--- a/SplitTris/splittris.hxx
+++ b/SplitTris/splittris.hxx
@@ -39,7 +39,7 @@
 using namespace std;
 #endif
 
-#include <Include/fg_types.h>
+#include <Math/point3d.hxx>
 
 
 // A triangle (indices of the three nodes)
@@ -48,7 +48,7 @@ typedef struct {
 } triangle;
 
 
-typedef vector < fgPoint3d > container_3d;
+typedef vector < Point3D > container_3d;
 typedef container_3d::iterator iterator_3d;
 typedef container_3d::const_iterator const_iterator_3d;
 
@@ -65,6 +65,9 @@ void triload(const string& basename);
 
 
 // $Log$
+// Revision 1.4  1998/10/18 01:17:28  curt
+// Point3D tweaks.
+//
 // Revision 1.3  1998/09/22 23:49:58  curt
 // C++-ified, STL-ified, and string-ified.
 //
diff --git a/Tri2obj/tri2obj.cxx b/Tri2obj/tri2obj.cxx
index 732da5c03..dfc374a00 100644
--- a/Tri2obj/tri2obj.cxx
+++ b/Tri2obj/tri2obj.cxx
@@ -36,14 +36,14 @@
 #include <Include/fg_types.h>
 #include <Bucket/bucketutils.h>
 
-#include <Math/fg_geodesy.h>
+#include <Math/fg_geodesy.hxx>
 #include <Math/mat3.h>
 #include <Math/polar3d.hxx>
 
 
 int nodecount, tricount;
 int normalcount = 0;
-static fgPoint3d nodes[MAX_NODES];
+static Point3D nodes[MAX_NODES];
 static int tris[MAX_TRIS][3];
 
 static double normals[MAX_NODES][3];
@@ -52,42 +52,16 @@ fgBUCKET my_index;
 fgBUCKET ne_index, nw_index, sw_index, se_index;
 fgBUCKET north_index, south_index, east_index, west_index;
 
-/* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
- * a cartesian point */
-fgPoint3d geod_to_cart(double geod[3]) {
-    fgPoint3d cp;
-    fgPoint3d pp;
-    double gc_lon, gc_lat, sl_radius;
-
-    /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
-	   geod[0], geod[1], geod[2]); */
-
-    gc_lon = geod[0]*ARCSEC_TO_RAD;
-    fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
-
-    /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
-	   gc_lat, sl_radius+geod[2]); */
-
-    pp.lon = gc_lon;
-    pp.lat = gc_lat;
-    pp.radius = sl_radius + geod[2];
-    cp = fgPolarToCart3d(pp);
-    
-    /* printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z); */
-
-    return(cp);
-}
-
 
 /* given three points defining a triangle, calculate the normal */
-void calc_normal(fgPoint3d p1, fgPoint3d p2, 
-		 fgPoint3d p3, double normal[3])
+void calc_normal(Point3D p1, Point3D p2, 
+		 Point3D p3, double normal[3])
 {
     double v1[3], v2[3];
     double temp;
 
-    v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
-    v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
+    v1[0] = p2.x() - p1.x(); v1[1] = p2.y() - p1.y(); v1[2] = p2.z() - p1.z();
+    v2[0] = p3.x() - p1.x(); v2[1] = p3.y() - p1.y(); v2[2] = p3.z() - p1.z();
 
     MAT3cross_product(normal, v1, v2);
     MAT3_NORMALIZE_VEC(normal, temp);
@@ -407,6 +381,7 @@ FILE *my_open(char *basename, char *basepath, char *ext) {
 void triload(char *basename, char *basepath) {
     char nodename[256], elename[256];
     double n[3];
+    Point3D p;
     FILE *ne, *nw, *se, *sw, *north, *south, *east, *west;
     FILE *node, *ele;
     int dim, junk1, junk2;
@@ -468,7 +443,8 @@ void triload(char *basename, char *basepath) {
 	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
 	       &n[0], &n[1], &n[2], &junk2);
 	/* printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); */
-	nodes[i] = geod_to_cart(n);
+	p = Point3D(n[0], n[1], n[2]);
+	nodes[i] = fgGeodToCart(p);
 	/* printf("%d %.2f %.2f %.2f\n", 
 	       junk1, nodes[i].x, nodes[i].y, nodes[i].z); */
     }
@@ -506,6 +482,7 @@ void dump_obj(char *basename) {
     double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
     FILE *obj;
     int i, t1, t2, t3, t4, t5, count;
+    double x, y, z;
 
     strcpy(objname, basename);
     strcat(objname, ".obj");
@@ -517,8 +494,10 @@ void dump_obj(char *basename) {
     /* dump vertices */
     printf("  writing vertices\n");
     for ( i = 1; i <= nodecount; i++ ) {
-	fprintf(obj, "v %.6f %.6f %.6f\n", 
-		nodes[i].x, nodes[i].y, nodes[i].z);
+	x = nodes[i].x();
+	y = nodes[i].y();
+	z = nodes[i].z();
+	fprintf(obj, "v %.6f %.6f %.6f\n", x, y, z);
     }
 
     printf("  calculating and writing normals\n");
@@ -644,9 +623,12 @@ int main(int argc, char **argv) {
 
 
 /* $Log$
-/* Revision 1.1  1998/07/08 14:54:53  curt
-/* renamed *.[ch] to *.[ch]xx
+/* Revision 1.2  1998/10/18 01:17:29  curt
+/* Point3D tweaks.
 /*
+ * Revision 1.1  1998/07/08 14:54:53  curt
+ * renamed *.[ch] to *.[ch]xx
+ *
  * Revision 1.17  1998/07/04 00:56:40  curt
  * typedef'd struct fgBUCKET.
  *

From 5321d533d689bc26da0fb176e7931b973080aedd Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 19 Oct 1998 19:33:31 +0000
Subject: [PATCH 158/283] C++-ification.

---
 Tri2obj/tri2obj.cxx | 258 ++++++++++++++++++++++----------------------
 1 file changed, 130 insertions(+), 128 deletions(-)

diff --git a/Tri2obj/tri2obj.cxx b/Tri2obj/tri2obj.cxx
index dfc374a00..20ecb0b2b 100644
--- a/Tri2obj/tri2obj.cxx
+++ b/Tri2obj/tri2obj.cxx
@@ -1,34 +1,33 @@
-/* tri2obj.c -- read in a .ele/.node file pair generated by the triangle 
- *              program and output a simple Wavefront .obj file.
- *
- * Written by Curtis Olson, started October 1997.
- *
- * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- */
+// tri2obj.cxx -- read in a .ele/.node file pair generated by the triangle 
+//                program and output a simple Wavefront .obj file.
+//
+// Written by Curtis Olson, started October 1997.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
 
 
 #include <stdio.h>
-#include <stdlib.h>   /* for atoi() */
+#include <stdlib.h>   // for atoi()
 #include <string.h>
-#include <sys/stat.h> /* for stat() */
-#include <unistd.h>   /* for stat() */
+#include <sys/stat.h> // for stat()
+#include <unistd.h>   // for stat()
 
 #include "tri2obj.hxx"
 
@@ -53,7 +52,7 @@ fgBUCKET ne_index, nw_index, sw_index, se_index;
 fgBUCKET north_index, south_index, east_index, west_index;
 
 
-/* given three points defining a triangle, calculate the normal */
+// given three points defining a triangle, calculate the normal
 void calc_normal(Point3D p1, Point3D p2, 
 		 Point3D p3, double normal[3])
 {
@@ -66,11 +65,11 @@ void calc_normal(Point3D p1, Point3D p2,
     MAT3cross_product(normal, v1, v2);
     MAT3_NORMALIZE_VEC(normal, temp);
 
-/*  printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
+//  printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]);
 }
 
 
-/* return the index of all triangles containing the specified node */
+// return the index of all triangles containing the specified node
 void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
     int i;
 
@@ -96,7 +95,7 @@ void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
 }
 
 
-/* return the file base name ( foo/bar/file.ext = file.ext ) */
+// return the file base name ( foo/bar/file.ext = file.ext )
 void extract_file(char *in, char *base) {
     int len, i;
 
@@ -112,7 +111,7 @@ void extract_file(char *in, char *base) {
 }
 
 
-/* return the file path name ( foo/bar/file.ext = foo/bar ) */
+// return the file path name ( foo/bar/file.ext = foo/bar )
 void extract_path(char *in, char *base) {
     int len, i;
 
@@ -128,7 +127,7 @@ void extract_path(char *in, char *base) {
 }
 
 
-/* check if a file exists */
+// check if a file exists
 int file_exists(char *file) {
     struct stat stat_buf;
     int result;
@@ -138,18 +137,18 @@ int file_exists(char *file) {
     result = stat(file, &stat_buf);
 
     if ( result != 0 ) {
-	/* stat failed, no file */
+	// stat failed, no file
 	printf("not found.\n");
 	return(0);
     } else {
-	/* stat succeeded, file exists */
+	// stat succeeded, file exists
 	printf("exists.\n");
 	return(1);
     }
 }
 
 
-/* check to see if a shared object exists */
+// check to see if a shared object exists
 int shared_object_exists(char *basepath, char *ext, char *file) {
     char scene_path[256];
     long int index;
@@ -335,7 +334,7 @@ int shared_object_exists(char *basepath, char *ext, char *file) {
 }
 
 
-/* given a file pointer, read all the vn (normals from it) */
+// given a file pointer, read all the vn (normals from it)
 void read_normals(FILE *fp) {
     char line[256];
 
@@ -356,28 +355,28 @@ void read_normals(FILE *fp) {
 }
 
 
-/* my custom file opening routine ... don't open if a shared edge or
- * vertex alread exists */
+// my custom file opening routine ... don't open if a shared edge or
+// vertex alread exists
 FILE *my_open(char *basename, char *basepath, char *ext) {
     FILE *fp;
     char filename[256];
 
-    /* check if a shared object already exists */
+    // check if a shared object already exists
     if ( shared_object_exists(basepath, ext, filename) ) {
-	/* not an actual file open error, but we've already got the
-         * shared edge, so we don't want to create another one */
+	// not an actual file open error, but we've already got the
+        // shared edge, so we don't want to create another one
 	fp = fopen(filename, "r");
 	printf("Opening %s\n", filename);
 	return(fp);
     } else {
-	/* open the file */
+	// open the file
 	printf("not opening\n");
 	return(NULL);
     }
 }
 
 
-/* Initialize a new mesh structure */
+// Initialize a new mesh structure
 void triload(char *basename, char *basepath) {
     char nodename[256], elename[256];
     double n[3];
@@ -442,11 +441,11 @@ void triload(char *basename, char *basepath) {
     for ( i = 1; i <= nodecount; i++ ) {
 	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
 	       &n[0], &n[1], &n[2], &junk2);
-	/* printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); */
+	// printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]);
 	p = Point3D(n[0], n[1], n[2]);
 	nodes[i] = fgGeodToCart(p);
-	/* printf("%d %.2f %.2f %.2f\n", 
-	       junk1, nodes[i].x, nodes[i].y, nodes[i].z); */
+	// printf("%d %.2f %.2f %.2f\n", 
+	//        junk1, nodes[i].x, nodes[i].y, nodes[i].z);
     }
 
     fclose(node);
@@ -469,14 +468,14 @@ void triload(char *basename, char *basepath) {
     for ( i = 1; i <= tricount; i++ ) {
 	fscanf(ele, "%d %d %d %d\n", &junk1, 
 	       &tris[i][0], &tris[i][1], &tris[i][2]);
-	/* printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
+	// printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
     }
 
     fclose(ele);
 }
 
 
-/* dump in WaveFront .obj format */
+// dump in WaveFront .obj format
 void dump_obj(char *basename) {
     char objname[256];
     double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
@@ -491,7 +490,7 @@ void dump_obj(char *basename) {
 
     obj = fopen(objname, "w");
 
-    /* dump vertices */
+    // dump vertices
     printf("  writing vertices\n");
     for ( i = 1; i <= nodecount; i++ ) {
 	x = nodes[i].x();
@@ -503,16 +502,16 @@ void dump_obj(char *basename) {
     printf("  calculating and writing normals\n");
     printf("  First %d normals taken from shared files.\n", normalcount);
 						     
-    /* calculate and generate normals */
+    // calculate and generate normals
     for ( i = 1; i <= nodecount; i++ ) {
 
 	if ( i <= normalcount ) {
-	    /* use precalculated (shared) normal */
+	    // use precalculated (shared) normal
 	    norm[0] = normals[i-1][0];
 	    norm[1] = normals[i-1][1];
 	    norm[2] = normals[i-1][2];
 	} else {
-	    /* printf("Finding normal\n"); */
+	    // printf("Finding normal\n");
 
 	    find_tris(i, &t1, &t2, &t3, &t4, &t5);
 
@@ -550,24 +549,24 @@ void dump_obj(char *basename) {
 		count = 5;
 	    }
 
-	    /* printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
+	    // printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]);
 
 	    norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count;
 	    norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count;
 	    norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count;
 	
-	    /* 	printf("  count = %d\n", count); */
-	    /* 	printf("  Ave. normal = %.4f %.4f %.4f\n", 
-		       norm[0], norm[1], norm[2]);*/
+	    // 	printf("  count = %d\n", count);
+	    // 	printf("  Ave. normal = %.4f %.4f %.4f\n", 
+	    //         norm[0], norm[1], norm[2]);*/
 	    MAT3_NORMALIZE_VEC(norm, temp);
-	    /* 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
-	    /* 	       norm[0], norm[1], norm[2]); */
+	    // 	printf("  Normalized ave. normal = %.4f %.4f %.4f\n", 
+	    // 	       norm[0], norm[1], norm[2]);
 	}
-	/* printf("%d vn %.4f %.4f %.4f\n", i, norm[0], norm[1], norm[2]); */
+	// printf("%d vn %.4f %.4f %.4f\n", i, norm[0], norm[1], norm[2]);
 	fprintf(obj, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
     }
 
-    /* dump faces */
+    // dump faces
     printf("  writing faces\n");
     for ( i = 1; i <= tricount; i++ ) {
 	fprintf(obj, "f %d %d %d\n", tris[i][0], tris[i][1], tris[i][2]);
@@ -583,13 +582,13 @@ int main(int argc, char **argv) {
 
     strcpy(basename, argv[1]);
 
-    /* find the base path of the file */
+    // find the base path of the file
     extract_path(basename, basepath);
     extract_path(basepath, basepath);
     extract_path(basepath, basepath);
     printf("%s\n", basepath);
 
-    /* find the index of the current file */
+    // find the index of the current file
     extract_file(basename, temp);
     len = strlen(temp);
     if ( len >= 2 ) {
@@ -601,7 +600,7 @@ int main(int argc, char **argv) {
 
     printf("bucket = %d %d %d %d\n", 
 	   my_index.lon, my_index.lat, my_index.x, my_index.y);
-    /* generate the indexes of the neighbors */
+    // generate the indexes of the neighbors
     fgBucketOffset(&my_index, &ne_index,  1,  1);
     fgBucketOffset(&my_index, &nw_index, -1,  1);
     fgBucketOffset(&my_index, &se_index,  1, -1);
@@ -612,75 +611,78 @@ int main(int argc, char **argv) {
     fgBucketOffset(&my_index, &east_index,  1,  0);
     fgBucketOffset(&my_index, &west_index, -1,  0);
 
-    /* load the input data files */
+    // load the input data files
     triload(basename, basepath);
 
-    /* dump in WaveFront .obj format */
+    // dump in WaveFront .obj format
     dump_obj(basename);
 
     return(0);
 }
 
 
-/* $Log$
-/* Revision 1.2  1998/10/18 01:17:29  curt
-/* Point3D tweaks.
-/*
- * Revision 1.1  1998/07/08 14:54:53  curt
- * renamed *.[ch] to *.[ch]xx
- *
- * Revision 1.17  1998/07/04 00:56:40  curt
- * typedef'd struct fgBUCKET.
- *
- * Revision 1.16  1998/05/23 15:20:41  curt
- * Output more digits after the decimal place.
- *
- * Revision 1.15  1998/05/02 01:54:39  curt
- * Converting to polar3d.h routines.
- *
- * Revision 1.14  1998/04/18 04:01:32  curt
- * Now use libMath rather than having local copies of math routines.
- *
- * Revision 1.13  1998/04/14 02:26:11  curt
- * Code reorganizations.  Added a Lib/ directory for more general libraries.
- *
- * Revision 1.12  1998/04/08 23:22:18  curt
- * Adopted Gnu automake/autoconf system.
- *
- * Revision 1.11  1998/03/03 16:01:00  curt
- * More c++ compile tweaks.
- *
- * Revision 1.10  1998/01/31 00:41:27  curt
- * Made a few changes converting floats to doubles.
- *
- * Revision 1.9  1998/01/27 18:37:04  curt
- * Lots of updates to get back in sync with changes made over in .../Src/
- *
- * Revision 1.8  1998/01/17 01:25:39  curt
- * Added support for shared normals.
- *
- * Revision 1.7  1998/01/12 02:42:00  curt
- * Average up to five triangles per vertex instead of three.
- *
- * Revision 1.6  1998/01/09 23:03:15  curt
- * Restructured to split 1deg x 1deg dem's into 64 subsections.
- *
- * Revision 1.5  1997/12/08 19:17:50  curt
- * Fixed a type in the normal generation code.
- *
- * Revision 1.4  1997/12/02 13:13:32  curt
- * Fixed problem with averaged vertex normals.
- *
- * Revision 1.3  1997/11/15 18:05:05  curt
- * minor tweaks ...
- *
- * Revision 1.2  1997/11/14 00:29:13  curt
- * Transform scenery coordinates at this point in pipeline when scenery is
- * being translated to .obj format, not when it is being loaded into the end
- * renderer.  Precalculate normals for each node as average of the normals
- * of each containing polygon so Garoude shading is now supportable.
- *
- * Revision 1.1  1997/10/29 23:05:15  curt
- * Initial revision.
- *
- */
+// $Log$
+// Revision 1.3  1998/10/19 19:33:31  curt
+// C++-ification.
+//
+// Revision 1.2  1998/10/18 01:17:29  curt
+// Point3D tweaks.
+//
+// Revision 1.1  1998/07/08 14:54:53  curt
+// renamed *.[ch] to *.[ch]xx
+//
+// Revision 1.17  1998/07/04 00:56:40  curt
+// typedef'd struct fgBUCKET.
+//
+// Revision 1.16  1998/05/23 15:20:41  curt
+// Output more digits after the decimal place.
+//
+// Revision 1.15  1998/05/02 01:54:39  curt
+// Converting to polar3d.h routines.
+//
+// Revision 1.14  1998/04/18 04:01:32  curt
+// Now use libMath rather than having local copies of math routines.
+//
+// Revision 1.13  1998/04/14 02:26:11  curt
+// Code reorganizations.  Added a Lib/ directory for more general libraries.
+//
+// Revision 1.12  1998/04/08 23:22:18  curt
+// Adopted Gnu automake/autoconf system.
+//
+// Revision 1.11  1998/03/03 16:01:00  curt
+// More c++ compile tweaks.
+//
+// Revision 1.10  1998/01/31 00:41:27  curt
+// Made a few changes converting floats to doubles.
+//
+// Revision 1.9  1998/01/27 18:37:04  curt
+// Lots of updates to get back in sync with changes made over in .../Src/
+//
+// Revision 1.8  1998/01/17 01:25:39  curt
+// Added support for shared normals.
+//
+// Revision 1.7  1998/01/12 02:42:00  curt
+// Average up to five triangles per vertex instead of three.
+//
+// Revision 1.6  1998/01/09 23:03:15  curt
+// Restructured to split 1deg x 1deg dem's into 64 subsections.
+//
+// Revision 1.5  1997/12/08 19:17:50  curt
+// Fixed a type in the normal generation code.
+//
+// Revision 1.4  1997/12/02 13:13:32  curt
+// Fixed problem with averaged vertex normals.
+//
+// Revision 1.3  1997/11/15 18:05:05  curt
+// minor tweaks ...
+//
+// Revision 1.2  1997/11/14 00:29:13  curt
+// Transform scenery coordinates at this point in pipeline when scenery is
+// being translated to .obj format, not when it is being loaded into the end
+// renderer.  Precalculate normals for each node as average of the normals
+// of each containing polygon so Garoude shading is now supportable.
+//
+// Revision 1.1  1997/10/29 23:05:15  curt
+// Initial revision.
+//
+

From 048130a991cf2daacf79329cb69d21ee22e96f13 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 20 Oct 1998 15:49:22 +0000
Subject: [PATCH 159/283] Converted to Point3D class.

---
 FixNode/fixnode.cxx | 24 ++++++++++++++++--------
 FixNode/fixnode.hxx | 17 ++++++++++++++---
 2 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/FixNode/fixnode.cxx b/FixNode/fixnode.cxx
index f8819e30c..183833d4d 100644
--- a/FixNode/fixnode.cxx
+++ b/FixNode/fixnode.cxx
@@ -3,7 +3,7 @@
 //
 // Written by Curtis Olson, started November 1997.
 //
-// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
+// Copyright (C) 1997  Curtis L. Olson  - curt@me.umn.edu
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -36,16 +36,20 @@
 #include <Misc/fgstream.hxx>
 
 #include "fixnode.hxx"
-// #include "triload.hxx"
+
+
+// load extra nodes
+void load_extra(const string& filename, container& extra_list) {
+}
 
 
 // load the node information
 void load_nodes(const string& filename, container& node_list) {
-    fgPoint3d node;
+    Point3D node;
     int dim, junk1, junk2;
     int i, nodecount;
 
-    cout << "Loading node file:  " + filename + " ...\n";
+    cout << "Loading node file:  " << filename << " ...\n";
 
     fg_gzifstream in( filename );
     if ( !in ) {
@@ -64,7 +68,7 @@ void load_nodes(const string& filename, container& node_list) {
 
     in.eat_comments();
     while ( ! in.eof() ) {
-	in.stream() >> junk1 >> node.x >> node.y >> node.z >> junk2;
+	in.stream() >> junk1 >> node >> junk2;
 	in.eat_comments();
 	node_list.push_back(node);
     }
@@ -86,8 +90,9 @@ void fix_nodes( const string& filename, fgDEM& dem, container& node_list )
 	// printf("Current: %d %.2f %.2f %.2f\n", i, nodes[i][0],
 	//        nodes[i][1], nodes[i][2]);
 
-	(*current).z = 
-	    dem.interpolate_altitude( (*current).x, (*current).y );
+	(*current).setz( 
+			dem.interpolate_altitude( (*current).x(), 
+						  (*current).y() ) );
 
 	// printf("Fixed: %d %.2f %.2f %.2f\n", i, nodes[i][0],
 	//        nodes[i][1], nodes[i][2]);
@@ -107,7 +112,7 @@ void fix_nodes( const string& filename, fgDEM& dem, container& node_list )
     i = 1;
     for ( current = node_list.begin() ; current != last ; ++current ) {
 	fprintf( fd, "%d %.2f %.2f %.2f 0\n", i,
-		 (*current).x, (*current).y, (*current).z );
+		 (*current).x(), (*current).y(), (*current).z() );
 	++i;
     }
 
@@ -116,6 +121,9 @@ void fix_nodes( const string& filename, fgDEM& dem, container& node_list )
 
 
 // $Log$
+// Revision 1.6  1998/10/20 15:49:22  curt
+// Converted to Point3D class.
+//
 // Revision 1.5  1998/09/22 23:49:10  curt
 // eliminated a left over #include
 //
diff --git a/FixNode/fixnode.hxx b/FixNode/fixnode.hxx
index 0bcc9b2c3..80b6eb2b6 100644
--- a/FixNode/fixnode.hxx
+++ b/FixNode/fixnode.hxx
@@ -40,10 +40,10 @@ using namespace std;
 #endif
 
 #include <DEM/dem.hxx>
-#include <Include/fg_types.h>
+#include <Math/point3d.hxx>
 
 
-typedef vector < fgPoint3d > container;
+typedef vector < Point3D > container;
 typedef container::iterator iterator;
 typedef container::const_iterator const_iterator;
 
@@ -52,7 +52,15 @@ typedef container::const_iterator const_iterator;
 void load_nodes(const string& basename, container& node_list);
 
 
-// load the node information
+// load the extra nodes.  These are always the first n nodes of the
+// .node file.  (???  These will be tagged with a code indicating what
+// needs to be done with this node's elevation such as adjust to local
+// DEM elevation, or massage the local DEM points to match this
+// elevation point. ???)
+void load_extra_nodes(const string& filename, container& node_list);
+
+
+// fix the node elevations
 void fix_nodes( const string& basename, fgDEM& dem, container& node_list );
 
 
@@ -60,6 +68,9 @@ void fix_nodes( const string& basename, fgDEM& dem, container& node_list );
 
 
 // $Log$
+// Revision 1.4  1998/10/20 15:49:23  curt
+// Converted to Point3D class.
+//
 // Revision 1.3  1998/09/19 20:43:53  curt
 // C++-ified and STL-ified the code.  Combined triload.* and fixnode.* into
 // a single file.

From 477753ef945a56ac5b33a2d4e17398866bad30f0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 20 Oct 1998 15:49:54 +0000
Subject: [PATCH 160/283] tweak ...

---
 GenAirports/area.cxx | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/GenAirports/area.cxx b/GenAirports/area.cxx
index aeb104552..75d785377 100644
--- a/GenAirports/area.cxx
+++ b/GenAirports/area.cxx
@@ -125,9 +125,12 @@ gen_area(point2d origin, double angle, list < point2d > cart_list)
     current = rad_list.begin();
     last = rad_list.end();
     for ( ; current != last ; ++current ) {
-	current->theta -= angle;
-	while ( current->theta > FG_2PI ) {
-	    current->theta -= FG_2PI;
+        current->theta -= angle;
+        while ( current->theta > FG_2PI ) {
+            current->theta -= FG_2PI;
+	// (*current).theta -= angle;
+	// while ( (*current).theta > FG_2PI ) {
+	//     (*current).theta -= FG_2PI;
 	}
 	// printf("(%.2f, %.2f)\n", current->theta, current->dist);
     }
@@ -215,6 +218,9 @@ gen_runway_area( double lon, double lat, double heading,
 
 
 // $Log$
+// Revision 1.5  1998/10/20 15:49:54  curt
+// tweak ...
+//
 // Revision 1.4  1998/09/09 20:59:53  curt
 // Loop construct tweaks for STL usage.
 // Output airport file to be used to generate airport scenery on the fly

From 4daff42c25ae95708f4a76d336fdea1b0139a282 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 20 Oct 1998 15:50:16 +0000
Subject: [PATCH 161/283] comment reformat

---
 Makedir/makedir.cxx | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/Makedir/makedir.cxx b/Makedir/makedir.cxx
index 96563cf1a..24cee5dc8 100644
--- a/Makedir/makedir.cxx
+++ b/Makedir/makedir.cxx
@@ -11,8 +11,7 @@
 #include <Bucket/bucketutils.h>
 
 #ifdef __CYGWIN32__
-#  define MKDIR(a) mkdir(a,S_IRWXU)     // I am just guessing at this flag
-(NHV)
+#  define MKDIR(a) mkdir(a,S_IRWXU)     // I am just guessing at this flag (NHV)
 #endif // __CYGWIN32__
 
 #ifdef __CYGWIN32__

From 69ac8bd3a7a53398000e0d50c48d102b35b26083 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 20 Oct 1998 15:50:33 +0000
Subject: [PATCH 162/283] whitespace tweak.

---
 SplitTris/splittris.cxx | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/SplitTris/splittris.cxx b/SplitTris/splittris.cxx
index 5892aa467..41e94a75d 100644
--- a/SplitTris/splittris.cxx
+++ b/SplitTris/splittris.cxx
@@ -36,7 +36,6 @@
 
 #include <Include/fg_constants.h>
 #include <Bucket/bucketutils.h>
-
 #include <Math/fg_geodesy.hxx>
 #include <Math/mat3.h>
 #include <Math/point3d.hxx>
@@ -612,6 +611,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.5  1998/10/20 15:50:33  curt
+// whitespace tweak.
+//
 // Revision 1.4  1998/10/18 01:17:27  curt
 // Point3D tweaks.
 //

From 8f9a1bcb56c021de6ee31b99d9244a0fa3857af3 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 20 Oct 1998 15:52:46 +0000
Subject: [PATCH 163/283] Fixed a units conversion bug introduced when
 converting to Point3D class.

---
 Tri2obj/tri2obj.cxx | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Tri2obj/tri2obj.cxx b/Tri2obj/tri2obj.cxx
index 20ecb0b2b..2079c3d4d 100644
--- a/Tri2obj/tri2obj.cxx
+++ b/Tri2obj/tri2obj.cxx
@@ -32,7 +32,6 @@
 #include "tri2obj.hxx"
 
 #include <Include/fg_constants.h>
-#include <Include/fg_types.h>
 #include <Bucket/bucketutils.h>
 
 #include <Math/fg_geodesy.hxx>
@@ -442,7 +441,9 @@ void triload(char *basename, char *basepath) {
 	fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
 	       &n[0], &n[1], &n[2], &junk2);
 	// printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]);
-	p = Point3D(n[0], n[1], n[2]);
+	p = Point3D( n[0] * ARCSEC_TO_RAD,
+		     n[1] * ARCSEC_TO_RAD,
+		     n[2] );
 	nodes[i] = fgGeodToCart(p);
 	// printf("%d %.2f %.2f %.2f\n", 
 	//        junk1, nodes[i].x, nodes[i].y, nodes[i].z);
@@ -622,6 +623,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.4  1998/10/20 15:52:46  curt
+// Fixed a units conversion bug introduced when converting to Point3D class.
+//
 // Revision 1.3  1998/10/19 19:33:31  curt
 // C++-ification.
 //

From 71f2e4342cc429e0de6016aa7ed214da74d268c6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 21 Oct 1998 14:55:55 +0000
Subject: [PATCH 164/283] Converted to Point3D class.

---
 FixObj/obj.cxx | 253 ++++++++++++++++++++++++++-----------------------
 1 file changed, 136 insertions(+), 117 deletions(-)

diff --git a/FixObj/obj.cxx b/FixObj/obj.cxx
index 25690d5b4..571a71058 100644
--- a/FixObj/obj.cxx
+++ b/FixObj/obj.cxx
@@ -23,20 +23,32 @@
 
 
 #include <stdio.h>
+#include <iostream>
 #include <string.h>
 
+#include <vector>
+#include "Include/compiler.h"
+
+#ifdef NEEDNAMESPACESTD
+using namespace std;
+#endif
+
 #include "obj.hxx"
 
 #include <Math/mat3.h>
+#include <Math/point3d.hxx>
 
 
+typedef vector < Point3D > container3;
+typedef container3::iterator iterator3;
+typedef container3::const_iterator const_iterator3;
 
 
 // what do ya' know, here's some global variables
-static double nodes[MAXNODES][3];
-static double normals[MAXNODES][3];
+container3 nodes;
+container3 normals;
 static int faces[MAXNODES][3];
-int ncount, vncount, fcount;
+int vncount, fcount;
 
 static int ccw_list[MAXNODES];
 int ccw_list_ptr;
@@ -46,7 +58,7 @@ int cw_list_ptr;
 
 FILE *in, *out;
 
-double refx, refy, refz;
+Point3D ref;
 
 
 // some simple list routines
@@ -131,66 +143,78 @@ void fix_cw_list(int *list, int list_ptr) {
 }
 
 
-// Calculate distance between (0,0,0) and the specified point
-static double calc_dist(double x, double y, double z) {
-    return ( sqrt(x*x + y*y + z*z) );
-}
-
-
 void dump_global_bounds( void ) {
     double dist, radius;
-    int i;
 
     radius = 0.0;
 
     fprintf(out, "\n");
 
-    for ( i = 1; i < ncount; i++ ) {
+    
+    iterator3 current = nodes.begin();
+    iterator3 last = nodes.end();
 
-	dist = calc_dist(nodes[i][0] - refx, nodes[i][1] - refy, 
-			 nodes[i][2] - refz);
-	// printf("node = %.2f %.2f %.2f dist = %.2f\n", 
-        //        nodes[i][0], nodes[i][1], nodes[i][2],
-	//        dist);
+    // skip first dummy node
+    ++current;
+
+    for ( ; current != last; ++current ) {
+	dist = ref.distance3D(*current);
+	// cout << "node = " << *current << " dist = " << dist << endl;
 
 	if ( dist > radius ) {
 	    radius = dist;
 	}
-
     }
 
-    fprintf(out, "gbs %.5f %.5f %.5f %.2f\n", refx, refy, refz, radius);
+    fprintf( out, 
+	     "gbs %.5f %.5f %.5f %.2f\n", 
+	     ref.x(), ref.y(), ref.z(), radius);
 }
 
 
 // dump nodes
 void dump_nodes( void ) {
-    int i;
+    Point3D p;
 
     fprintf(out, "\n");
-    for ( i = 1; i < ncount; i++ ) {
-	fprintf(out, "v %.5f %.5f %.5f\n",
-		nodes[i][0] - refx, nodes[i][1] - refy, nodes[i][2] - refz);
+
+    iterator3 current = nodes.begin();
+    iterator3 last = nodes.end();
+
+    // skip first dummy node
+    ++current;
+
+    for ( ; current != last; ++current ) {
+	p = *current - ref;
+	fprintf( out, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
     }
 }
 
 
 // dump normals
 void dump_normals( void ) {
-    int i;
+    Point3D p;
 
     fprintf(out, "\n");
-    for ( i = 1; i < vncount; i++ ) {
-	fprintf(out, "vn %.5f %.5f %.5f\n", 
-		normals[i][0], normals[i][1], normals[i][2]);
+
+    iterator3 current = normals.begin();
+    iterator3 last = normals.end();
+
+    // skip first dummy normal
+    ++current;
+
+    for ( ; current != last; ++current ) {
+	p = *current;
+	fprintf(out, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
     }
 }
 
 
 // dump faces
 void dump_faces( void ) {
+    Point3D p;
     int i, n1, n2, n3;
-    double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
+    double xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
 
     fprintf(out, "\n");
     for ( i = 1; i < fcount; i++ ) {
@@ -199,40 +223,39 @@ void dump_faces( void ) {
 	n3 = faces[i][2];
 
 	// calc center of face
-	xmin = xmax = nodes[n1][0];
-	ymin = ymax = nodes[n1][1];
-	zmin = zmax = nodes[n1][2];
+	xmin = xmax = nodes[n1].x();
+	ymin = ymax = nodes[n1].y();
+	zmin = zmax = nodes[n1].z();
 
-	if ( nodes[n2][0] < xmin ) { xmin = nodes[n2][0]; }
-	if ( nodes[n2][0] > xmax ) { xmax = nodes[n2][0]; }
-	if ( nodes[n2][1] < ymin ) { ymin = nodes[n2][1]; }
-	if ( nodes[n2][1] > ymax ) { ymax = nodes[n2][1]; }
-	if ( nodes[n2][2] < zmin ) { zmin = nodes[n2][2]; }
-	if ( nodes[n2][2] > zmax ) { zmax = nodes[n2][2]; }
+	if ( nodes[n2].x() < xmin ) { xmin = nodes[n2].x(); }
+	if ( nodes[n2].x() > xmax ) { xmax = nodes[n2].x(); }
+	if ( nodes[n2].y() < ymin ) { ymin = nodes[n2].y(); }
+	if ( nodes[n2].y() > ymax ) { ymax = nodes[n2].y(); }
+	if ( nodes[n2].z() < zmin ) { zmin = nodes[n2].z(); }
+	if ( nodes[n2].z() > zmax ) { zmax = nodes[n2].z(); }
 
-	if ( nodes[n3][0] < xmin ) { xmin = nodes[n3][0]; }
-	if ( nodes[n3][0] > xmax ) { xmax = nodes[n3][0]; }
-	if ( nodes[n3][1] < ymin ) { ymin = nodes[n3][1]; }
-	if ( nodes[n3][1] > ymax ) { ymax = nodes[n3][1]; }
-	if ( nodes[n3][2] < zmin ) { zmin = nodes[n3][2]; }
-	if ( nodes[n3][2] > zmax ) { zmax = nodes[n3][2]; }
+	if ( nodes[n3].x() < xmin ) { xmin = nodes[n3].x(); }
+	if ( nodes[n3].x() > xmax ) { xmax = nodes[n3].x(); }
+	if ( nodes[n3].y() < ymin ) { ymin = nodes[n3].y(); }
+	if ( nodes[n3].y() > ymax ) { ymax = nodes[n3].y(); }
+	if ( nodes[n3].z() < zmin ) { zmin = nodes[n3].z(); }
+	if ( nodes[n3].z() > zmax ) { zmax = nodes[n3].z(); }
 
-	x = (xmin + xmax) / 2.0;
-	y = (ymin + ymax) / 2.0;
-	z = (zmin + zmax) / 2.0;
+	p = Point3D( (xmin + xmax) / 2.0,
+		     (ymin + ymax) / 2.0,
+		     (zmin + zmax) / 2.0 );
 
 	// calc bounding radius
-	radius = calc_dist(nodes[n1][0] - x, nodes[n1][1] - y, 
-			   nodes[n1][2] - z);
+	radius = p.distance3D(nodes[n1]);
 
-	dist = calc_dist(nodes[n2][0] - x, nodes[n2][1] - y, nodes[n2][2] - z);
+	dist = p.distance3D(nodes[n2]);
 	if ( dist > radius ) { radius = dist; }
 
-	dist = calc_dist(nodes[n3][0] - x, nodes[n3][1] - y, nodes[n3][2] - z);
+	dist = p.distance3D(nodes[n3]);
 	if ( dist > radius ) { radius = dist; }
 	
 	// output data
-	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", x, y, z, radius);
+	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", p.x(), p.y(), p.z(), radius);
 	fprintf(out, "f %d %d %d\n", n1, n2, n3);
     }
 }
@@ -240,7 +263,8 @@ void dump_faces( void ) {
 
 // dump list
 void dump_list(int *list, int list_ptr) {
-    double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
+    Point3D p;
+    double xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
     int i, j, len, n;
 
     if ( list_ptr < 3 ) {
@@ -271,41 +295,40 @@ void dump_list(int *list, int list_ptr) {
 
 	// calc center of face
 	n = list[i];
-	xmin = xmax = nodes[n][0];
-	ymin = ymax = nodes[n][1];
-	zmin = zmax = nodes[n][2];
-	// printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
+	xmin = xmax = nodes[n].x();
+	ymin = ymax = nodes[n].y();
+	zmin = zmax = nodes[n].z();
+	// printf("%.2f %.2f %.2f\n", nodes[n].x(), nodes[n].y(), nodes[n].z());
 
 	for ( j = i + 1; j < i + len; j++ ) {
 	    // printf("j = %d\n", j);
 	    n = list[j];
-	    if ( nodes[n][0] < xmin ) { xmin = nodes[n][0]; }
-	    if ( nodes[n][0] > xmax ) { xmax = nodes[n][0]; }
-	    if ( nodes[n][1] < ymin ) { ymin = nodes[n][1]; }
-	    if ( nodes[n][1] > ymax ) { ymax = nodes[n][1]; }
-	    if ( nodes[n][2] < zmin ) { zmin = nodes[n][2]; }
-	    if ( nodes[n][2] > zmax ) { zmax = nodes[n][2]; }
-	    // printf("%.2f %.2f %.2f\n", nodes[n][0], nodes[n][1], nodes[n][2]);
-	}	    
-	x = (xmin + xmax) / 2.0;
-	y = (ymin + ymax) / 2.0;
-	z = (zmin + zmax) / 2.0;
-	// printf("center = %.2f %.2f %.2f\n", x, y, z);
+	    if ( nodes[n].x() < xmin ) { xmin = nodes[n].x(); }
+	    if ( nodes[n].x() > xmax ) { xmax = nodes[n].x(); }
+	    if ( nodes[n].y() < ymin ) { ymin = nodes[n].y(); }
+	    if ( nodes[n].y() > ymax ) { ymax = nodes[n].y(); }
+	    if ( nodes[n].z() < zmin ) { zmin = nodes[n].z(); }
+	    if ( nodes[n].z() > zmax ) { zmax = nodes[n].z(); }
+	    // printf("%.2f %.2f %.2f\n", nodes[n].x(), nodes[n].y(), nodes[n].z());
+	}
+	p = Point3D( (xmin + xmax) / 2.0,
+		     (ymin + ymax) / 2.0,
+		     (zmin + zmax) / 2.0 );
+	// printf("center = %.2f %.2f %.2f\n", p.x(), p.y(), p.z());
 
 	// calc bounding radius
 	n = list[i];
-	radius = calc_dist(nodes[n][0] - x, nodes[n][1] - y, nodes[n][2] - z);
+	radius = p.distance3D(nodes[n]);
 
 	for ( j = i + 1; j < i + len; j++ ) {
 	    n = list[j];
-	    dist = calc_dist(nodes[n][0] - x, nodes[n][1] - y, 
-			     nodes[n][2] - z);
+	    dist = p.distance3D(nodes[n]);
 	    if ( dist > radius ) { radius = dist; }
 	}
 	// printf("radius = %.2f\n", radius);
 
 	// dump bounding sphere and header
-	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", x, y, z, radius);
+	fprintf(out, "bs %.2f %.2f %.2f %.2f\n", p.x(), p.y(), p.z(), radius);
 	fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]);
 	// printf("t %d %d %d\n", list[i], list[i+1], list[i+2]);
 	i += 3;
@@ -335,12 +358,12 @@ double check_cur_face(int n1, int n2, int n3) {
 
     // check for the proper rotation by calculating an approximate
     // normal and seeing if it is close to the precalculated normal
-    v1[0] = nodes[n2][0] - nodes[n1][0];
-    v1[1] = nodes[n2][1] - nodes[n1][1];
-    v1[2] = nodes[n2][2] - nodes[n1][2];
-    v2[0] = nodes[n3][0] - nodes[n1][0];
-    v2[1] = nodes[n3][1] - nodes[n1][1];
-    v2[2] = nodes[n3][2] - nodes[n1][2];
+    v1[0] = nodes[n2].x() - nodes[n1].x();
+    v1[1] = nodes[n2].y() - nodes[n1].y();
+    v1[2] = nodes[n2].z() - nodes[n1].z();
+    v2[0] = nodes[n3].x() - nodes[n1].x();
+    v2[1] = nodes[n3].y() - nodes[n1].y();
+    v2[2] = nodes[n3].z() - nodes[n1].z();
 
     MAT3cross_product(approx_normal, v1, v2);
     MAT3_NORMALIZE_VEC(approx_normal,temp);
@@ -362,6 +385,7 @@ double check_cur_face(int n1, int n2, int n3) {
 
 // Load a .obj file
 void obj_fix(char *infile, char *outfile) {
+    Point3D node, normal;
     char line[256];
     double dot_prod;
     int first, n1, n2, n3, n4;
@@ -378,13 +402,20 @@ void obj_fix(char *infile, char *outfile) {
 	exit(-1);
     }
 
+    // push dummy records onto the lists since we start counting with "1"
+    node = Point3D(0.0, 0.0, 0.0);
+    nodes.push_back(node);
+
+    normal = Point3D(0.0, 0.0, 0.0);
+    normals.push_back(normal);
+
+    // initialize other lists
     list_init(&ccw_list_ptr);
     list_init(&cw_list_ptr);
 
     // I start counting at one because that is how the triangle
     // program refers to nodes and normals
     first = 1;
-    ncount = 1;
     vncount = 1;
     fcount = 1;
 
@@ -399,52 +430,37 @@ void obj_fix(char *infile, char *outfile) {
 	    // fprintf(out, "%s", line);
 	} else if ( strncmp(line, "v ", 2) == 0 ) {
 	    // save vertex to memory and output to file
-            if ( ncount < MAXNODES ) {
-                // printf("vertex = %s", line);
-                sscanf(line, "v %lf %lf %lf\n", &x, &y, &z);
-		nodes[ncount][0] = x;
-		nodes[ncount][1] = y;
-		nodes[ncount][2] = z;
+	    // printf("vertex = %s", line);
+	    sscanf(line, "v %lf %lf %lf\n", &x, &y, &z);
 
+	    if ( nodes.size() == 1 ) {
 		// first time through set min's and max'es
-		if ( ncount == 1 ) {
-		    xmin = x;
-		    xmax = x;
-		    ymin = y;
-		    ymax = y;
-		    zmin = z;
-		    zmax = z;
-		}
-    
-		// keep track of min/max vertex values
+		xmin = x;
+		xmax = x;
+		ymin = y;
+		ymax = y;
+		zmin = z;
+		zmax = z;
+	    } else {
+		// update min/max vertex values
 		if ( x < xmin ) xmin = x;
 		if ( x > xmax ) xmax = x;
 		if ( y < ymin ) ymin = y;
 		if ( y > ymax ) ymax = y;
 		if ( z < zmin ) zmin = z;
 		if ( z > zmax ) zmax = z;		
+	    }
 
-		// fprintf(out, "v %.2f %.2f %.2f\n", 
-		//       nodes[ncount][0], nodes[ncount][1], nodes[ncount][2]);
-		ncount++;
-            } else {
-                printf("Read too many nodes ... dying :-(\n");
-                exit(-1);
-            }
+	    node = Point3D(x, y, z);
+	    nodes.push_back(node);
+	    // fprintf(out, "v %.2f %.2f %.2f\n", 
+	    //       node.x(), node.y(), node.z());
 	} else if ( strncmp(line, "vn ", 3) == 0 ) {
 	    // save vertex normals to memory and output to file
-            if ( vncount < MAXNODES ) {
-                // printf("vertex normal = %s", line);
-                sscanf(line, "vn %lf %lf %lf\n", 
-                       &normals[vncount][0], &normals[vncount][1], 
-                       &normals[vncount][2]);
-		// fprintf(out, "vn %.4f %.4f %.4f\n", normals[vncount][0], 
-		//	normals[vncount][1], normals[vncount][2]);
-                vncount++;
-            } else {
-                printf("Read too many vertex normals ... dying :-(\n");
-                exit(-1);
-            }
+	    // printf("vertex normal = %s", line);
+	    sscanf(line, "vn %lf %lf %lf\n", &x, &y, &z);
+	    normal = Point3D(x, y, z);
+	    normals.push_back(normal);
 	} else if ( line[0] == 't' ) {
 	    // starting a new triangle strip
 
@@ -539,9 +555,9 @@ void obj_fix(char *infile, char *outfile) {
     }
 
     // reference point is the "center"
-    refx = (xmin + xmax) / 2.0;
-    refy = (ymin + ymax) / 2.0;
-    refz = (zmin + zmax) / 2.0;
+    ref = Point3D( (xmin + xmax) / 2.0,
+		   (ymin + ymax) / 2.0,
+		   (zmin + zmax) / 2.0 );
 
     // convert the cw_list to ccw add append to ccw_list
     fix_cw_list(cw_list, cw_list_ptr);
@@ -561,6 +577,9 @@ void obj_fix(char *infile, char *outfile) {
 
 
 // $Log$
+// Revision 1.2  1998/10/21 14:55:55  curt
+// Converted to Point3D class.
+//
 // Revision 1.1  1998/06/08 17:11:46  curt
 // Renamed *.[ch] to *.[ch]xx
 //

From e12ef6b4509c74db54b51bdb70e13feef91138b0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 21 Oct 1998 14:56:20 +0000
Subject: [PATCH 165/283] Fixed a units conversion bug.

---
 SplitTris/splittris.cxx | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/SplitTris/splittris.cxx b/SplitTris/splittris.cxx
index 41e94a75d..e4247715e 100644
--- a/SplitTris/splittris.cxx
+++ b/SplitTris/splittris.cxx
@@ -133,7 +133,7 @@ void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
 // Initialize a new mesh structure
 void triload(const string& basename) {
     string nodename, elename;
-    Point3D node1, node2;
+    Point3D node1, node2, p;
     triangle tri;
     int nodecount, tricount, dim, junk1, junk2;
     int i;
@@ -163,8 +163,13 @@ void triload(const string& basename) {
 	node_in.stream() >> junk1 >> node1 >> junk2;
 	nodes_orig.push_back(node1);
 	// printf("%d %.2f %.2f %.2f\n", junk1, node1.x, node1.y, node1.z);
+	
+	// convert to radians (before we can convert to cartesian)
+	p = Point3D( node1.x() * ARCSEC_TO_RAD,
+	             node1.y() * ARCSEC_TO_RAD,
+		     node1.z() );
 
-	node2 = fgGeodToCart(node1);
+	node2 = fgGeodToCart(p);
 	nodes_cart.push_back(node2);
 	// printf("%d %.2f %.2f %.2f\n", junk1, node2.x, node2.y, node2.z);
 
@@ -611,6 +616,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.6  1998/10/21 14:56:20  curt
+// Fixed a units conversion bug.
+//
 // Revision 1.5  1998/10/20 15:50:33  curt
 // whitespace tweak.
 //

From d4e18d0acc29f0f49d655a0bc0723b8d7a4f3414 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 21 Oct 1998 14:56:50 +0000
Subject: [PATCH 166/283] Minor parameter passing tweak.

---
 Tri2obj/tri2obj.cxx | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Tri2obj/tri2obj.cxx b/Tri2obj/tri2obj.cxx
index 2079c3d4d..a3401052c 100644
--- a/Tri2obj/tri2obj.cxx
+++ b/Tri2obj/tri2obj.cxx
@@ -52,8 +52,8 @@ fgBUCKET north_index, south_index, east_index, west_index;
 
 
 // given three points defining a triangle, calculate the normal
-void calc_normal(Point3D p1, Point3D p2, 
-		 Point3D p3, double normal[3])
+void calc_normal(const Point3D& p1, const Point3D& p2, 
+		 const Point3D& p3, double normal[3])
 {
     double v1[3], v2[3];
     double temp;
@@ -623,6 +623,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.5  1998/10/21 14:56:50  curt
+// Minor parameter passing tweak.
+//
 // Revision 1.4  1998/10/20 15:52:46  curt
 // Fixed a units conversion bug introduced when converting to Point3D class.
 //

From 3468bef4bbd1d86b95d3f1198fa729380e664106 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 22 Oct 1998 21:59:19 +0000
Subject: [PATCH 167/283] Fixed a couple subtle bugs that resulted from some of
 my c++ conversions. One bug could cause a segfault on certain input, and the
 other bug could cause the whole procedure to go balistic and generate huge
 files (also only on rare input combinations.)

---
 DEM/dem.cxx | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index fbadcecda..3a20abea9 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -265,7 +265,7 @@ int fgDEM::read_a_record() {
 
     // Map projection parameters (ignored)
     for ( i = 0; i < 15; i++ ) {
-	dnum = next_double();
+	dnum = next_exp();
 	// printf("%d: %f\n",i,dnum);
     }
 
@@ -331,9 +331,9 @@ int fgDEM::read_a_record() {
     cout << "    length = " << i << "\n";
 
 #if 1
-    inum = atoi( token.substr( 0, 1 ) );
-    row_step = atof( token.substr( 1, 12 ) );
-    col_step = atof( token.substr( 13, 12 ) );
+    inum = atoi( token.substr( 0, i - 36 ) );
+    row_step = atof( token.substr( i - 36, 12 ) );
+    col_step = atof( token.substr( i - 24, 12 ) );
     //token.substr( 25, 12 )
 #else
     ptr = token.c_str() + i - 12;
@@ -852,6 +852,12 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.19  1998/10/22 21:59:19  curt
+// Fixed a couple subtle bugs that resulted from some of my c++ conversions.
+// One bug could cause a segfault on certain input, and the other bug could
+// cause the whole procedure to go balistic and generate huge files (also only
+// on rare input combinations.)
+//
 // Revision 1.18  1998/10/18 01:17:09  curt
 // Point3D tweaks.
 //

From 7ef298dc2ef868b860922a9f66de8c206efa35f3 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 22 Oct 1998 22:00:10 +0000
Subject: [PATCH 168/283] Modified the info that is put in the VERSION file.

---
 Tools/process-dem.pl | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 5751ec498..954b73ac2 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -467,7 +467,11 @@ sub install {
 	die "Cannot open $install_dir/VERSION for writing\n";
     print VERSION "FGFS Scenery Version $scenery_format_version\n";
     $date = `date`; chop($date);
-    print VERSION "Created by $ENV{LOGNAME} on $date\n";
+    $hostname = `hostname`; chop($hostname);
+    print VERSION "Creator = $ENV{LOGNAME}\n";
+    print VERSION "Date = $date\n";
+    print VERSION "Machine = $hostname\n";
+    print VERSION "
     print VERSION "\n";
     print VERSION "DEM File Name = $dem_file\n";
     print VERSION "DEM Label = $quad_name\n";
@@ -511,6 +515,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.30  1998/10/22 22:00:10  curt
+# Modified the info that is put in the VERSION file.
+#
 # Revision 1.29  1998/10/02 21:41:56  curt
 # Added Makedir + fixes for win32.
 #

From 914bbba3ef13ad1476b72c3ac97e9774a4668299 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 28 Oct 1998 19:38:20 +0000
Subject: [PATCH 169/283] Elliminate some unnecessary win32 specific stuff (by
 Norman Vine)

---
 DEM/dem.cxx | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 3a20abea9..d04bc3917 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -54,6 +54,7 @@ FG_USING_NAMESPACE(std);
 
 #define MAX_EX_NODES 10000
 
+#if 0
 #ifdef WIN32
 # ifdef __BORLANDC__
 #  include <dir.h>
@@ -62,6 +63,7 @@ FG_USING_NAMESPACE(std);
 #  define MKDIR(a) mkdir(a,S_IRWXU)  // I am just guessing at this flag (NHV)
 # endif // __BORLANDC__
 #endif // WIN32
+#endif //0
 
 
 fgDEM::fgDEM( void ) {
@@ -71,6 +73,7 @@ fgDEM::fgDEM( void ) {
 }
 
 
+#if 0
 #ifdef WIN32
 
 // return the file path name ( foo/bar/file.ext = foo/bar )
@@ -114,6 +117,7 @@ static int my_mkdir (const char *dir) {
 }
 
 #endif // WIN32
+#endif //0
 
 
 // open a DEM file
@@ -746,12 +750,13 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
     if ( result != 0 && errno == ENOENT ) {
 	cout << "Creating directory\n";
 
-#ifndef WIN32
+// #ifndef WIN32
 
 	command = "mkdir -p " + dir + "\n";
 	system( command.c_str() );
 
-#else // WIN32
+#if 0
+// #else // WIN32
 
 	// Cygwin crashes when trying to output to node file
 	// explicitly making directory structure seems OK on Win95
@@ -767,7 +772,8 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
 	dir = fg_root + "/Scenery/" + base_path;
 	if (my_mkdir ( dir.c_str() )) { exit (-1); }
 
-#endif // WIN32
+// #endif // WIN32
+#endif //0
 
     } else {
 	// assume directory exists
@@ -852,6 +858,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.20  1998/10/28 19:38:20  curt
+// Elliminate some unnecessary win32 specific stuff (by Norman Vine)
+//
 // Revision 1.19  1998/10/22 21:59:19  curt
 // Fixed a couple subtle bugs that resulted from some of my c++ conversions.
 // One bug could cause a segfault on certain input, and the other bug could

From 033491ac3164ece3c00123054ed12a56c7def39f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 28 Oct 1998 19:39:06 +0000
Subject: [PATCH 170/283] Changes to better support win32 scenery development.

---
 Tools/process-dem.pl | 121 ++++++++++++++++++++++++++++---------------
 1 file changed, 80 insertions(+), 41 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 954b73ac2..21bee54a8 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -91,9 +91,9 @@ while ( $dem_file = shift(@ARGV) ) {
 exit(0);
 
 
-# fix command to work with windoze, replaces first "/" with "\\"
-sub fix_command {
-    my($in) = @_;
+# replace all unix forward slashes with windoze backwards slashes if
+# running on a cygwin32 system
+sub fix_slashes { my($in) = @_;
 
     $system = `uname -s`;
     chop($system);
@@ -126,7 +126,7 @@ sub file_root {
 
 sub dem2node {
     $command = "Dem2node/dem2node $work_dir $dem_file $error";
-    $command = fix_command($command);
+    $command = fix_slashes($command);
     print "Running '$command'\n";
 
     open(OUT, "$command |");
@@ -167,11 +167,11 @@ sub triangle_1 {
 	    $fileroot =~ s/\.node$//;
 	    print "$subdir/$fileroot\n";
 	    $command = "Triangle/triangle";
+	    $command = fix_slashes($command);
 	    if ( -r "$subdir/$fileroot.poly" ) {
 		$command .= " -pc";
 	    }
 	    $command .= " -a$max_area -q10 $subdir/$file";
-	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -181,7 +181,9 @@ sub triangle_1 {
 
 	    # remove input file.node
 	    if ( $remove_tmps ) {
-		unlink("$subdir/$file");
+		$file1 = "$subdir/$file";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
 	    }
 	}
     }
@@ -195,8 +197,9 @@ sub triangle_1 {
 #     fixed file.1.node
 
 sub fixnode {
-    $command = "FixNode/fixnode $dem_file $subdir";
-    $command = fix_command($command);
+    $command = "FixNode/fixnode";
+    $command = fix_slashes($command);
+    $command .= " $dem_file $subdir";
     print "Running '$command'\n";
     open(OUT, "$command |") || die "cannot run command\n";
     while ( <OUT> ) {
@@ -228,8 +231,9 @@ sub splittris {
 	if ( $file =~ m/\.1\.node$/ ) {
 	    $file =~ s/\.node$//;  # strip off the ".node"
 	
-	    $command = "SplitTris/splittris $subdir/$file";
-	    $command = fix_command($command);
+	    $command = "SplitTris/splittris";
+	    $command = fix_slashes($command);
+	    $command .= " $subdir/$file";
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -238,9 +242,15 @@ sub splittris {
 	    close(OUT);
 
 	    if ( $remove_tmps ) {
-		unlink("$subdir/$file.node");
-		unlink("$subdir/$file.node.orig");
-		unlink("$subdir/$file.ele");
+		$file1 = "$subdir/$file.node";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
+		$file1 = "$subdir/$file.node.orig";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
+		$file1 = "$subdir/$file.ele";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
 	    }
 	}
     }
@@ -258,8 +268,9 @@ sub assemtris {
 	if ( $file =~ m/\.1\.body$/ ) {
 	    $file =~ s/\.1\.body$//;  # strip off the ".body"
 	
-	    $command = "AssemTris/assemtris $subdir/$file";
-	    $command = fix_command($command);
+	    $command = "AssemTris/assemtris";
+	    $command = fix_slashes($command);
+	    $command .= " $subdir/$file";
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -268,7 +279,9 @@ sub assemtris {
 	    close(OUT);
 	}
 	if ( $remove_tmps ) {
-	    unlink("$subdir/$file.body");
+	    $file1 = "$subdir/$file.body";
+	    $file1 = fix_slashes($file1);
+	    unlink($file1);
 	}
     }
 }
@@ -288,6 +301,7 @@ sub triangle_2 {
 	    print("Test for $subdir/$base.q\n");
 
 	    $command = "Triangle/triangle";
+	    $command = fix_slashes($command);
 
 	    if ( -r "$subdir/$base.q" ) {
 		# if triangle hangs, we can create a filebase.q for
@@ -303,7 +317,6 @@ sub triangle_2 {
 		$command .= " $subdir/$file";
 	    }
 
-	    $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -313,7 +326,9 @@ sub triangle_2 {
 
 	    # remove input file.node
 	    if ( $remove_tmps ) {
-		unlink("$subdir/$file");
+		$file1 = "$subdir/$file";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
 	    }
 	}
     }
@@ -337,8 +352,9 @@ sub tri2obj {
 	if ( $file =~ m/\.1\.node$/ ) {
 	    $file =~ s/\.node$//;  # strip off the ".node"
 	    
-	    $command = "Tri2obj/tri2obj $subdir/$file";
-	    $command = fix_command($command);
+	    $command = "Tri2obj/tri2obj";
+	    $command = fix_slashes($command);
+	    $command .= " $subdir/$file";
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -347,9 +363,15 @@ sub tri2obj {
 	    close(OUT);
 	    
 	    if ( $remove_tmps ) {
-		unlink("$subdir/$file.node");
-		unlink("$subdir/$file.node.orig");
-		unlink("$subdir/$file.ele");
+		$file1 = "$subdir/$file.node";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
+		$file1 = "$subdir/$file.node.orig";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
+		$file1 = "$subdir/$file.ele";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
 	    }
 	}
     }
@@ -372,8 +394,9 @@ sub strips {
 	if ( $file =~ m/\.1\.obj$/ ) {
 	    $newfile = $file;
 	    $newfile =~ s/\.1\.obj$//;
-	    $command = "Stripe_w/strips $subdir/$file $subdir/$newfile.2.obj";
-	    $command = fix_command($command);
+	    $command = "Stripe_w/strips";
+	    $command = fix_slashes($command);
+	    $command .= " $subdir/$file $subdir/$newfile.2.obj";
 	    print "Running '$command'\n";
     	    # $input = <STDIN>;
 	    open(OUT, "$command |");
@@ -396,7 +419,9 @@ sub strips {
 	    # close(OUT);
 	    
 	    if ( $remove_tmps ) {
-		unlink("$subdir/$file");
+		$file1 = "$subdir/$file";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
 	    }
 	}
     }
@@ -415,8 +440,9 @@ sub fixobj {
 	    $newfile = $file;
 	    $newfile =~ s/\.2\.obj$/.obj/;
 	    
-	    $command = "FixObj/fixobj $subdir/$file $subdir/$newfile";
-	    $command = fix_command($command);
+	    $command = "FixObj/fixobj";
+	    $command = fix_slashes($command);
+	    $command .= " $subdir/$file $subdir/$newfile";
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -425,7 +451,9 @@ sub fixobj {
 	    close(OUT);
 
 	    if ( $remove_tmps ) {
-		unlink("$subdir/$file");
+		$file1 = "$subdir/$file";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
 	    }
 	}
     }
@@ -446,15 +474,17 @@ sub install {
     $install_dir =~ s/\/+/\//g;
     print "Install dir = $install_dir\n";
 
+    $system = `uname -s`;
+    chop($system);
+
     if ( $system !~ m/CYGWIN32/ ) {
 	$command = "mkdir -p $install_dir";
     } else {
         $command = "Makedir/makedir $install_dir";
-	$command = fix_command($command);
+	$command = fix_slashes($command);
     }
 
-    # system($command);
-
+    # print "Running '$command'\n";
     open(OUT, "$command |");
     while ( <OUT> ) {
 	print $_;
@@ -463,15 +493,20 @@ sub install {
 
 
     # write out version and info record
-    open(VERSION, ">$install_dir/VERSION") || 
-	die "Cannot open $install_dir/VERSION for writing\n";
+    $version_file = "$install_dir/VERSION";
+    open(VERSION, ">$version_file") || 
+	die "Cannot open $version_file for writing\n";
     print VERSION "FGFS Scenery Version $scenery_format_version\n";
-    $date = `date`; chop($date);
+    if ( $system !~ m/CYGWIN32/ ) {
+	$date = `date`; chop($date);
+    } else {
+	# ???
+	$date = "not available";
+    }
     $hostname = `hostname`; chop($hostname);
     print VERSION "Creator = $ENV{LOGNAME}\n";
     print VERSION "Date = $date\n";
     print VERSION "Machine = $hostname\n";
-    print VERSION "
     print VERSION "\n";
     print VERSION "DEM File Name = $dem_file\n";
     print VERSION "DEM Label = $quad_name\n";
@@ -485,10 +520,9 @@ sub install {
 	    $new_file = file_root($file);
 	    
 	    $command = 
-		"gzip -v --best < $subdir/$file > $install_dir/$new_file.gz";
-	    $command = fix_command($command);
+		"gzip -c --best -v < $subdir/$file > $install_dir/$new_file.gz";
+	    $command = fix_slashes($command);
 
-	    # $command = fix_command($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -497,11 +531,13 @@ sub install {
 	    close(OUT);
 
 	    if ( $remove_tmps ) {
-		unlink("$subdir/$file");
+		$file1 = "$subdir/$file";
+		$file1 = fix_slashes($file1);
+		unlink($file1);
 	    }
 	} elsif ( $file =~ m/\d\d.apt$/ ) {
 	    $command = "cp $subdir/$file $install_dir/$file";
-	    # $command = fix_command($command);
+	    $command = fix_slashes($command);
 	    print "Running '$command'\n";
 	    open(OUT, "$command |");
 	    while ( <OUT> ) {
@@ -515,6 +551,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.31  1998/10/28 19:39:06  curt
+# Changes to better support win32 scenery development.
+#
 # Revision 1.30  1998/10/22 22:00:10  curt
 # Modified the info that is put in the VERSION file.
 #

From 17040e4b4dbffb51ff63b57ff0394de1882a2538 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 28 Oct 1998 19:39:33 +0000
Subject: [PATCH 171/283] Changes contributed by Norman Vine

---
 Makedir/makedir.cxx | 162 +++++++++++++++++++++-----------------------
 1 file changed, 77 insertions(+), 85 deletions(-)

diff --git a/Makedir/makedir.cxx b/Makedir/makedir.cxx
index 24cee5dc8..9ba9db610 100644
--- a/Makedir/makedir.cxx
+++ b/Makedir/makedir.cxx
@@ -1,8 +1,13 @@
-#include <ctype.h>    // isspace()
-#include <stdlib.h>   // atoi()
-#include <math.h>     // rint()
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
 #include <stdio.h>
-#include <string.h>
 #include <sys/stat.h> // stat()
 #include <unistd.h>   // stat()
 
@@ -10,98 +15,82 @@
 
 #include <Bucket/bucketutils.h>
 
-#ifdef __CYGWIN32__
-#  define MKDIR(a) mkdir(a,S_IRWXU)     // I am just guessing at this flag (NHV)
-#endif // __CYGWIN32__
-
-#ifdef __CYGWIN32__
-
-// return the file path name ( foo/bar/file.ext = foo/bar )
-static void extract_path (char *in, char *base) {
-    int len, i;
-
-    len = strlen (in);
-    strcpy (base, in);
-
-    i = len - 1;
-    while ( (i >= 0) && (in[i] != '/') ) {
-	i--;
-    }
-
-    base[i] = '\0';
-}
 
 
-// Make a subdirectory
-static int my_mkdir (char *dir) {
-    struct stat stat_buf;
-    int result;
-
-    printf ("mk_dir() ");
-
-    result = stat (dir, &stat_buf);
-
-    if (result != 0) {
-	MKDIR (dir);
-	result = stat (dir, &stat_buf);
-	if (result != 0) {
-	    printf ("problem creating %s\n", dir);
-	} else {
-	    printf ("%s created\n", dir);
-	}
-    } else {
-	printf ("%s already exists\n", dir);
-    }
-
-    return (result);
-}
-
-#endif // __CYGWIN32__
-
-
-void scenery_dir( const string& dir ) {
-    struct stat stat_buf;
-    char base_path[256], file[256], exfile[256];
-#ifdef __CYGWIN32__
-    char tmp_path[256];
+#ifdef WIN32
+#ifndef TRUE
+ #define FALSE 0
+ #define TRUE 1
 #endif
-    string command;
-    FILE *fd;
-	fgBUCKET p;
-	int result;
 
-    cout << "Dir = " + dir + "\n";
+char* PathDivider()
+{
+	return "\\";
+} // PathDivider
 
-    // stat() directory and create if needed
-    result = stat(dir.c_str(), &stat_buf);
-    if ( result != 0 ) {
-	cout << "Stat error need to create directory\n";
+void ReplaceDivider( char* path )
+{
+	char	div = PathDivider()[0];
+	int		i;
 
-#ifndef __CYGWIN32__
+	if ( ! path )
+		return;
+	if ( div == '/' )
+		return;
 
-	command = "mkdir -p " + dir + "\n";
-	system( command.c_str() );
+	for ( i = 0; path[i]; i++ )
+		if ( path[i] == '/' )
+			path[i] = div;
 
-#else // __CYGWIN32__
+} // ReplaceDivider
 
-	// Cygwin crashes when trying to output to node file
-	// explicitly making directory structure seems OK on Win95
+int	Exists( char* path )
+{
+    struct stat statbuff;
 
-	extract_path (base_path, tmp_path);
+	ReplaceDivider( path );
+	if ( path[strlen( path ) - 1] == ':' )
+		return TRUE;
+	if ( _stat( path, &statbuff ) != 0 )
+		return FALSE;
+	return TRUE;
+} // Exists
 
-	dir = tmp_path;
-	if (my_mkdir ( dir.c_str() )) {	exit (-1); }
 
-	dir = base_path;
-	if (my_mkdir ( dir.c_str() )) {	exit (-1); }
+void CreateDir( char* path )
+{
+	if ( ! path  ||  ! strlen( path ) )
+		return;
+	ReplaceDivider( path );
+								// see if the parent exists yet
+	int		i;	// looping index
+	string	parent;	// path to parent
 
-#endif // __CYGWIN32__
+	parent =  path;
+	for ( i = strlen( parent.c_str() )-1; i >= 0; i-- )
+		if ( parent[i] == PathDivider()[0] )
+		{
+			parent[i] = '\0';
+			break;
+		}
+	
+	if ( ! Exists( parent.c_str() ) )
+	{
+		CreateDir( parent.c_str() );
+	}
+
+	if ( ! Exists( path ) )
+	{
+		if (mkdir(path, S_IRWXU) != 0 )
+		{
+			cout << "Could not create directory " << path << endl;
+		}else{
+			cout << "CreateDir: " << path << endl;
+		}
+	}
+	
+} // CreateDir
 
-    } else {
-	// assume directory exists
-		cout << "  Allready Exists !\n";
-    }
-}
 
 int main(int argc, char **argv)
 {
@@ -109,11 +98,14 @@ int main(int argc, char **argv)
 
 	if(argc != 2)
 	{
-		cout << "Makedir failed\n";
+		cout << "Makedir failed needs one argument\n";
 		return(10);
 	}
 	root = argv[1];
-	scenery_dir(root);
-
+	
+	CreateDir(root.c_str());
+	
 	return(0);
 }
+#endif // WIN32
+

From 1d97b7542df424d0715ccc2c1bdc64a21ef9f7bf Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 2 Nov 1998 18:25:40 +0000
Subject: [PATCH 172/283] Check for __CYGWIN__ (b20) as well as __CYGWIN32__
 (pre b20 compilers) Other misc. tweaks.

---
 AssemTris/assemtris.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/AssemTris/assemtris.cxx b/AssemTris/assemtris.cxx
index 332a670d8..1c87851e3 100644
--- a/AssemTris/assemtris.cxx
+++ b/AssemTris/assemtris.cxx
@@ -32,7 +32,6 @@
 #include "assemtris.hxx"
 
 #include <Include/fg_constants.h>
-#include <Include/fg_types.h>
 #include <Bucket/bucketutils.h>
 
 
@@ -542,6 +541,10 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.3  1998/11/02 18:25:40  curt
+// Check for __CYGWIN__ (b20) as well as __CYGWIN32__ (pre b20 compilers)
+// Other misc. tweaks.
+//
 // Revision 1.2  1998/09/25 19:38:01  curt
 // Minor tweaks so that this actually compiles.
 //

From 535282bd234352c667a26890418ce141a946fd01 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 2 Nov 1998 18:29:42 +0000
Subject: [PATCH 173/283] Add a unix main so program will compiler there too. 
 It will output an "only for windoze" message.

---
 Makedir/makedir.cxx | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Makedir/makedir.cxx b/Makedir/makedir.cxx
index 9ba9db610..1bc7734cb 100644
--- a/Makedir/makedir.cxx
+++ b/Makedir/makedir.cxx
@@ -107,5 +107,13 @@ int main(int argc, char **argv)
 	
 	return(0);
 }
+#else
+
+int main(int argc, char **argv)
+{
+	cout << "This program is intended to work with windoze\n";
+	cout << "Other platforms can use mkdir\n";
+}
+
 #endif // WIN32
 

From 66f4bab7a002fdaca087c35d2291926be6ab0a4d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 4 Nov 1998 23:01:43 +0000
Subject: [PATCH 174/283] Changes to the automake/autoconf system to reduce the
 number of libraries that are unnecessarily linked into the various
 executables.

---
 Areas/Makefile.am        | 8 +++++++-
 AssemTris/Makefile.am    | 7 ++++++-
 DemInfo/Makefile.am      | 7 ++++++-
 DemRaw2ascii/Makefile.am | 6 +++++-
 FixNode/Makefile.am      | 7 ++++++-
 FixObj/Makefile.am       | 7 ++++++-
 GenAirports/Makefile.am  | 7 ++++++-
 Makedir/Makefile.am      | 4 +++-
 SplitTris/Makefile.am    | 7 ++++++-
 Stripe_u/Makefile.am     | 1 +
 Stripe_w/Makefile.am     | 1 +
 Tri2obj/Makefile.am      | 7 ++++++-
 Triangle/Makefile.am     | 2 ++
 13 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/Areas/Makefile.am b/Areas/Makefile.am
index 0ee77fcf0..7c6106189 100644
--- a/Areas/Makefile.am
+++ b/Areas/Makefile.am
@@ -28,13 +28,19 @@ bin_PROGRAMS = areas
 
 areas_SOURCES = area.cxx area.hxx main.cxx
 
-areas_LDADD = $(top_builddir)/Lib/Bucket/libBucket.a
+areas_LDADD = \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/11/04 23:01:43  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.2  1998/07/30 23:49:18  curt
 # Removed libtool support.
 #
diff --git a/AssemTris/Makefile.am b/AssemTris/Makefile.am
index 2398c9371..5e830c88b 100644
--- a/AssemTris/Makefile.am
+++ b/AssemTris/Makefile.am
@@ -29,13 +29,18 @@ bin_PROGRAMS = assemtris
 assemtris_SOURCES = assemtris.cxx assemtris.hxx
 
 assemtris_LDADD = \
-	$(top_builddir)/Lib/Bucket/libBucket.a
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1998/11/04 23:01:45  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.4  1998/09/25 19:35:25  curt
 # Renamed assemtris.[ch] to assemtris.[ch]xx
 #
diff --git a/DemInfo/Makefile.am b/DemInfo/Makefile.am
index aa73af873..39ae915fa 100644
--- a/DemInfo/Makefile.am
+++ b/DemInfo/Makefile.am
@@ -33,7 +33,8 @@ deminfo_LDADD = \
 	$(top_builddir)/Lib/DEM/libDEM.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
-	$(top_builddir)/Lib/zlib/libz.a
+	$(top_builddir)/Lib/zlib/libz.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
@@ -45,6 +46,10 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1998/11/04 23:01:48  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.3  1998/09/19 18:01:21  curt
 # Support for changes to libDEM.a
 #
diff --git a/DemRaw2ascii/Makefile.am b/DemRaw2ascii/Makefile.am
index 2ff4fb31e..b638e2e96 100644
--- a/DemRaw2ascii/Makefile.am
+++ b/DemRaw2ascii/Makefile.am
@@ -28,13 +28,17 @@ bin_PROGRAMS = raw2ascii
 
 raw2ascii_SOURCES = main.c rawdem.c rawdem.h
 
-raw2ascii_LDADD = 
+raw2ascii_LDADD = $(base_LIBS)
 
 INCLUDES += 
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/11/04 23:01:50  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.2  1998/04/24 00:44:04  curt
 # Added zlib support.
 #
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index a72e8b22c..cc21872cc 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -34,7 +34,8 @@ fixnode_LDADD = \
 	$(top_builddir)/Lib/DEM/libDEM.a \
         $(top_builddir)/Lib/Bucket/libBucket.a \
         $(top_builddir)/Lib/Misc/libMisc.a \
-        $(top_builddir)/Lib/zlib/libz.a
+        $(top_builddir)/Lib/zlib/libz.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
@@ -46,6 +47,10 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.7  1998/11/04 23:01:51  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.6  1998/09/19 20:43:50  curt
 # C++-ified and STL-ified the code.  Combined triload.* and fixnode.* into
 # a single file.
diff --git a/FixObj/Makefile.am b/FixObj/Makefile.am
index bafcf879c..7ced91cc9 100644
--- a/FixObj/Makefile.am
+++ b/FixObj/Makefile.am
@@ -31,13 +31,18 @@ fixobj_SOURCES = main.cxx obj.cxx obj.hxx
 fixobj_LDADD = \
 	$(top_builddir)/Lib/Math/libMath.a \
 	$(top_builddir)/Lib/Debug/libDebug.a \
-	$(top_builddir)/Lib/zlib/libz.a
+	$(top_builddir)/Lib/zlib/libz.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.7  1998/11/04 23:01:53  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.6  1998/07/30 23:49:25  curt
 # Removed libtool support.
 #
diff --git a/GenAirports/Makefile.am b/GenAirports/Makefile.am
index e3593d492..8ba8e5d1d 100644
--- a/GenAirports/Makefile.am
+++ b/GenAirports/Makefile.am
@@ -34,13 +34,18 @@ genapts_SOURCES = \
 
 genapts_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
-	$(top_builddir)/Lib/zlib/libz.a
+	$(top_builddir)/Lib/zlib/libz.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1998/11/04 23:01:54  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.2  1998/09/04 23:04:47  curt
 # Beginning of convex hull genereration routine.
 #
diff --git a/Makedir/Makefile.am b/Makedir/Makefile.am
index c83672258..e93857cc0 100644
--- a/Makedir/Makefile.am
+++ b/Makedir/Makefile.am
@@ -2,6 +2,8 @@ bin_PROGRAMS = makedir
 
 makedir_SOURCES = makedir.cxx
 
-makedir_LDADD = $(top_builddir)/Lib/Bucket/libBucket.a
+makedir_LDADD = \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
diff --git a/SplitTris/Makefile.am b/SplitTris/Makefile.am
index 8e4c2df64..e8f64e5b9 100644
--- a/SplitTris/Makefile.am
+++ b/SplitTris/Makefile.am
@@ -33,13 +33,18 @@ splittris_LDADD = \
 	$(top_builddir)/Lib/Math/libMath.a \
         $(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
-        $(top_builddir)/Lib/zlib/libz.a
+        $(top_builddir)/Lib/zlib/libz.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.8  1998/11/04 23:01:57  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.7  1998/10/18 01:17:25  curt
 # Point3D tweaks.
 #
diff --git a/Stripe_u/Makefile.am b/Stripe_u/Makefile.am
index 56308ad51..8373ea88b 100644
--- a/Stripe_u/Makefile.am
+++ b/Stripe_u/Makefile.am
@@ -27,3 +27,4 @@ strips_SOURCES = \
 	triangulate.h triangulatex.h \
 	util.c util.h
 
+strips_LDADD = $(base_LIBS)
diff --git a/Stripe_w/Makefile.am b/Stripe_w/Makefile.am
index d3dbaab29..ac0280b8a 100644
--- a/Stripe_w/Makefile.am
+++ b/Stripe_w/Makefile.am
@@ -24,3 +24,4 @@ strips_SOURCES = \
 	triangulate.h triangulatex.h \
 	util.c util.h
 
+strips_LDADD = $(base_LIBS)
diff --git a/Tri2obj/Makefile.am b/Tri2obj/Makefile.am
index 6c57a638d..c27fc320f 100644
--- a/Tri2obj/Makefile.am
+++ b/Tri2obj/Makefile.am
@@ -32,13 +32,18 @@ tri2obj_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Math/libMath.a \
         $(top_builddir)/Lib/Debug/libDebug.a \
-        $(top_builddir)/Lib/zlib/libz.a
+        $(top_builddir)/Lib/zlib/libz.a \
+	$(base_LIBS)
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.7  1998/11/04 23:02:02  curt
+# Changes to the automake/autoconf system to reduce the number of libraries
+# that are unnecessarily linked into the various executables.
+#
 # Revision 1.6  1998/07/30 23:49:26  curt
 # Removed libtool support.
 #
diff --git a/Triangle/Makefile.am b/Triangle/Makefile.am
index 99c292410..9753a8dad 100644
--- a/Triangle/Makefile.am
+++ b/Triangle/Makefile.am
@@ -15,4 +15,6 @@ bin_PROGRAMS = triangle # showme
 
 triangle_SOURCES = triangle.c triangle.h
 
+triangle_LDADD = $(base_LIBS)
+
 # showme_SOURCES = showme.c

From 01f5ad20cadddcf76d77e8d7605d1421833e50ee Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 6 Nov 1998 14:04:32 +0000
Subject: [PATCH 175/283] Changes due to updates in fgstream.

---
 DEM/dem.cxx | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index d04bc3917..b9dd62930 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -156,7 +156,7 @@ int fgDEM::close () {
 string fgDEM::next_token() {
     string token;
 
-    in->stream() >> token;
+    *in >> token;
 
     // cout << "    returning " + token + "\n";
 
@@ -167,8 +167,8 @@ string fgDEM::next_token() {
 // return next integer from input stream
 int fgDEM::next_int() {
     int result;
-
-    in->stream() >> result;
+    
+    *in >> result;
 
     return result;
 }
@@ -178,7 +178,7 @@ int fgDEM::next_int() {
 double fgDEM::next_double() {
     double result;
 
-    in->stream() >> result;
+    *in >> result;
 
     return result;
 }
@@ -858,6 +858,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.21  1998/11/06 14:04:32  curt
+// Changes due to updates in fgstream.
+//
 // Revision 1.20  1998/10/28 19:38:20  curt
 // Elliminate some unnecessary win32 specific stuff (by Norman Vine)
 //

From 8cf9f40c72a1e4e741e19b72a38fe58fd5aab65f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 6 Nov 1998 21:33:55 +0000
Subject: [PATCH 176/283] Updates to go along with changes in fgstream.

---
 FixNode/fixnode.cxx     | 11 +++++++----
 SplitTris/splittris.cxx | 11 +++++++----
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/FixNode/fixnode.cxx b/FixNode/fixnode.cxx
index 183833d4d..5269ac459 100644
--- a/FixNode/fixnode.cxx
+++ b/FixNode/fixnode.cxx
@@ -60,16 +60,16 @@ void load_nodes(const string& filename, container& node_list) {
     }
 
     // Read header line
-    in.stream() >> nodecount >> dim >> junk1 >> junk2;
+    in >> nodecount >> dim >> junk1 >> junk2;
     cout << "    Expecting " << nodecount << " nodes\n";
 
     // start with an empty list :-)
     node_list.erase( node_list.begin(), node_list.end() );
 
-    in.eat_comments();
+    in >> skipcomment;
     while ( ! in.eof() ) {
-	in.stream() >> junk1 >> node >> junk2;
-	in.eat_comments();
+	in >> junk1 >> node >> junk2;
+	in >> skipcomment;
 	node_list.push_back(node);
     }
 }
@@ -121,6 +121,9 @@ void fix_nodes( const string& filename, fgDEM& dem, container& node_list )
 
 
 // $Log$
+// Revision 1.7  1998/11/06 21:33:55  curt
+// Updates to go along with changes in fgstream.
+//
 // Revision 1.6  1998/10/20 15:49:22  curt
 // Converted to Point3D class.
 //
diff --git a/SplitTris/splittris.cxx b/SplitTris/splittris.cxx
index e4247715e..20e26e7a9 100644
--- a/SplitTris/splittris.cxx
+++ b/SplitTris/splittris.cxx
@@ -156,11 +156,11 @@ void triload(const string& basename) {
     nodes_cart.push_back(node1);
     tri_list.push_back(tri);
 
-    node_in.stream() >> nodecount >> dim >> junk1 >> junk2;
+    node_in >> nodecount >> dim >> junk1 >> junk2;
     cout << "    Expecting " << nodecount << " nodes\n";
 
     for ( i = 1; i <= nodecount; i++ ) {
-	node_in.stream() >> junk1 >> node1 >> junk2;
+	node_in >> junk1 >> node1 >> junk2;
 	nodes_orig.push_back(node1);
 	// printf("%d %.2f %.2f %.2f\n", junk1, node1.x, node1.y, node1.z);
 	
@@ -199,13 +199,13 @@ void triload(const string& basename) {
 	exit(-1);
     }
 
-    ele_in.stream() >> tricount >> junk1 >> junk2;
+    ele_in >> tricount >> junk1 >> junk2;
     cout << "    Expecting " << tricount << " elements\n";
 
     for ( i = 1; i <= tricount; i++ ) {
 	// fscanf(ele_file, "%d %d %d %d\n", &junk1, 
 	//        &(tri.n1), &(tri.n2), &(tri.n3));
-	ele_in.stream() >> junk1 >> tri.n1 >> tri.n2 >> tri.n3;
+	ele_in >> junk1 >> tri.n1 >> tri.n2 >> tri.n3;
 	// printf("%d %d %d %d\n", junk1, tri.n1, tri.n2, tri.n3);
 	tri_list.push_back(tri);
     }
@@ -616,6 +616,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.7  1998/11/06 21:33:57  curt
+// Updates to go along with changes in fgstream.
+//
 // Revision 1.6  1998/10/21 14:56:20  curt
 // Fixed a units conversion bug.
 //

From 90b73f480f413b73564e916333f207f5554ae23e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 20 Nov 1998 01:02:55 +0000
Subject: [PATCH 177/283] Speedups for win32.

---
 Tools/process-dem.pl | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/Tools/process-dem.pl b/Tools/process-dem.pl
index 21bee54a8..5a92c5bb5 100755
--- a/Tools/process-dem.pl
+++ b/Tools/process-dem.pl
@@ -58,6 +58,7 @@ $fg_root = shift(@ARGV);
 $work_dir = shift(@ARGV);
 $error = shift(@ARGV);
 $error += 0.0;
+$system_name = `uname -s`; chop($system_name);
 
 while ( $dem_file = shift(@ARGV) ) {
     print "Source file = $dem_file  Error tolerance = $error\n";
@@ -94,11 +95,7 @@ exit(0);
 # replace all unix forward slashes with windoze backwards slashes if
 # running on a cygwin32 system
 sub fix_slashes { my($in) = @_;
-
-    $system = `uname -s`;
-    chop($system);
-
-    if ( $system =~ m/CYGWIN32/ ) { 
+    if ( $system_name =~ m/CYGWIN32/ ) { 
         $in =~ s/\/+/\//g;
         $in =~ s/\//\\/g;
     }
@@ -474,10 +471,7 @@ sub install {
     $install_dir =~ s/\/+/\//g;
     print "Install dir = $install_dir\n";
 
-    $system = `uname -s`;
-    chop($system);
-
-    if ( $system !~ m/CYGWIN32/ ) {
+    if ( $system_name !~ m/CYGWIN32/ ) {
 	$command = "mkdir -p $install_dir";
     } else {
         $command = "Makedir/makedir $install_dir";
@@ -491,13 +485,12 @@ sub install {
     }
     close(OUT);
 
-
     # write out version and info record
     $version_file = "$install_dir/VERSION";
     open(VERSION, ">$version_file") || 
 	die "Cannot open $version_file for writing\n";
     print VERSION "FGFS Scenery Version $scenery_format_version\n";
-    if ( $system !~ m/CYGWIN32/ ) {
+    if ( $system_name !~ m/CYGWIN32/ ) {
 	$date = `date`; chop($date);
     } else {
 	# ???
@@ -551,6 +544,9 @@ sub install {
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.32  1998/11/20 01:02:55  curt
+# Speedups for win32.
+#
 # Revision 1.31  1998/10/28 19:39:06  curt
 # Changes to better support win32 scenery development.
 #

From 72ea27e43b4491677fe3e3c59b914798a4238f94 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 20 Nov 1998 01:03:18 +0000
Subject: [PATCH 178/283] FreeBSD support.

---
 Stripe_w/bands.c       | 23 +++++++++++++++--------
 Stripe_w/polyvertsex.h | 12 ++++++++++--
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/Stripe_w/bands.c b/Stripe_w/bands.c
index 1992795a6..161e8ccde 100644
--- a/Stripe_w/bands.c
+++ b/Stripe_w/bands.c
@@ -35,15 +35,22 @@
 
 /*   TIMING for Windows */
 #ifdef WIN32
-#include <sys/timeb.h>
-#include <time.h>
+#  include <sys/timeb.h>
+#  include <time.h>
 /*   TIMING for UNIX */
 #else
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/times.h>
-extern long times( );
-long elapsed()
+#  include <sys/types.h>
+#  include <sys/param.h>
+#  include <sys/times.h>
+#  if defined(__FreeBSD__)
+#    ifndef HZ
+#      include <time.h>
+#      define HZ CLK_TCK
+#    endif /* HZ */
+#  else
+     extern long times( );
+#  endif /* __FreeBSD__ */
+  long elapsed()
 {
   static long total = 0;
   long cpu_time, dummy;
@@ -55,7 +62,7 @@ long elapsed()
   total    = dummy;
   return(cpu_time);
 }
-#endif
+#endif /* WIN32 */
 
 
 int     norms[STRIP_MAX];
diff --git a/Stripe_w/polyvertsex.h b/Stripe_w/polyvertsex.h
index 8e05a7dd3..4c541f7bc 100644
--- a/Stripe_w/polyvertsex.h
+++ b/Stripe_w/polyvertsex.h
@@ -10,9 +10,17 @@
 /*   STRIPE: polvertsex.h
 -----------------------------------------------------------------------*/
 
-#include "queue.h"
-#include <malloc.h>
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
 
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#else
+#  include <malloc.h>
+#endif
+
+#include "queue.h"
 
 /*      external functions */
 void Start_Vert_Struct();

From a2410cd3168cf698cb01610ed25215da7b08192b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 19 Jan 1999 20:56:56 +0000
Subject: [PATCH 179/283] MacOS portability changes contributed by "Robert
 Puyol" <puyol@abvent.fr>

---
 DEM/dem.cxx | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index b9dd62930..8fce8cc97 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -28,18 +28,28 @@
 #  include <config.h>
 #endif
 
+#include <Include/compiler.h>
+
 #include <ctype.h>    // isspace()
 #include <stdlib.h>   // atoi()
 #include <math.h>     // rint()
 #include <stdio.h>
 #include <string.h>
-#include <sys/stat.h> // stat()
-#include <errno.h>
+#ifdef HAVE_SYS_STAT_H
+#  include <sys/stat.h> // stat()
+#endif
+#ifdef FG_HAVE_STD_INCLUDES
+#  include <cerrno>
+#else
+#  include <errno.h>
+#endif
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>   // stat()
 #endif
 #include <string>
 
+#include STL_IOSTREAM
+
 // #include <zlib/zlib.h>
 #include <Misc/fgstream.hxx>
 #include <Misc/strutils.hxx>
@@ -858,6 +868,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.22  1999/01/19 20:56:56  curt
+// MacOS portability changes contributed by "Robert Puyol" <puyol@abvent.fr>
+//
 // Revision 1.21  1998/11/06 14:04:32  curt
 // Changes due to updates in fgstream.
 //

From 730132afab2b864b076f59b0798cc68ef7bc08de Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Feb 1999 21:09:21 +0000
Subject: [PATCH 180/283] Moving location of Lib/DEM/ to Tools/DEM/

---
 DemInfo/Makefile.am | 7 +++++--
 FixNode/Makefile.am | 7 +++++--
 Tools/Makefile.am   | 1 +
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/DemInfo/Makefile.am b/DemInfo/Makefile.am
index 39ae915fa..0b3c81ebf 100644
--- a/DemInfo/Makefile.am
+++ b/DemInfo/Makefile.am
@@ -30,13 +30,13 @@ deminfo_SOURCES = \
 	deminfo.cxx
 
 deminfo_LDADD = \
-	$(top_builddir)/Lib/DEM/libDEM.a \
+	$(top_builddir)/Tools/DEM/libDEM.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
 
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
@@ -46,6 +46,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1999/02/01 21:09:27  curt
+# Moving location of Lib/DEM/ to Tools/DEM/
+#
 # Revision 1.4  1998/11/04 23:01:48  curt
 # Changes to the automake/autoconf system to reduce the number of libraries
 # that are unnecessarily linked into the various executables.
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index cc21872cc..0ec673276 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -31,13 +31,13 @@ fixnode_SOURCES = \
 	main.cxx
 
 fixnode_LDADD = \
-	$(top_builddir)/Lib/DEM/libDEM.a \
+	$(top_builddir)/Tools/DEM/libDEM.a \
         $(top_builddir)/Lib/Bucket/libBucket.a \
         $(top_builddir)/Lib/Misc/libMisc.a \
         $(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
 
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
@@ -47,6 +47,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.8  1999/02/01 21:09:30  curt
+# Moving location of Lib/DEM/ to Tools/DEM/
+#
 # Revision 1.7  1998/11/04 23:01:51  curt
 # Changes to the automake/autoconf system to reduce the number of libraries
 # that are unnecessarily linked into the various executables.
diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 41cc40b7c..f501f6d76 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	Areas \
 	AssemTris \
+	DEM \
 	Dem2node \
 	DemInfo \
 	DemRaw2ascii \

From 3cf321736b543f41f7a61b7c913c813705827c5f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Feb 1999 21:09:40 +0000
Subject: [PATCH 181/283] Optimizations from Norman Vine.

---
 FixObj/obj.cxx | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/FixObj/obj.cxx b/FixObj/obj.cxx
index 571a71058..4239a1891 100644
--- a/FixObj/obj.cxx
+++ b/FixObj/obj.cxx
@@ -144,7 +144,7 @@ void fix_cw_list(int *list, int list_ptr) {
 
 
 void dump_global_bounds( void ) {
-    double dist, radius;
+    double dist_squared, radius, radius_squared;
 
     radius = 0.0;
 
@@ -158,14 +158,16 @@ void dump_global_bounds( void ) {
     ++current;
 
     for ( ; current != last; ++current ) {
-	dist = ref.distance3D(*current);
-	// cout << "node = " << *current << " dist = " << dist << endl;
+	dist_squared = ref.distance3Dsquared(*current);
+	// cout << "node = " << *current << " dist = " << dist_squared << endl;
 
-	if ( dist > radius ) {
-	    radius = dist;
+	if ( dist_squared > radius_squared ) {
+	    radius_squared = dist_squared;
 	}
     }
 
+    radius = sqrt(radius_squared);
+
     fprintf( out, 
 	     "gbs %.5f %.5f %.5f %.2f\n", 
 	     ref.x(), ref.y(), ref.z(), radius);
@@ -264,7 +266,8 @@ void dump_faces( void ) {
 // dump list
 void dump_list(int *list, int list_ptr) {
     Point3D p;
-    double xmax, xmin, ymax, ymin, zmax, zmin, dist, radius;
+    double xmax, xmin, ymax, ymin, zmax, zmin, dist_squared, radius_squared;
+    double radius;
     int i, j, len, n;
 
     if ( list_ptr < 3 ) {
@@ -318,13 +321,17 @@ void dump_list(int *list, int list_ptr) {
 
 	// calc bounding radius
 	n = list[i];
-	radius = p.distance3D(nodes[n]);
+	radius_squared = p.distance3Dsquared(nodes[n]);
 
 	for ( j = i + 1; j < i + len; j++ ) {
 	    n = list[j];
-	    dist = p.distance3D(nodes[n]);
-	    if ( dist > radius ) { radius = dist; }
+	    dist_squared = p.distance3Dsquared(nodes[n]);
+	    if ( dist_squared > radius_squared ) {
+		radius_squared = dist_squared;
+	    }
 	}
+	radius = sqrt(radius_squared);
+
 	// printf("radius = %.2f\n", radius);
 
 	// dump bounding sphere and header
@@ -577,6 +584,9 @@ void obj_fix(char *infile, char *outfile) {
 
 
 // $Log$
+// Revision 1.3  1999/02/01 21:09:40  curt
+// Optimizations from Norman Vine.
+//
 // Revision 1.2  1998/10/21 14:55:55  curt
 // Converted to Point3D class.
 //
@@ -635,4 +645,3 @@ void obj_fix(char *infile, char *outfile) {
 // Revision 1.1  1997/12/08 19:28:54  curt
 // Initial revision.
 //
-

From d6b38f2eeaa3e1b8c144dcd1f8e24ba09fc3f01f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 11 Feb 1999 01:10:16 +0000
Subject: [PATCH 182/283] Added Clipper/ and ShapeFile/

---
 Tools/Makefile.am | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index f501f6d76..a98b77857 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	Areas \
 	AssemTris \
+	Clipper \
 	DEM \
 	Dem2node \
 	DemInfo \
@@ -11,6 +12,7 @@ SUBDIRS = \
 	FixObj \
 	GenAirports \
 	Makedir \
+	ShapeFile \
 	SplitTris \
 	Stripe_w \
 	Tri2obj \

From b1eb65cd5dae2e88f1ad4606e6a4bb2134b15fe0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 11 Feb 1999 01:10:50 +0000
Subject: [PATCH 183/283] Start of scenery revamp project.

---
 GenAirports/Makefile.am |   5 +
 GenAirports/main.cxx    | 259 ++++++++++++++++++----------------------
 2 files changed, 124 insertions(+), 140 deletions(-)

diff --git a/GenAirports/Makefile.am b/GenAirports/Makefile.am
index 8ba8e5d1d..70e1c076c 100644
--- a/GenAirports/Makefile.am
+++ b/GenAirports/Makefile.am
@@ -34,6 +34,8 @@ genapts_SOURCES = \
 
 genapts_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/Debug/libDebug.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
@@ -42,6 +44,9 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.4  1999/02/11 01:10:50  curt
+# Start of scenery revamp project.
+#
 # Revision 1.3  1998/11/04 23:01:54  curt
 # Changes to the automake/autoconf system to reduce the number of libraries
 # that are unnecessarily linked into the various executables.
diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index 475ae10ea..47297b91b 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -27,6 +27,8 @@
 #include <config.h>
 #endif
 
+#include <Include/compiler.h>
+
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
@@ -34,16 +36,55 @@
 #include <list>
 #include <stdio.h>
 #include <string.h>
-#include <string>
+#include STL_STRING
 
-#include <Bucket/bucketutils.h>
+#include <Bucket/newbucket.hxx>
+#include <Debug/logstream.hxx>
 #include <Include/fg_constants.h>
-#include <Include/fg_zlib.h>
+#include <Misc/fgstream.hxx>
 
 #include "area.hxx"
 #include "convex_hull.hxx"
 
 
+// write out airport data
+void write_airport( list_container hull_list, FGBucket b, const string& root,
+		    const bool cut_and_keep ) {
+    char tmp[256];
+
+    long int index = b.gen_index();
+    string base = b.gen_base_path();
+    string path = root + "/Scenery/" + base;
+    string command = "mkdir -p " + path;
+    system( command.c_str() );
+
+    sprintf(tmp, "%ld", index);
+    string aptfile = path + "/" + tmp + ".apt";
+    cout << "apt file = " << aptfile << endl;
+
+    FILE *fd;
+    if ( (fd = fopen(aptfile.c_str(), "a")) == NULL ) {
+        cout << "Cannot open file: " << aptfile << endl;
+        exit(-1);
+    }
+
+    if ( cut_and_keep ) {
+	fprintf( fd, "cut_and_keep\n" );
+    } else {
+	fprintf( fd, "cut_and_ignore\n" );
+    }
+    fprintf( fd, "%d\n", hull_list.size() );
+    // write perimeter polygon
+    list_iterator current = hull_list.begin();
+    list_iterator last = hull_list.end();
+    for ( ; current != last ; ++current ) {
+	fprintf( fd, "%.7f %.7f\n", (*current).lon, (*current).lat );
+    }
+
+    fclose(fd);
+}
+
+
 // process and airport + runway list
 void process_airport( string last_airport, list < string > & runway_list,
 		      const string& root ) {
@@ -52,26 +93,19 @@ void process_airport( string last_airport, list < string > & runway_list,
 
     string line_str;
     double lon, lat;
+    // int i;
+    int count;
+
+    // generate the vertices of all the runways
     int len, width, hdg, label_hdg, elev;
     char codes[10];
     char side;
-    point2d average;
-    double sum_x, sum_y;
-
-    FILE *fd;
-    fgBUCKET b;
-    long int index;
-    char base[256], tmp[256];
-    string path, command, exfile, file, aptfile;
-    int i, count;
-
-    printf( "(apt) %s", last_airport.c_str() );
-
+    cout << "(apt) " << last_airport;
     list < string >::iterator last_runway = runway_list.end();
     for ( list < string >::iterator current_runway = runway_list.begin();
 	  current_runway != last_runway ; ++current_runway ) {
 	line_str = (*current_runway);
-	printf( "%s", line_str.c_str() );
+	cout << line_str;
 
 	sscanf( line_str.c_str(), "%lf %lf %d %d %d %s %d %c %d\n",
 		&lon, &lat, &len, &width, &hdg, codes, &label_hdg, 
@@ -90,123 +124,75 @@ void process_airport( string last_airport, list < string > & runway_list,
     }
 
     // printf("Runway points in degrees\n");
-    current = apt_list.begin();
-    last = apt_list.end();
-    for ( ; current != last; ++current ) {
-	// printf( "%.5f %.5f\n", current->lon, current->lat );
-    }
+    // current = apt_list.begin();
+    // last = apt_list.end();
+    // for ( ; current != last; ++current ) {
+    //   printf( "%.5f %.5f\n", current->lon, current->lat );
+    // }
     // printf("\n");
 
     // generate convex hull
     hull_list = convex_hull(apt_list);
 
-    // find average center point of convex hull
+    // find average center, min, and max point of convex hull
+    point2d average, min, max;
+    double sum_x, sum_y;
     count = hull_list.size();
-
     current = hull_list.begin();
     last = hull_list.end();
     sum_x = sum_y = 0.0;
+    min.x = min.y = 200.0;
+    max.x = max.y = -200.0;
     for ( ; current != last; ++current ) {
 	// printf("return = %.6f %.6f\n", (*current).x, (*current).y);
 	sum_x += (*current).x;
 	sum_y += (*current).y;
-    }
 
+	if ( (*current).x < min.x ) { min.x = (*current).x; }
+	if ( (*current).y < min.y ) { min.y = (*current).y; }
+	if ( (*current).x > max.x ) { max.x = (*current).x; }
+	if ( (*current).y > max.y ) { max.y = (*current).y; }
+    }
     average.x = sum_x / count;
     average.y = sum_y / count;
 
-    // find bucket based on average center point of hull list.
-    // Eventually we'll need to handle cases where the area crosses
-    // bucket boundaries.
-    fgBucketFind( average.lon, average.lat, &b);
-    printf( "Bucket = lon,lat = %d,%d  x,y index = %d,%d\n", 
-	    b.lon, b.lat, b.x, b.y);
+    // find buckets for center, min, and max points of convex hull.
+    // note to self: self, you should think about checking for runways
+    // that span the data line
+    FGBucket b(average.lon, average.lat);
+    FGBucket b_min(min.x, min.y);
+    FGBucket b_max(max.x, max.y);
+    cout << "Bucket center = " << b << endl;
+    cout << "Bucket min = " << b_min << endl;
+    cout << "Bucket max = " << b_max << endl;
+    
+    if ( b_min == b_max ) {
+	write_airport( hull_list, b, root, true );
+    } else {
+	FGBucket b_cur;
+	int dx, dy, i, j;
 
-    index = fgBucketGenIndex(&b);
-    fgBucketGenBasePath(&b, base);
-    path = root + "/Scenery/" + base;
-    command = "mkdir -p " + path;
-    system( command.c_str() );
+	fgBucketDiff(b_min, b_max, &dx, &dy);
+	cout << "airport spans tile boundaries" << endl;
+	cout << "  dx = " << dx << "  dy = " << dy << endl;
 
-    sprintf(tmp, "%ld", index);
-    exfile =  path + "/" + tmp + ".node.ex";
-    file =    path + "/" + tmp + ".poly";
-    aptfile = path + "/" + tmp + ".apt";
-    printf( "extra node file = %s\n", exfile.c_str() );
-    printf( "poly file = %s\n", file.c_str() );
-    printf( "apt file = %s\n", aptfile.c_str() );
+	if ( (dx > 1) || (dy > 1) ) {
+	    cout << "somethings really wrong!!!!" << endl;
+	    exit(-1);
+	}
 
-    // output exclude nodes
-    printf("Output exclude nodes\n");
-    if ( (fd = fopen(exfile.c_str(), "w")) == NULL ) {
-        printf("Cannot open file: %s\n", exfile.c_str());
-        exit(-1);
+	for ( j = 0; j <= dy; j++ ) {
+	    for ( i = 0; i <= dx; i++ ) {
+		b_cur = fgBucketOffset(min.x, min.y, i, j);
+		if ( b_cur == b ) {
+		    write_airport( hull_list, b_cur, root, true );
+		} else {
+		    write_airport( hull_list, b_cur, root, false );
+		}
+	    }
+	}
+	// string answer; cin >> answer;
     }
-
-    fprintf( fd, "%d 2 0 0\n", count );
-
-    current = hull_list.begin();
-    last = hull_list.end();
-    i = 1;
-    for ( ; current != last ; ++current ) {
-	// printf( "(%.4f, %.4f)\n", 
-	fprintf( fd, "%d %.2f %.2f %.2f\n", i, 
-		 (*current).lon * 3600.0, (*current).lat * 3600.0, 
-		 (double)elev * FEET_TO_METER );
-	++i;
-    }
-    fclose(fd);
-
-    // output poly
-    printf("Output poly\n");
-    if ( (fd = fopen(file.c_str(), "w")) == NULL ) {
-        printf("Cannot open file: %s\n", file.c_str());
-        exit(-1);
-    }
-
-    // output empty node list
-    fprintf(fd, "0 2 0 0\n");
-
-    // output segments
-    fprintf( fd, "%d 0\n", count );
-    for ( i = 1; i < count; i++ ) {
-	fprintf( fd, "%d %d %d\n", i, i, i + 1 );
-    }
-    fprintf( fd, "%d %d %d\n", count, count, 1 );
-
-    // output hole center
-    fprintf( fd, "1\n");
-    fprintf( fd, "1 %.2f %.2f\n", average.x * 3600.0, average.y * 3600);
-
-    fclose(fd);
-
-    // output "apt" file
-    printf("Output airport\n");
-    if ( (fd = fopen(aptfile.c_str(), "w")) == NULL ) {
-        printf("Cannot open file: %s\n", aptfile.c_str());
-        exit(-1);
-    }
-
-    // write main airport identifier
-    fprintf(fd, "a %s", last_airport.c_str() );
-
-    // write perimeter polygon
-    current = hull_list.begin();
-    last = hull_list.end();
-    for ( ; current != last ; ++current ) {
-	fprintf( fd, "p %.7f %.7f %.2f\n", (*current).lon, (*current).lat, 
-		 (double)elev * FEET_TO_METER );
-    }
-
-    // write runway info
-    for ( list < string >::iterator current_runway = runway_list.begin();
-	  current_runway != last_runway ; ++current_runway ) {
-	line_str = (*current_runway);
-	line_str = line_str.substr(1, line_str.size());
-	fprintf(fd, "r %s", line_str.c_str() );
-    }
-
-    fclose(fd);
 }
 
 
@@ -214,38 +200,30 @@ void process_airport( string last_airport, list < string > & runway_list,
 // airport records
 int main( int argc, char **argv ) {
     list < string > runway_list;
-    string apt_path, gz_apt_path;
     string airport, last_airport;
-    fgFile f;
-    char line[256];
-    /*
-    fgBUCKET b;
-    point2d nodes[4];
-    char base[256], path[256], command[256], file[256], exfile[256];
-    double lon, lat, elevation, heading;
-    double length, width;
-    long int index;
-    */
+    string line;
+    char tmp[256];
+
+    fglog().setLogLevels( FG_ALL, FG_DEBUG );
 
     if ( argc != 3 ) {
-	printf("Usage %s <apt_file> <work dir>\n", argv[0]);
-	exit(0);
+	FG_LOG( FG_GENERAL, FG_ALERT, 
+		"Usage " << argv[0] << " <apt_file> <work dir>" );
+	exit(-1);
     }
 
-    apt_path = argv[1];
-    gz_apt_path = apt_path + ".gz";
-
-    // first try "path.gz"
-    if ( (f = fgopen(gz_apt_path.c_str(), "rb")) == NULL ) {
-	// next try "path"
-        if ( (f = fgopen(apt_path.c_str(), "rb")) == NULL ) {
-	    printf( "Cannot open file: %s\n", apt_path.c_str());
-	}
+    fg_gzifstream in( argv[1] );
+    if ( !in ) {
+        FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << argv[1] );
+        exit(-1);
     }
 
-    while ( fggets(f, line, 250) != NULL ) {
-	// printf("%s", line);
-	if ( strlen(line) == 0 ) {
+    while ( ! in.eof() ) {
+	in.getline(tmp, 256);
+	line = tmp;
+	// cout << line << endl;
+
+	if ( line.length() == 0 ) {
 	    // empty, skip
 	} else if ( line[0] == '#' ) {
 	    // comment, skip
@@ -273,13 +251,14 @@ int main( int argc, char **argv ) {
 	process_airport(last_airport, runway_list, argv[2]);
     }
 
-    fgclose(f);
-
-    return(1);
+    return 0;
 }
 
 
 // $Log$
+// Revision 1.6  1999/02/11 01:10:51  curt
+// Start of scenery revamp project.
+//
 // Revision 1.5  1998/09/17 18:40:43  curt
 // Debug message tweaks.
 //

From bbcb8878f98904ebe59be63a6a881d22c9635676 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 15 Feb 1999 19:10:23 +0000
Subject: [PATCH 184/283] Initial revision.

---
 ShapeFile/Makefile.am |  11 +++++
 ShapeFile/main.cxx    | 103 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)
 create mode 100644 ShapeFile/Makefile.am
 create mode 100644 ShapeFile/main.cxx

diff --git a/ShapeFile/Makefile.am b/ShapeFile/Makefile.am
new file mode 100644
index 000000000..9139bcd92
--- /dev/null
+++ b/ShapeFile/Makefile.am
@@ -0,0 +1,11 @@
+bin_PROGRAMS = shape-decode
+
+shape_decode_SOURCES = main.cxx
+
+shape_decode_LDADD = $(top_builddir)/Lib/Debug/libDebug.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
+	$(top_builddir)/Lib/zlib/libz.a \
+	-lgfc
+
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
new file mode 100644
index 000000000..1319c98bb
--- /dev/null
+++ b/ShapeFile/main.cxx
@@ -0,0 +1,103 @@
+// main.cxx -- process shapefiles and extract polygon outlines,
+//             clipping against and sorting them into the revelant
+//             tiles.
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+
+// Include Geographic Foundation Classes library
+
+// libgfc.a includes need this bit o' strangeness
+#if defined ( linux )
+#  define _LINUX_
+#endif
+
+#include <gfc/gadt_polygon.h>
+#include <gfc/gdbf.h>
+#include <gfc/gshapefile.h>
+
+// include Generic Polygon Clipping Library
+
+extern "C" {
+#include <gpc.h>
+}
+
+#include <Debug/logstream.hxx>
+
+
+int main( int argc, char **argv ) {
+    fglog().setLogLevels( FG_ALL, FG_DEBUG );
+
+    if ( argc != 2 ) {
+	FG_LOG( FG_GENERAL, FG_ALERT, "Usage: " << argv[0] << " <shapefile>" );
+	exit(-1);
+    }
+
+    FG_LOG( FG_GENERAL, FG_DEBUG, "Opening " << argv[1] << " for reading." );
+
+    GShapeFile * sf = new GShapeFile( argv[1] );
+    GDBFile *names = new GDBFile( argv[1] );
+
+    GPolygon shape;
+    double  *coords; // in decimal degrees
+    int	n_vertices;
+    double lon, lat;
+
+    FG_LOG( FG_GENERAL, FG_INFO, sf->numRecords() );
+
+    GShapeFile::ShapeType t = sf->shapeType();
+    if ( t != GShapeFile::av_Polygon ) {
+	FG_LOG( FG_GENERAL, FG_ALERT, "Can't handle non-polygon shape files" );
+	exit(-1);
+    }
+
+    for ( int i = 0; i < sf->numRecords(); i++ ) {
+	//fetch i-th record (shape)
+	FG_LOG( FG_GENERAL, FG_DEBUG, names->getRecord( i ) );
+
+	sf->getShapeRec(i, &shape); 
+
+	FG_LOG( FG_GENERAL, FG_DEBUG, "Record = " << i << "  rings = " 
+		<< shape.numRings() );
+
+	for ( int j = 0; j < shape.numRings(); j++ ) {
+	    //return j-th branch's coords, # of vertices
+	    n_vertices = shape.getRing(j, coords);
+
+	    FG_LOG( FG_GENERAL, FG_DEBUG, "  ring " << j << " = " );
+	    FG_LOG( FG_GENERAL, FG_INFO, n_vertices );
+
+	    for ( int k = 0; k < n_vertices; k++ ) {
+		lon = coords[k*2+0];
+		lat = coords[k*2+1];
+		FG_LOG( FG_GENERAL, FG_INFO, lon << " " << lat );
+	    }
+	}
+    }
+
+    return 0;
+}
+
+// $Log$
+// Revision 1.1  1999/02/15 19:10:23  curt
+// Initial revision.
+//

From d4950f5e70344d81e868e91cc544fcda0c9eb3f9 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 19 Feb 1999 19:05:17 +0000
Subject: [PATCH 185/283] Working on clipping shapes and distributing into
 buckets.

---
 ShapeFile/Makefile.am |  3 +-
 ShapeFile/main.cxx    | 92 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/ShapeFile/Makefile.am b/ShapeFile/Makefile.am
index 9139bcd92..3c92a6561 100644
--- a/ShapeFile/Makefile.am
+++ b/ShapeFile/Makefile.am
@@ -3,9 +3,10 @@ bin_PROGRAMS = shape-decode
 shape_decode_SOURCES = main.cxx
 
 shape_decode_LDADD = $(top_builddir)/Lib/Debug/libDebug.a \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
-	-lgfc
+	-lgfc -lgpc
 
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
index 1319c98bb..966b14f4a 100644
--- a/ShapeFile/main.cxx
+++ b/ShapeFile/main.cxx
@@ -35,16 +35,59 @@
 #include <gfc/gdbf.h>
 #include <gfc/gshapefile.h>
 
-// include Generic Polygon Clipping Library
+#undef E
+#undef DEG_TO_RAD
+#undef RAD_TO_DEG
 
+// include Generic Polygon Clipping Library
 extern "C" {
 #include <gpc.h>
 }
 
+#include <Bucket/newbucket.hxx>
 #include <Debug/logstream.hxx>
 
 
+class point2d {
+public:
+    double x, y;
+};
+
+
+static void clip_and_write_poly( FGBucket b, int n_vertices, double *coords ) {
+    point2d c, min, max;
+    c.x = b.get_center_lon();
+    c.y = b.get_center_lat();
+    double span = bucket_span(c.y);
+
+    // calculate bucket dimensions
+    if ( (c.y >= -89.0) && (c.y < 89.0) ) {
+	min.x = c.x - span / 2.0;
+	max.x = c.x + span / 2.0;
+	min.y = c.y - FG_HALF_BUCKET_SPAN;
+	max.y = c.y + FG_HALF_BUCKET_SPAN;
+    } else if ( c.y < -89.0) {
+	min.x = -90.0;
+	max.x = -89.0;
+	min.y = -180.0;
+	max.y = 180.0;
+    } else if ( c.y >= 89.0) {
+	min.x = 89.0;
+	max.x = 90.0;
+	min.y = -180.0;
+	max.y = 180.0;
+    } else {
+	FG_LOG ( FG_GENERAL, FG_ALERT, 
+		 "Out of range latitude in clip_and_write_poly() = " << c.y );
+    }
+
+    
+}
+
+
 int main( int argc, char **argv ) {
+    point2d min, max;
+
     fglog().setLogLevels( FG_ALL, FG_DEBUG );
 
     if ( argc != 2 ) {
@@ -86,6 +129,50 @@ int main( int argc, char **argv ) {
 	    FG_LOG( FG_GENERAL, FG_DEBUG, "  ring " << j << " = " );
 	    FG_LOG( FG_GENERAL, FG_INFO, n_vertices );
 
+	    // find min/max of this polygon
+	    min.x = min.y = 200.0;
+	    max.x = max.y = -200.0;
+	    for ( int k = 0; k < n_vertices; k++ ) {
+		if ( coords[k*2+0] < min.x ) { min.x = coords[k*2+0]; }
+		if ( coords[k*2+1] < min.y ) { min.y = coords[k*2+1]; }
+		if ( coords[k*2+0] > max.x ) { max.x = coords[k*2+0]; }
+		if ( coords[k*2+1] > max.y ) { max.y = coords[k*2+1]; }
+	    }
+	    FG_LOG( FG_GENERAL, FG_INFO, "min = " << min.x << "," << min.y
+		    << " max = " << max.x << "," << max.y );
+
+	    // find buckets for min, and max points of convex hull.
+	    // note to self: self, you should think about checking for
+	    // polygons that span the date line
+	    FGBucket b_min(min.x, min.y);
+	    FGBucket b_max(max.x, max.y);
+	    cout << "Bucket min = " << b_min << endl;
+	    cout << "Bucket max = " << b_max << endl;
+	    
+	    if ( b_min == b_max ) {
+		clip_and_write_poly( b_min, n_vertices, coords );
+	    } else {
+		FGBucket b_cur;
+		int dx, dy, i, j;
+
+		fgBucketDiff(b_min, b_max, &dx, &dy);
+		cout << "airport spans tile boundaries" << endl;
+		cout << "  dx = " << dx << "  dy = " << dy << endl;
+
+		if ( (dx > 1) || (dy > 1) ) {
+		    cout << "somethings really wrong!!!!" << endl;
+		    exit(-1);
+		}
+
+		for ( j = 0; j <= dy; j++ ) {
+		    for ( i = 0; i <= dx; i++ ) {
+			b_cur = fgBucketOffset(min.x, min.y, i, j);
+			clip_and_write_poly( b_cur, n_vertices, coords );
+		    }
+		}
+		// string answer; cin >> answer;
+	    }
+
 	    for ( int k = 0; k < n_vertices; k++ ) {
 		lon = coords[k*2+0];
 		lat = coords[k*2+1];
@@ -98,6 +185,9 @@ int main( int argc, char **argv ) {
 }
 
 // $Log$
+// Revision 1.2  1999/02/19 19:05:18  curt
+// Working on clipping shapes and distributing into buckets.
+//
 // Revision 1.1  1999/02/15 19:10:23  curt
 // Initial revision.
 //

From 1a7c97601d6203a5c26e3531d80a50277db2236f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 23 Feb 1999 01:29:03 +0000
Subject: [PATCH 186/283] Additional progress.

---
 ShapeFile/Makefile.am |   2 +-
 ShapeFile/main.cxx    | 262 +++++++++++++++++++++++++++---------------
 ShapeFile/names.cxx   | 104 +++++++++++++++++
 ShapeFile/names.hxx   |  68 +++++++++++
 ShapeFile/shape.cxx   | 258 +++++++++++++++++++++++++++++++++++++++++
 ShapeFile/shape.hxx   |  61 ++++++++++
 6 files changed, 659 insertions(+), 96 deletions(-)
 create mode 100644 ShapeFile/names.cxx
 create mode 100644 ShapeFile/names.hxx
 create mode 100644 ShapeFile/shape.cxx
 create mode 100644 ShapeFile/shape.hxx

diff --git a/ShapeFile/Makefile.am b/ShapeFile/Makefile.am
index 3c92a6561..c0c4b666e 100644
--- a/ShapeFile/Makefile.am
+++ b/ShapeFile/Makefile.am
@@ -1,6 +1,6 @@
 bin_PROGRAMS = shape-decode
 
-shape_decode_SOURCES = main.cxx
+shape_decode_SOURCES = names.cxx names.hxx main.cxx shape.cxx shape.hxx
 
 shape_decode_LDADD = $(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
index 966b14f4a..3af9438c6 100644
--- a/ShapeFile/main.cxx
+++ b/ShapeFile/main.cxx
@@ -30,11 +30,9 @@
 #if defined ( linux )
 #  define _LINUX_
 #endif
-
 #include <gfc/gadt_polygon.h>
 #include <gfc/gdbf.h>
 #include <gfc/gshapefile.h>
-
 #undef E
 #undef DEG_TO_RAD
 #undef RAD_TO_DEG
@@ -44,68 +42,42 @@ extern "C" {
 #include <gpc.h>
 }
 
-#include <Bucket/newbucket.hxx>
+#include <Include/compiler.h>
+
+#include STL_STRING
+
 #include <Debug/logstream.hxx>
 
-
-class point2d {
-public:
-    double x, y;
-};
-
-
-static void clip_and_write_poly( FGBucket b, int n_vertices, double *coords ) {
-    point2d c, min, max;
-    c.x = b.get_center_lon();
-    c.y = b.get_center_lat();
-    double span = bucket_span(c.y);
-
-    // calculate bucket dimensions
-    if ( (c.y >= -89.0) && (c.y < 89.0) ) {
-	min.x = c.x - span / 2.0;
-	max.x = c.x + span / 2.0;
-	min.y = c.y - FG_HALF_BUCKET_SPAN;
-	max.y = c.y + FG_HALF_BUCKET_SPAN;
-    } else if ( c.y < -89.0) {
-	min.x = -90.0;
-	max.x = -89.0;
-	min.y = -180.0;
-	max.y = 180.0;
-    } else if ( c.y >= 89.0) {
-	min.x = 89.0;
-	max.x = 90.0;
-	min.y = -180.0;
-	max.y = 180.0;
-    } else {
-	FG_LOG ( FG_GENERAL, FG_ALERT, 
-		 "Out of range latitude in clip_and_write_poly() = " << c.y );
-    }
-
-    
-}
+#include "names.hxx"
+#include "shape.hxx"
 
 
 int main( int argc, char **argv ) {
-    point2d min, max;
+    gpc_polygon gpc_shape;
+    int i, j;
 
     fglog().setLogLevels( FG_ALL, FG_DEBUG );
 
-    if ( argc != 2 ) {
-	FG_LOG( FG_GENERAL, FG_ALERT, "Usage: " << argv[0] << " <shapefile>" );
+    if ( argc != 3 ) {
+	FG_LOG( FG_GENERAL, FG_ALERT, "Usage: " << argv[0] 
+		<< " <shapefile> <workdir>" );
 	exit(-1);
     }
 
     FG_LOG( FG_GENERAL, FG_DEBUG, "Opening " << argv[1] << " for reading." );
 
+    // initialize structure for building gpc polygons
+    shape_utils_init();
+
     GShapeFile * sf = new GShapeFile( argv[1] );
-    GDBFile *names = new GDBFile( argv[1] );
+    GDBFile *dbf = new GDBFile( argv[1] );
+    string path = argv[2];
 
     GPolygon shape;
     double  *coords; // in decimal degrees
     int	n_vertices;
-    double lon, lat;
 
-    FG_LOG( FG_GENERAL, FG_INFO, sf->numRecords() );
+    FG_LOG( FG_GENERAL, FG_INFO, "shape file records = " << sf->numRecords() );
 
     GShapeFile::ShapeType t = sf->shapeType();
     if ( t != GShapeFile::av_Polygon ) {
@@ -113,78 +85,178 @@ int main( int argc, char **argv ) {
 	exit(-1);
     }
 
-    for ( int i = 0; i < sf->numRecords(); i++ ) {
+    for ( i = 16473; i < sf->numRecords(); i++ ) {
 	//fetch i-th record (shape)
-	FG_LOG( FG_GENERAL, FG_DEBUG, names->getRecord( i ) );
-
 	sf->getShapeRec(i, &shape); 
-
 	FG_LOG( FG_GENERAL, FG_DEBUG, "Record = " << i << "  rings = " 
 		<< shape.numRings() );
 
-	for ( int j = 0; j < shape.numRings(); j++ ) {
-	    //return j-th branch's coords, # of vertices
-	    n_vertices = shape.getRing(j, coords);
+	AreaType area = get_area_type(dbf, i);
+	FG_LOG( FG_GENERAL, FG_DEBUG, "area type = " << (int)area );
 
-	    FG_LOG( FG_GENERAL, FG_DEBUG, "  ring " << j << " = " );
-	    FG_LOG( FG_GENERAL, FG_INFO, n_vertices );
+	FG_LOG( FG_GENERAL, FG_INFO, "  record = " << i 
+		<< " ring = " << 0 );
 
-	    // find min/max of this polygon
-	    min.x = min.y = 200.0;
-	    max.x = max.y = -200.0;
-	    for ( int k = 0; k < n_vertices; k++ ) {
-		if ( coords[k*2+0] < min.x ) { min.x = coords[k*2+0]; }
-		if ( coords[k*2+1] < min.y ) { min.y = coords[k*2+1]; }
-		if ( coords[k*2+0] > max.x ) { max.x = coords[k*2+0]; }
-		if ( coords[k*2+1] > max.y ) { max.y = coords[k*2+1]; }
+	if ( area == MarshArea ) {
+	    // interior of polygon is marsh, holes are water
+
+	    // do main outline first
+	    init_shape(&gpc_shape);
+	    n_vertices = shape.getRing(0, coords);
+	    add_to_shape(n_vertices, coords, &gpc_shape);
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+
+	    // do lakes (individually) next
+	    for (  j = 1; j < shape.numRings(); j++ ) {
+		FG_LOG( FG_GENERAL, FG_INFO, "  record = " << i 
+			<< " ring = " << j );
+		init_shape(&gpc_shape);
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+		process_shape(path, LakeArea, &gpc_shape);
+		free_shape(&gpc_shape);
 	    }
-	    FG_LOG( FG_GENERAL, FG_INFO, "min = " << min.x << "," << min.y
-		    << " max = " << max.x << "," << max.y );
+	} else if ( area == OceanArea ) {
+	    // interior of polygon is ocean, holes are islands
 
-	    // find buckets for min, and max points of convex hull.
-	    // note to self: self, you should think about checking for
-	    // polygons that span the date line
-	    FGBucket b_min(min.x, min.y);
-	    FGBucket b_max(max.x, max.y);
-	    cout << "Bucket min = " << b_min << endl;
-	    cout << "Bucket max = " << b_max << endl;
-	    
-	    if ( b_min == b_max ) {
-		clip_and_write_poly( b_min, n_vertices, coords );
-	    } else {
-		FGBucket b_cur;
-		int dx, dy, i, j;
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == LakeArea ) {
+	    // interior of polygon is lake, holes are islands
 
-		fgBucketDiff(b_min, b_max, &dx, &dy);
-		cout << "airport spans tile boundaries" << endl;
-		cout << "  dx = " << dx << "  dy = " << dy << endl;
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == DryLakeArea ) {
+	    // interior of polygon is dry lake, holes are islands
 
-		if ( (dx > 1) || (dy > 1) ) {
-		    cout << "somethings really wrong!!!!" << endl;
-		    exit(-1);
-		}
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == IntLakeArea ) {
+	    // interior of polygon is intermittent lake, holes are islands
 
-		for ( j = 0; j <= dy; j++ ) {
-		    for ( i = 0; i <= dx; i++ ) {
-			b_cur = fgBucketOffset(min.x, min.y, i, j);
-			clip_and_write_poly( b_cur, n_vertices, coords );
-		    }
-		}
-		// string answer; cin >> answer;
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == ReservoirArea ) {
+	    // interior of polygon is reservoir, holes are islands
+
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == IntReservoirArea ) {
+	    // interior of polygon is intermittent reservoir, holes are islands
+
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == StreamArea ) {
+	    // interior of polygon is stream, holes are islands
+
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == CanalArea ) {
+	    // interior of polygon is canal, holes are islands
+
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == GlacierArea ) {
+	    // interior of polygon is glacier, holes are dry land
+
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == VoidArea ) {
+	    // interior is ????
+
+	    // skip for now
+	    FG_LOG(  FG_GENERAL, FG_ALERT, "Void area ... SKIPPING!" );
+
+	    if ( shape.numRings() > 1 ) {
+		FG_LOG(  FG_GENERAL, FG_ALERT, "  Void area with holes!" );
+		// exit(-1);
 	    }
 
-	    for ( int k = 0; k < n_vertices; k++ ) {
-		lon = coords[k*2+0];
-		lat = coords[k*2+1];
-		FG_LOG( FG_GENERAL, FG_INFO, lon << " " << lat );
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
 	    }
+	    // process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else if ( area == NullArea ) {
+	    // interior is ????
+
+	    // skip for now
+	    FG_LOG(  FG_GENERAL, FG_ALERT, "Null area ... SKIPPING!" );
+
+	    if ( shape.numRings() > 1 ) {
+		FG_LOG(  FG_GENERAL, FG_ALERT, "  Null area with holes!" );
+		// exit(-1);
+	    }
+
+	    init_shape(&gpc_shape);
+	    for (  j = 0; j < shape.numRings(); j++ ) {
+		n_vertices = shape.getRing(j, coords);
+		add_to_shape(n_vertices, coords, &gpc_shape);
+	    }
+	    // process_shape(path, area, &gpc_shape);
+	    free_shape(&gpc_shape);
+	} else {
+	    FG_LOG(  FG_GENERAL, FG_ALERT, "Uknown area!" );
+	    exit(-1);
 	}
     }
 
     return 0;
 }
 
+
 // $Log$
+// Revision 1.3  1999/02/23 01:29:04  curt
+// Additional progress.
+//
 // Revision 1.2  1999/02/19 19:05:18  curt
 // Working on clipping shapes and distributing into buckets.
 //
diff --git a/ShapeFile/names.cxx b/ShapeFile/names.cxx
new file mode 100644
index 000000000..61be113cc
--- /dev/null
+++ b/ShapeFile/names.cxx
@@ -0,0 +1,104 @@
+// names.cxx -- process shapefiles names
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+#include "names.hxx"
+
+
+// return the type of the shapefile record
+AreaType get_area_type(GDBFile *dbf, int rec) {
+    GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
+    GDBFValue *fields;		//an array of field values
+    char* dbf_rec;		//a record containing all the fields
+
+    // grab the meta-information for all the fields
+    // this applies to all the records in the DBF file.
+    // for ( int i = 0; i < dbf->numFields(); i++ ) {
+    //   fdesc[i] = dbf->getFieldDesc(i);
+    //   cout << i << ") " << fdesc[i]->name << endl;
+    // }
+
+    // this is the whole name record
+    dbf_rec = dbf->getRecord( rec );
+
+    // parse it into individual fields
+    if ( dbf_rec ) {
+	fields = dbf->recordDeform( dbf_rec );
+    }
+
+    string area = fields[4].str_v;
+    // strip leading spaces
+    while ( area[0] == ' ' ) {
+	area = area.substr(1, area.length() - 1);
+    }
+    // strip trailing spaces
+    while ( area[area.length() - 1] == ' ' ) {
+	area = area.substr(0, area.length() - 1);
+    }
+    // strip other junk encountered
+    while ( (int)area[area.length() - 1] == 9 ) {
+	area = area.substr(0, area.length() - 1);
+    }
+
+    if ( area == "Swamp or Marsh" ) {
+	return MarshArea;
+    } else if ( area == "Bay  Estuary or Ocean" ) {
+	return OceanArea;
+    } else if ( area == "Lake" ) {
+	return LakeArea;
+    } else if ( area == "Lake   Dry" ) {
+	return DryLakeArea;
+    } else if ( area == "Lake   Intermittent" ) {
+	return IntLakeArea;
+    } else if ( area == "Reservoir" ) {
+	return ReservoirArea;
+    } else if ( area == "Reservoir   Intermittent" ) {
+	return IntReservoirArea;
+    } else if ( area == "Stream" ) {
+	return StreamArea;
+    } else if ( area == "Canal" ) {
+	return CanalArea;
+    } else if ( area == "Glacier" ) {
+	return GlacierArea;
+    } else if ( area == "Void Area" ) {
+	return VoidArea;
+    } else if ( area == "Null" ) {
+	return NullArea;
+    } else {
+	cout << "unknown area = '" << area << "'" << endl;
+	// cout << "area = " << area << endl;
+	for ( int i = 0; i < area.length(); i++ ) {
+	    cout << i << ") " << (int)area[i] << endl;
+	}
+	return UnknownArea;
+    }
+}
+
+
+// $Log$
+// Revision 1.1  1999/02/23 01:29:05  curt
+// Additional progress.
+//
diff --git a/ShapeFile/names.hxx b/ShapeFile/names.hxx
new file mode 100644
index 000000000..b9dafc524
--- /dev/null
+++ b/ShapeFile/names.hxx
@@ -0,0 +1,68 @@
+// names.hxx -- process shapefiles names
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+
+#ifndef _NAMES_HXX
+#define _NAMES_HXX
+
+
+// libgfc.a includes need this bit o' strangeness
+#if defined ( linux )
+#  define _LINUX_
+#endif
+#include <gfc/gadt_polygon.h>
+#include <gfc/gdbf.h>
+#undef E
+#undef DEG_TO_RAD
+#undef RAD_TO_DEG
+
+
+// Posible shape file types
+enum AreaType {
+    MarshArea = 0,
+    OceanArea = 1,
+    LakeArea = 2,
+    DryLakeArea = 3,
+    IntLakeArea = 4,
+    ReservoirArea = 5,
+    IntReservoirArea = 6,
+    StreamArea = 7,
+    CanalArea = 8,
+    GlacierArea = 9,
+    VoidArea = 9997,
+    NullArea = 9998,
+    UnknownArea = 9999
+};
+
+
+// return the type of the shapefile record
+AreaType get_area_type(GDBFile *dbf, int rec);
+
+
+#endif // _NAMES_HXX
+
+
+// $Log$
+// Revision 1.1  1999/02/23 01:29:05  curt
+// Additional progress.
+//
diff --git a/ShapeFile/shape.cxx b/ShapeFile/shape.cxx
new file mode 100644
index 000000000..1f2dec60c
--- /dev/null
+++ b/ShapeFile/shape.cxx
@@ -0,0 +1,258 @@
+// shape.cxx -- shape/gpc utils
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+#include <Bucket/newbucket.hxx>
+#include <Debug/logstream.hxx>
+
+#include "names.hxx"
+#include "shape.hxx"
+
+
+#define FG_MAX_VERTICES 100000
+static gpc_vertex_list v_list;
+
+
+class point2d {
+public:
+    double x, y;
+};
+
+
+static void clip_and_write_poly( string root, AreaType area, 
+				 FGBucket b, gpc_polygon *shape ) {
+    point2d c, min, max;
+    c.x = b.get_center_lon();
+    c.y = b.get_center_lat();
+    double span = bucket_span(c.y);
+    gpc_polygon base, result;
+    char tmp[256];
+
+    // calculate bucket dimensions
+    if ( (c.y >= -89.0) && (c.y < 89.0) ) {
+	min.x = c.x - span / 2.0;
+	max.x = c.x + span / 2.0;
+	min.y = c.y - FG_HALF_BUCKET_SPAN;
+	max.y = c.y + FG_HALF_BUCKET_SPAN;
+    } else if ( c.y < -89.0) {
+	min.x = -90.0;
+	max.x = -89.0;
+	min.y = -180.0;
+	max.y = 180.0;
+    } else if ( c.y >= 89.0) {
+	min.x = 89.0;
+	max.x = 90.0;
+	min.y = -180.0;
+	max.y = 180.0;
+    } else {
+	FG_LOG ( FG_GENERAL, FG_ALERT, 
+		 "Out of range latitude in clip_and_write_poly() = " << c.y );
+    }
+
+    FG_LOG( FG_GENERAL, FG_INFO, "  (" << min.x << "," << min.y << ") ("
+	    << max.x << "," << max.y << ")" );
+
+    // set up clipping tile
+    v_list.vertex[0].x = min.x;
+    v_list.vertex[0].y = min.y;
+
+    v_list.vertex[1].x = max.x;
+    v_list.vertex[1].y = min.y;
+
+    v_list.vertex[2].x = max.x;
+    v_list.vertex[2].y = max.y;
+
+    v_list.vertex[3].x = min.x;
+    v_list.vertex[3].y = max.y;
+
+    v_list.num_vertices = 4;
+
+    base.num_contours = 0;
+    base.contour = NULL;
+    gpc_add_contour( &base, &v_list );
+
+    // FG_LOG( FG_GENERAL, FG_DEBUG, "base = 4 vertices" );
+
+    /*
+    FILE *bfp= fopen("base", "w");
+    gpc_write_polygon(bfp, &base);
+    fclose(bfp);
+    */
+
+    gpc_polygon_clip(GPC_INT, &base, shape, &result);
+
+    if ( result.num_contours > 0 ) {
+	long int index = b.gen_index();
+	string path = root + "/Scenery/" + b.gen_base_path();
+	string command = "mkdir -p " + path;
+	system( command.c_str() );
+
+	sprintf(tmp, "%ld", index);
+	string polyfile = path + "/" + tmp;
+
+	if ( area == MarshArea ) {
+	    polyfile += ".marsh";
+	} else if ( area == OceanArea ) {
+	    polyfile += ".ocean";
+	} else if ( area == LakeArea ) {
+	    polyfile += ".lake";
+	} else if ( area == DryLakeArea ) {
+	    polyfile += ".drylake";
+	} else if ( area == IntLakeArea ) {
+	    polyfile += ".intlake";
+	} else if ( area == ReservoirArea ) {
+	    polyfile += ".reservoir";
+	} else if ( area == IntReservoirArea ) {
+	    polyfile += ".intreservoir";
+	} else if ( area == StreamArea ) {
+	    polyfile += ".stream";
+	} else if ( area == CanalArea ) {
+	    polyfile += ".canal";
+	} else if ( area == GlacierArea ) {
+	    polyfile += ".glacier";
+	} else {
+	    cout << "unknown area type in clip_and_write_poly()!" << endl;
+	    exit(-1);
+	}
+	
+	FILE *rfp= fopen(polyfile.c_str(), "w");
+	gpc_write_polygon(rfp, &result);
+	fclose(rfp);
+    }
+
+    gpc_free_polygon(&base);
+    gpc_free_polygon(&result);
+}
+
+
+// Initialize structure we use to create polygons for the gpc library
+bool shape_utils_init() {
+    v_list.num_vertices = 0;
+    v_list.vertex = new gpc_vertex[FG_MAX_VERTICES];;
+
+    return true;
+}
+
+
+// initialize a gpc_polygon
+void init_shape(gpc_polygon *shape) {
+    shape->num_contours = 0;
+    shape->contour = NULL;
+}
+
+
+// make a gpc_polygon
+void add_to_shape(int count, double *coords, gpc_polygon *shape) {
+    
+    for ( int i = 0; i < count; i++ ) {
+	v_list.vertex[i].x = coords[i*2+0];
+	v_list.vertex[i].y = coords[i*2+1];
+    }
+
+    v_list.num_vertices = count;
+    gpc_add_contour( shape, &v_list );
+}
+
+
+// process shape (write polygon to all intersecting tiles)
+void process_shape(string path, AreaType area, gpc_polygon *gpc_shape) {
+    point2d min, max;
+    int i, j;
+
+    min.x = min.y = 200.0;
+    max.x = max.y = -200.0;
+
+    // find min/max of polygon
+    for ( i = 0; i < gpc_shape->num_contours; i++ ) {
+	for ( j = 0; j < gpc_shape->contour[i].num_vertices; j++ ) {
+	    double x = gpc_shape->contour[i].vertex[j].x;
+	    double y = gpc_shape->contour[i].vertex[j].y;
+
+	    if ( x < min.x ) { min.x = x; }
+	    if ( y < min.y ) { min.y = y; }
+	    if ( x > max.x ) { max.x = x; }
+	    if ( y > max.y ) { max.y = y; }
+	}
+    }
+
+    /*
+    FILE *sfp= fopen("shape", "w");
+    gpc_write_polygon(sfp, gpc_shape);
+    fclose(sfp);
+    exit(-1);
+    */
+	
+    FG_LOG( FG_GENERAL, FG_INFO, "  min = " << min.x << "," << min.y
+	    << " max = " << max.x << "," << max.y );
+
+    // find buckets for min, and max points of convex hull.
+    // note to self: self, you should think about checking for
+    // polygons that span the date line
+    FGBucket b_min(min.x, min.y);
+    FGBucket b_max(max.x, max.y);
+    FG_LOG( FG_GENERAL, FG_INFO, "  Bucket min = " << b_min );
+    FG_LOG( FG_GENERAL, FG_INFO, "  Bucket max = " << b_max );
+	    
+    if ( b_min == b_max ) {
+	clip_and_write_poly( path, area, b_min, gpc_shape );
+    } else {
+	FGBucket b_cur;
+	int dx, dy, i, j;
+	    
+	fgBucketDiff(b_min, b_max, &dx, &dy);
+	FG_LOG( FG_GENERAL, FG_INFO, 
+		"  polygon spans tile boundaries" );
+	FG_LOG( FG_GENERAL, FG_INFO, "  dx = " << dx 
+		<< "  dy = " << dy );
+
+	if ( (dx > 100) || (dy > 100) ) {
+	    FG_LOG( FG_GENERAL, FG_ALERT, 
+		    "somethings really wrong!!!!" );
+	    exit(-1);
+	}
+
+	for ( j = 0; j <= dy; j++ ) {
+	    for ( i = 0; i <= dx; i++ ) {
+		b_cur = fgBucketOffset(min.x, min.y, i, j);
+		clip_and_write_poly( path, area, b_cur, gpc_shape );
+	    }
+	}
+	// string answer; cin >> answer;
+    }
+}
+
+
+// free a gpc_polygon
+void free_shape(gpc_polygon *shape) {
+    gpc_free_polygon(shape);
+}
+
+
+// $Log$
+// Revision 1.1  1999/02/23 01:29:06  curt
+// Additional progress.
+//
diff --git a/ShapeFile/shape.hxx b/ShapeFile/shape.hxx
new file mode 100644
index 000000000..ea8bcb5f5
--- /dev/null
+++ b/ShapeFile/shape.hxx
@@ -0,0 +1,61 @@
+// shape.hxx -- shape/gpc utils
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _SHAPE_HXX
+#define _SHAPE_HXX
+
+
+// include Generic Polygon Clipping Library
+extern "C" {
+#include <gpc.h>
+}
+
+#include "names.hxx"
+
+
+// Initialize structure we use to create polygons for the gpc library
+// this must be called once from main for any program that uses this library
+bool shape_utils_init();
+
+
+// initialize a gpc_polygon
+void init_shape(gpc_polygon *shape);
+
+// make a gpc_polygon
+void add_to_shape(int count, double *coords, gpc_polygon *shape);
+
+// process shape (write polygon to all intersecting tiles)
+void process_shape(string path, AreaType area, gpc_polygon *gpc_shape);
+
+// free a gpc_polygon
+void free_shape(gpc_polygon *shape);
+
+
+#endif // _SHAPE_HXX
+
+
+// $Log$
+// Revision 1.1  1999/02/23 01:29:06  curt
+// Additional progress.
+//

From ad34c1e4e4fe7870d0b99a268879935bfb09e2d2 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Feb 1999 21:30:24 +0000
Subject: [PATCH 187/283] Initial revision.

---
 Polygon/Makefile.am |   7 +++
 Polygon/index.cxx   |  76 +++++++++++++++++++++++
 Polygon/index.hxx   |  48 ++++++++++++++
 Polygon/names.cxx   | 148 ++++++++++++++++++++++++++++++++++++++++++++
 Polygon/names.hxx   |  76 +++++++++++++++++++++++
 5 files changed, 355 insertions(+)
 create mode 100644 Polygon/Makefile.am
 create mode 100644 Polygon/index.cxx
 create mode 100644 Polygon/index.hxx
 create mode 100644 Polygon/names.cxx
 create mode 100644 Polygon/names.hxx

diff --git a/Polygon/Makefile.am b/Polygon/Makefile.am
new file mode 100644
index 000000000..caa4c59be
--- /dev/null
+++ b/Polygon/Makefile.am
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = libPolygon.a
+
+libPolygon_a_SOURCES = \
+	index.cxx index.hxx \
+	names.cxx names.hxx
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
diff --git a/Polygon/index.cxx b/Polygon/index.cxx
new file mode 100644
index 000000000..a467c0ba6
--- /dev/null
+++ b/Polygon/index.cxx
@@ -0,0 +1,76 @@
+// index.cxx -- routines to handle a unique/persistant integer polygon index
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+#include <stdio.h>
+
+#include "index.hxx"
+
+
+static int poly_index;
+static string poly_path;
+
+
+// initialize the unique polygon index counter stored in path
+bool poly_index_init( string path ) {
+    poly_path = path;
+
+    FILE *fp = fopen( poly_path.c_str(), "r" );
+
+    if ( fp == NULL ) {
+	cout << "Error cannot open " << poly_path << endl;
+	poly_index = 0;
+	return false;
+    }
+
+    fscanf( fp, "%d", &poly_index );
+
+    fclose( fp );
+}
+
+
+// increment the persistant counter and return the next poly_index
+int poly_index_next() {
+    ++poly_index;
+
+    FILE *fp = fopen( poly_path.c_str(), "w" );
+
+    if ( fp == NULL ) {
+	cout << "Error cannot open " << poly_path << " for writing" << endl;
+    }
+
+    fprintf( fp, "%d\n", poly_index );
+
+    fclose( fp );
+
+    return poly_index;
+}
+
+
+// $Log$
+// Revision 1.1  1999/02/25 21:30:24  curt
+// Initial revision.
+//
diff --git a/Polygon/index.hxx b/Polygon/index.hxx
new file mode 100644
index 000000000..ddc8acb6f
--- /dev/null
+++ b/Polygon/index.hxx
@@ -0,0 +1,48 @@
+// index.cxx -- routines to handle a unique/persistant integer polygon index
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _INDEX_HXX
+#define _INDEX_HXX
+
+
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+
+// initialize the unique polygon index counter stored in path
+bool poly_index_init( string path );
+
+// increment the persistant counter and return the next poly_index
+int poly_index_next();
+
+
+
+#endif // _INDEX_HXX
+
+
+// $Log$
+// Revision 1.1  1999/02/25 21:30:24  curt
+// Initial revision.
+//
diff --git a/Polygon/names.cxx b/Polygon/names.cxx
new file mode 100644
index 000000000..d01dd9b8d
--- /dev/null
+++ b/Polygon/names.cxx
@@ -0,0 +1,148 @@
+// names.cxx -- process shapefiles names
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+#include "names.hxx"
+
+
+// return the type of the shapefile record
+AreaType get_area_type(GDBFile *dbf, int rec) {
+    GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
+    GDBFValue *fields;		//an array of field values
+    char* dbf_rec;		//a record containing all the fields
+
+    // grab the meta-information for all the fields
+    // this applies to all the records in the DBF file.
+    // for ( int i = 0; i < dbf->numFields(); i++ ) {
+    //   fdesc[i] = dbf->getFieldDesc(i);
+    //   cout << i << ") " << fdesc[i]->name << endl;
+    // }
+
+    // this is the whole name record
+    dbf_rec = dbf->getRecord( rec );
+
+    // parse it into individual fields
+    if ( dbf_rec ) {
+	fields = dbf->recordDeform( dbf_rec );
+    }
+
+    string area = fields[4].str_v;
+    // strip leading spaces
+    while ( area[0] == ' ' ) {
+	area = area.substr(1, area.length() - 1);
+    }
+    // strip trailing spaces
+    while ( area[area.length() - 1] == ' ' ) {
+	area = area.substr(0, area.length() - 1);
+    }
+    // strip other junk encountered
+    while ( (int)area[area.length() - 1] == 9 ) {
+	area = area.substr(0, area.length() - 1);
+    }
+
+    if ( area == "AirportKeep" ) {
+	return AirportKeepArea;
+    } else if ( area == "AirportIgnore" ) {
+	return AirportIgnoreArea;
+    } else if ( area == "Swamp or Marsh" ) {
+	return MarshArea;
+    } else if ( area == "Bay  Estuary or Ocean" ) {
+	return OceanArea;
+    } else if ( area == "Lake" ) {
+	return LakeArea;
+    } else if ( area == "Lake   Dry" ) {
+	return DryLakeArea;
+    } else if ( area == "Lake   Intermittent" ) {
+	return IntLakeArea;
+    } else if ( area == "Reservoir" ) {
+	return ReservoirArea;
+    } else if ( area == "Reservoir   Intermittent" ) {
+	return IntReservoirArea;
+    } else if ( area == "Stream" ) {
+	return StreamArea;
+    } else if ( area == "Canal" ) {
+	return CanalArea;
+    } else if ( area == "Glacier" ) {
+	return GlacierArea;
+    } else if ( area == "Void Area" ) {
+	return VoidArea;
+    } else if ( area == "Null" ) {
+	return NullArea;
+    } else {
+	cout << "unknown area = '" << area << "'" << endl;
+	// cout << "area = " << area << endl;
+	for ( int i = 0; i < area.length(); i++ ) {
+	    cout << i << ") " << (int)area[i] << endl;
+	}
+	return UnknownArea;
+    }
+}
+
+
+// return text form of area name
+string get_area_name( AreaType area ) {
+    if ( area == AirportKeepArea ) {
+	return "AirportKeep";
+    } else if ( area == AirportIgnoreArea ) {
+	return "AirportIgnore";
+    } else if ( area == MarshArea ) {
+	return "Marsh";
+    } else if ( area == OceanArea ) {
+	return "Ocean";
+    } else if ( area == LakeArea ) {
+	return "Lake";
+    } else if ( area == DryLakeArea ) {
+	return "DryLake";
+    } else if ( area == IntLakeArea ) {
+	return "IntermittentLake";
+    } else if ( area == ReservoirArea ) {
+	return "Reservoir";
+    } else if ( area == IntReservoirArea ) {
+	return "IntermittentReservoir";
+    } else if ( area == StreamArea ) {
+	return "Stream";
+    } else if ( area == CanalArea ) {
+	return "Canal";
+    } else if ( area == GlacierArea ) {
+	return "Glacier";
+    } else if ( area == VoidArea ) {
+	return "VoidArea";
+    } else if ( area == NullArea ) {
+	return "Null";
+    } else {
+	cout << "unknown area code = " << (int)area << endl;
+	return "Unknown";
+    }
+}
+
+
+// $Log$
+// Revision 1.1  1999/02/25 21:30:24  curt
+// Initial revision.
+//
+// Revision 1.1  1999/02/23 01:29:05  curt
+// Additional progress.
+//
diff --git a/Polygon/names.hxx b/Polygon/names.hxx
new file mode 100644
index 000000000..50222d104
--- /dev/null
+++ b/Polygon/names.hxx
@@ -0,0 +1,76 @@
+// names.hxx -- process shapefiles names
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+
+#ifndef _NAMES_HXX
+#define _NAMES_HXX
+
+
+// libgfc.a includes need this bit o' strangeness
+#if defined ( linux )
+#  define _LINUX_
+#endif
+#include <gfc/gadt_polygon.h>
+#include <gfc/gdbf.h>
+#undef E
+#undef DEG_TO_RAD
+#undef RAD_TO_DEG
+
+
+// Posible shape file types
+enum AreaType {
+    AirportKeepArea = 0,
+    AirportIgnoreArea = 1,
+    MarshArea = 2,
+    OceanArea = 3,
+    LakeArea = 4,
+    DryLakeArea = 5,
+    IntLakeArea = 6,
+    ReservoirArea = 7,
+    IntReservoirArea = 8,
+    StreamArea = 9,
+    CanalArea = 10,
+    GlacierArea = 11,
+    VoidArea = 9997,
+    NullArea = 9998,
+    UnknownArea = 9999
+};
+
+
+// return the type of the shapefile record
+AreaType get_area_type(GDBFile *dbf, int rec);
+
+// return text form of area name
+string get_area_name( AreaType area );
+
+
+#endif // _NAMES_HXX
+
+
+// $Log$
+// Revision 1.1  1999/02/25 21:30:24  curt
+// Initial revision.
+//
+// Revision 1.1  1999/02/23 01:29:05  curt
+// Additional progress.
+//

From 8de225f5bff36deb953d59067118c961cbf84445 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Feb 1999 21:31:04 +0000
Subject: [PATCH 188/283] First working version???

---
 ShapeFile/Makefile.am |   8 ++--
 ShapeFile/main.cxx    |  18 ++++++--
 ShapeFile/names.cxx   | 104 ------------------------------------------
 ShapeFile/names.hxx   |  68 ---------------------------
 ShapeFile/shape.cxx   |  58 +++++++++++------------
 ShapeFile/shape.hxx   |   5 +-
 6 files changed, 49 insertions(+), 212 deletions(-)
 delete mode 100644 ShapeFile/names.cxx
 delete mode 100644 ShapeFile/names.hxx

diff --git a/ShapeFile/Makefile.am b/ShapeFile/Makefile.am
index c0c4b666e..6aec7fdec 100644
--- a/ShapeFile/Makefile.am
+++ b/ShapeFile/Makefile.am
@@ -1,12 +1,14 @@
 bin_PROGRAMS = shape-decode
 
-shape_decode_SOURCES = names.cxx names.hxx main.cxx shape.cxx shape.hxx
+shape_decode_SOURCES = main.cxx shape.cxx shape.hxx
 
-shape_decode_LDADD = $(top_builddir)/Lib/Debug/libDebug.a \
+shape_decode_LDADD = \
+	$(top_builddir)/Tools/Polygon/libPolygon.a \
+	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	-lgfc -lgpc
 
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
index 3af9438c6..58ebf52a1 100644
--- a/ShapeFile/main.cxx
+++ b/ShapeFile/main.cxx
@@ -48,7 +48,8 @@ extern "C" {
 
 #include <Debug/logstream.hxx>
 
-#include "names.hxx"
+#include <Polygon/index.hxx>
+#include <Polygon/names.hxx>
 #include "shape.hxx"
 
 
@@ -60,12 +61,17 @@ int main( int argc, char **argv ) {
 
     if ( argc != 3 ) {
 	FG_LOG( FG_GENERAL, FG_ALERT, "Usage: " << argv[0] 
-		<< " <shapefile> <workdir>" );
+		<< " <shape_file> <work_dir>" );
 	exit(-1);
     }
 
     FG_LOG( FG_GENERAL, FG_DEBUG, "Opening " << argv[1] << " for reading." );
 
+    // initialize persistant polygon counter
+    string counter_file = argv[2];
+    counter_file += "/polygon.counter";
+    poly_index_init( counter_file );
+
     // initialize structure for building gpc polygons
     shape_utils_init();
 
@@ -85,14 +91,15 @@ int main( int argc, char **argv ) {
 	exit(-1);
     }
 
-    for ( i = 16473; i < sf->numRecords(); i++ ) {
+    for ( i = 0; i < sf->numRecords(); i++ ) {
 	//fetch i-th record (shape)
 	sf->getShapeRec(i, &shape); 
 	FG_LOG( FG_GENERAL, FG_DEBUG, "Record = " << i << "  rings = " 
 		<< shape.numRings() );
 
 	AreaType area = get_area_type(dbf, i);
-	FG_LOG( FG_GENERAL, FG_DEBUG, "area type = " << (int)area );
+	FG_LOG( FG_GENERAL, FG_DEBUG, "area type = " << get_area_name(area) 
+		<< " (" << (int)area << ")" );
 
 	FG_LOG( FG_GENERAL, FG_INFO, "  record = " << i 
 		<< " ring = " << 0 );
@@ -254,6 +261,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.4  1999/02/25 21:31:05  curt
+// First working version???
+//
 // Revision 1.3  1999/02/23 01:29:04  curt
 // Additional progress.
 //
diff --git a/ShapeFile/names.cxx b/ShapeFile/names.cxx
deleted file mode 100644
index 61be113cc..000000000
--- a/ShapeFile/names.cxx
+++ /dev/null
@@ -1,104 +0,0 @@
-// names.cxx -- process shapefiles names
-//
-// Written by Curtis Olson, started February 1999.
-//
-// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-// (Log is kept at end of this file)
- 
-#include <Include/compiler.h>
-
-#include STL_STRING
-
-#include "names.hxx"
-
-
-// return the type of the shapefile record
-AreaType get_area_type(GDBFile *dbf, int rec) {
-    GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
-    GDBFValue *fields;		//an array of field values
-    char* dbf_rec;		//a record containing all the fields
-
-    // grab the meta-information for all the fields
-    // this applies to all the records in the DBF file.
-    // for ( int i = 0; i < dbf->numFields(); i++ ) {
-    //   fdesc[i] = dbf->getFieldDesc(i);
-    //   cout << i << ") " << fdesc[i]->name << endl;
-    // }
-
-    // this is the whole name record
-    dbf_rec = dbf->getRecord( rec );
-
-    // parse it into individual fields
-    if ( dbf_rec ) {
-	fields = dbf->recordDeform( dbf_rec );
-    }
-
-    string area = fields[4].str_v;
-    // strip leading spaces
-    while ( area[0] == ' ' ) {
-	area = area.substr(1, area.length() - 1);
-    }
-    // strip trailing spaces
-    while ( area[area.length() - 1] == ' ' ) {
-	area = area.substr(0, area.length() - 1);
-    }
-    // strip other junk encountered
-    while ( (int)area[area.length() - 1] == 9 ) {
-	area = area.substr(0, area.length() - 1);
-    }
-
-    if ( area == "Swamp or Marsh" ) {
-	return MarshArea;
-    } else if ( area == "Bay  Estuary or Ocean" ) {
-	return OceanArea;
-    } else if ( area == "Lake" ) {
-	return LakeArea;
-    } else if ( area == "Lake   Dry" ) {
-	return DryLakeArea;
-    } else if ( area == "Lake   Intermittent" ) {
-	return IntLakeArea;
-    } else if ( area == "Reservoir" ) {
-	return ReservoirArea;
-    } else if ( area == "Reservoir   Intermittent" ) {
-	return IntReservoirArea;
-    } else if ( area == "Stream" ) {
-	return StreamArea;
-    } else if ( area == "Canal" ) {
-	return CanalArea;
-    } else if ( area == "Glacier" ) {
-	return GlacierArea;
-    } else if ( area == "Void Area" ) {
-	return VoidArea;
-    } else if ( area == "Null" ) {
-	return NullArea;
-    } else {
-	cout << "unknown area = '" << area << "'" << endl;
-	// cout << "area = " << area << endl;
-	for ( int i = 0; i < area.length(); i++ ) {
-	    cout << i << ") " << (int)area[i] << endl;
-	}
-	return UnknownArea;
-    }
-}
-
-
-// $Log$
-// Revision 1.1  1999/02/23 01:29:05  curt
-// Additional progress.
-//
diff --git a/ShapeFile/names.hxx b/ShapeFile/names.hxx
deleted file mode 100644
index b9dafc524..000000000
--- a/ShapeFile/names.hxx
+++ /dev/null
@@ -1,68 +0,0 @@
-// names.hxx -- process shapefiles names
-//
-// Written by Curtis Olson, started February 1999.
-//
-// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-// (Log is kept at end of this file)
- 
-
-#ifndef _NAMES_HXX
-#define _NAMES_HXX
-
-
-// libgfc.a includes need this bit o' strangeness
-#if defined ( linux )
-#  define _LINUX_
-#endif
-#include <gfc/gadt_polygon.h>
-#include <gfc/gdbf.h>
-#undef E
-#undef DEG_TO_RAD
-#undef RAD_TO_DEG
-
-
-// Posible shape file types
-enum AreaType {
-    MarshArea = 0,
-    OceanArea = 1,
-    LakeArea = 2,
-    DryLakeArea = 3,
-    IntLakeArea = 4,
-    ReservoirArea = 5,
-    IntReservoirArea = 6,
-    StreamArea = 7,
-    CanalArea = 8,
-    GlacierArea = 9,
-    VoidArea = 9997,
-    NullArea = 9998,
-    UnknownArea = 9999
-};
-
-
-// return the type of the shapefile record
-AreaType get_area_type(GDBFile *dbf, int rec);
-
-
-#endif // _NAMES_HXX
-
-
-// $Log$
-// Revision 1.1  1999/02/23 01:29:05  curt
-// Additional progress.
-//
diff --git a/ShapeFile/shape.cxx b/ShapeFile/shape.cxx
index 1f2dec60c..ae3e1432f 100644
--- a/ShapeFile/shape.cxx
+++ b/ShapeFile/shape.cxx
@@ -29,7 +29,8 @@
 #include <Bucket/newbucket.hxx>
 #include <Debug/logstream.hxx>
 
-#include "names.hxx"
+#include <Polygon/index.hxx>
+#include <Polygon/names.hxx>
 #include "shape.hxx"
 
 
@@ -43,14 +44,14 @@ public:
 };
 
 
-static void clip_and_write_poly( string root, AreaType area, 
+static void clip_and_write_poly( string root, int p_index, AreaType area, 
 				 FGBucket b, gpc_polygon *shape ) {
     point2d c, min, max;
     c.x = b.get_center_lon();
     c.y = b.get_center_lat();
     double span = bucket_span(c.y);
     gpc_polygon base, result;
-    char tmp[256];
+    char tile_name[256], poly_index[256];
 
     // calculate bucket dimensions
     if ( (c.y >= -89.0) && (c.y < 89.0) ) {
@@ -106,42 +107,28 @@ static void clip_and_write_poly( string root, AreaType area,
     gpc_polygon_clip(GPC_INT, &base, shape, &result);
 
     if ( result.num_contours > 0 ) {
-	long int index = b.gen_index();
+	long int t_index = b.gen_index();
 	string path = root + "/Scenery/" + b.gen_base_path();
 	string command = "mkdir -p " + path;
 	system( command.c_str() );
 
-	sprintf(tmp, "%ld", index);
-	string polyfile = path + "/" + tmp;
+	sprintf( tile_name, "%ld", t_index );
+	string polyfile = path + "/" + tile_name;
 
-	if ( area == MarshArea ) {
-	    polyfile += ".marsh";
-	} else if ( area == OceanArea ) {
-	    polyfile += ".ocean";
-	} else if ( area == LakeArea ) {
-	    polyfile += ".lake";
-	} else if ( area == DryLakeArea ) {
-	    polyfile += ".drylake";
-	} else if ( area == IntLakeArea ) {
-	    polyfile += ".intlake";
-	} else if ( area == ReservoirArea ) {
-	    polyfile += ".reservoir";
-	} else if ( area == IntReservoirArea ) {
-	    polyfile += ".intreservoir";
-	} else if ( area == StreamArea ) {
-	    polyfile += ".stream";
-	} else if ( area == CanalArea ) {
-	    polyfile += ".canal";
-	} else if ( area == GlacierArea ) {
-	    polyfile += ".glacier";
-	} else {
+	sprintf( poly_index, "%d", p_index );
+	polyfile += ".";
+	polyfile += poly_index;
+
+	string poly_type = get_area_name( area );
+	if ( poly_type == "Unknown" ) {
 	    cout << "unknown area type in clip_and_write_poly()!" << endl;
 	    exit(-1);
 	}
 	
-	FILE *rfp= fopen(polyfile.c_str(), "w");
-	gpc_write_polygon(rfp, &result);
-	fclose(rfp);
+	FILE *rfp= fopen( polyfile.c_str(), "w" );
+	fprintf( rfp, "%s\n", poly_type.c_str() );
+	gpc_write_polygon( rfp, &result );
+	fclose( rfp );
     }
 
     gpc_free_polygon(&base);
@@ -181,6 +168,7 @@ void add_to_shape(int count, double *coords, gpc_polygon *shape) {
 // process shape (write polygon to all intersecting tiles)
 void process_shape(string path, AreaType area, gpc_polygon *gpc_shape) {
     point2d min, max;
+    int index;
     int i, j;
 
     min.x = min.y = 200.0;
@@ -206,6 +194,9 @@ void process_shape(string path, AreaType area, gpc_polygon *gpc_shape) {
     exit(-1);
     */
 	
+    // get next polygon index
+    index = poly_index_next();
+
     FG_LOG( FG_GENERAL, FG_INFO, "  min = " << min.x << "," << min.y
 	    << " max = " << max.x << "," << max.y );
 
@@ -218,7 +209,7 @@ void process_shape(string path, AreaType area, gpc_polygon *gpc_shape) {
     FG_LOG( FG_GENERAL, FG_INFO, "  Bucket max = " << b_max );
 	    
     if ( b_min == b_max ) {
-	clip_and_write_poly( path, area, b_min, gpc_shape );
+	clip_and_write_poly( path, index, area, b_min, gpc_shape );
     } else {
 	FGBucket b_cur;
 	int dx, dy, i, j;
@@ -238,7 +229,7 @@ void process_shape(string path, AreaType area, gpc_polygon *gpc_shape) {
 	for ( j = 0; j <= dy; j++ ) {
 	    for ( i = 0; i <= dx; i++ ) {
 		b_cur = fgBucketOffset(min.x, min.y, i, j);
-		clip_and_write_poly( path, area, b_cur, gpc_shape );
+		clip_and_write_poly( path, index, area, b_cur, gpc_shape );
 	    }
 	}
 	// string answer; cin >> answer;
@@ -253,6 +244,9 @@ void free_shape(gpc_polygon *shape) {
 
 
 // $Log$
+// Revision 1.2  1999/02/25 21:31:08  curt
+// First working version???
+//
 // Revision 1.1  1999/02/23 01:29:06  curt
 // Additional progress.
 //
diff --git a/ShapeFile/shape.hxx b/ShapeFile/shape.hxx
index ea8bcb5f5..6a59b77e3 100644
--- a/ShapeFile/shape.hxx
+++ b/ShapeFile/shape.hxx
@@ -31,7 +31,7 @@ extern "C" {
 #include <gpc.h>
 }
 
-#include "names.hxx"
+#include <Polygon/names.hxx>
 
 
 // Initialize structure we use to create polygons for the gpc library
@@ -56,6 +56,9 @@ void free_shape(gpc_polygon *shape);
 
 
 // $Log$
+// Revision 1.2  1999/02/25 21:31:09  curt
+// First working version???
+//
 // Revision 1.1  1999/02/23 01:29:06  curt
 // Additional progress.
 //

From 78bca880ea1590f767ed4d86a87b70f6aadaecac Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Feb 1999 21:32:47 +0000
Subject: [PATCH 189/283] Modified to adhere to new polygon naming convention,
 and also to read the new Robin Peel aiport format.

---
 GenAirports/Makefile.am     |   7 +-
 GenAirports/convex_hull.cxx |   8 +-
 GenAirports/main.cxx        | 151 ++++++++++++++++++++++++++++--------
 3 files changed, 130 insertions(+), 36 deletions(-)

diff --git a/GenAirports/Makefile.am b/GenAirports/Makefile.am
index 70e1c076c..d1d6aaca5 100644
--- a/GenAirports/Makefile.am
+++ b/GenAirports/Makefile.am
@@ -33,17 +33,22 @@ genapts_SOURCES = \
 	point2d.cxx point2d.hxx
 
 genapts_LDADD = \
+	$(top_builddir)/Tools/Polygon/libPolygon.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.5  1999/02/25 21:32:47  curt
+# Modified to adhere to new polygon naming convention, and also to read the
+# new Robin Peel aiport format.
+#
 # Revision 1.4  1999/02/11 01:10:50  curt
 # Start of scenery revamp project.
 #
diff --git a/GenAirports/convex_hull.cxx b/GenAirports/convex_hull.cxx
index 5905c4922..0cdff1dcb 100644
--- a/GenAirports/convex_hull.cxx
+++ b/GenAirports/convex_hull.cxx
@@ -178,8 +178,8 @@ list_container convex_hull( list_container input_list )
     // double check list size ... this should never fail because a
     // single runway will always generate four points.
     if ( radians_map.size() < 3 ) {
-	// printf("convex hull not possible with < 3 points\n");
-	exit(0);
+	cout << "convex hull not possible with < 3 points" << endl;
+	exit(-1);
     }
 
     // ensure that we run the while loop at least once
@@ -256,6 +256,10 @@ list_container convex_hull( list_container input_list )
 
 
 // $Log$
+// Revision 1.5  1999/02/25 21:32:48  curt
+// Modified to adhere to new polygon naming convention, and also to read the
+// new Robin Peel aiport format.
+//
 // Revision 1.4  1998/09/17 18:40:42  curt
 // Debug message tweaks.
 //
diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index 47297b91b..77b9607c3 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -42,24 +42,29 @@
 #include <Debug/logstream.hxx>
 #include <Include/fg_constants.h>
 #include <Misc/fgstream.hxx>
+#include <Polygon/index.hxx>
 
 #include "area.hxx"
 #include "convex_hull.hxx"
 
 
 // write out airport data
-void write_airport( list_container hull_list, FGBucket b, const string& root,
-		    const bool cut_and_keep ) {
-    char tmp[256];
+void write_airport( int p_index, list_container hull_list, FGBucket b, 
+		    const string& root, const bool cut_and_keep ) {
+    char tile_name[256], poly_index[256];
 
-    long int index = b.gen_index();
+    long int b_index = b.gen_index();
     string base = b.gen_base_path();
     string path = root + "/Scenery/" + base;
     string command = "mkdir -p " + path;
     system( command.c_str() );
 
-    sprintf(tmp, "%ld", index);
-    string aptfile = path + "/" + tmp + ".apt";
+    sprintf(tile_name, "%ld", b_index);
+    string aptfile = path + "/" + tile_name;
+
+    sprintf( poly_index, "%d", p_index );
+    aptfile += ".";
+    aptfile += poly_index;
     cout << "apt file = " << aptfile << endl;
 
     FILE *fd;
@@ -69,9 +74,9 @@ void write_airport( list_container hull_list, FGBucket b, const string& root,
     }
 
     if ( cut_and_keep ) {
-	fprintf( fd, "cut_and_keep\n" );
+	fprintf( fd, "AirportKeep\n" );
     } else {
-	fprintf( fd, "cut_and_ignore\n" );
+	fprintf( fd, "AirportIgnore\n" );
     }
     fprintf( fd, "%d\n", hull_list.size() );
     // write perimeter polygon
@@ -86,32 +91,77 @@ void write_airport( list_container hull_list, FGBucket b, const string& root,
 
 
 // process and airport + runway list
-void process_airport( string last_airport, list < string > & runway_list,
+void process_airport( string airport, list < string > & runway_list,
 		      const string& root ) {
     list_container rwy_list, apt_list, hull_list;
     list_iterator current, last;
 
-    string line_str;
-    double lon, lat;
-    // int i;
-    int count;
+    // parse main airport information
+    int elev;
+
+    cout << airport << endl;
+    string apt_type = airport.substr(0, 1);
+    string apt_code = airport.substr(2, 4);
+    string apt_lat = airport.substr(7, 10);
+    string apt_lon = airport.substr(18, 11);
+    string apt_elev = airport.substr(30, 5);
+    sscanf( apt_elev.c_str(), "%d", &elev );
+    string apt_use = airport.substr(36, 1);
+    string apt_twr = airport.substr(37, 1);
+    string apt_bldg = airport.substr(38, 1);
+    string apt_name = airport.substr(40);
+
+    /*
+    cout << "  type = " << apt_type << endl;
+    cout << "  code = " << apt_code << endl;
+    cout << "  lat  = " << apt_lat << endl;
+    cout << "  lon  = " << apt_lon << endl;
+    cout << "  elev = " << apt_elev << " " << elev << endl;
+    cout << "  use  = " << apt_use << endl;
+    cout << "  twr  = " << apt_twr << endl;
+    cout << "  bldg = " << apt_bldg << endl;
+    cout << "  name = " << apt_name << endl;
+    */
+
+    // parse runways and generate the vertex list
+    string rwy_str;
+    double lon, lat, hdg;
+    int len, width;
 
-    // generate the vertices of all the runways
-    int len, width, hdg, label_hdg, elev;
-    char codes[10];
-    char side;
-    cout << "(apt) " << last_airport;
     list < string >::iterator last_runway = runway_list.end();
     for ( list < string >::iterator current_runway = runway_list.begin();
 	  current_runway != last_runway ; ++current_runway ) {
-	line_str = (*current_runway);
-	cout << line_str;
+	rwy_str = (*current_runway);
 
-	sscanf( line_str.c_str(), "%lf %lf %d %d %d %s %d %c %d\n",
-		&lon, &lat, &len, &width, &hdg, codes, &label_hdg, 
-		&side, &elev );
+	cout << rwy_str << endl;
+	string rwy_no = rwy_str.substr(2, 4);
+	string rwy_lat = rwy_str.substr(6, 10);
+	sscanf( rwy_lat.c_str(), "%lf", &lat);
+	string rwy_lon = rwy_str.substr(17, 11);
+	sscanf( rwy_lon.c_str(), "%lf", &lon);
+	string rwy_hdg = rwy_str.substr(29, 7);
+	sscanf( rwy_hdg.c_str(), "%lf", &hdg);
+	string rwy_len = rwy_str.substr(36, 7);
+	sscanf( rwy_len.c_str(), "%d", &len);
+	string rwy_width = rwy_str.substr(43, 4);
+	sscanf( rwy_width.c_str(), "%d", &width);
+	string rwy_sfc = rwy_str.substr(47, 4);
+	string rwy_end1 = rwy_str.substr(52, 6);
+	string rwy_end2 = rwy_str.substr(59, 6);
 
-	rwy_list = gen_runway_area( lon, lat, (double)hdg * DEG_TO_RAD, 
+	/*
+	cout << "  no    = " << rwy_no << endl;
+	cout << "  lat   = " << rwy_lat << " " << lat << endl;
+	cout << "  lon   = " << rwy_lon << " " << lon << endl;
+	cout << "  hdg   = " << rwy_hdg << " " << hdg << endl;
+	cout << "  len   = " << rwy_len << " " << len << endl;
+	cout << "  width = " << rwy_width << " " << width << endl;
+	cout << "  sfc   = " << rwy_sfc << endl;
+	cout << "  end1  = " << rwy_end1 << endl;
+	cout << "  end2  = " << rwy_end2 << endl;
+	*/
+	
+	rwy_list = gen_runway_area( lon, lat, hdg * DEG_TO_RAD, 
 				    (double)len * FEET_TO_METER,
 				    (double)width * FEET_TO_METER );
 
@@ -123,6 +173,11 @@ void process_airport( string last_airport, list < string > & runway_list,
 	}
     }
 
+    if ( apt_list.size() == 0 ) {
+	cout << "no runway points generated" << endl;
+	return;
+    }
+
     // printf("Runway points in degrees\n");
     // current = apt_list.begin();
     // last = apt_list.end();
@@ -134,10 +189,13 @@ void process_airport( string last_airport, list < string > & runway_list,
     // generate convex hull
     hull_list = convex_hull(apt_list);
 
+    // get next polygon index
+    int index = poly_index_next();
+
     // find average center, min, and max point of convex hull
     point2d average, min, max;
     double sum_x, sum_y;
-    count = hull_list.size();
+    int count = hull_list.size();
     current = hull_list.begin();
     last = hull_list.end();
     sum_x = sum_y = 0.0;
@@ -167,7 +225,7 @@ void process_airport( string last_airport, list < string > & runway_list,
     cout << "Bucket max = " << b_max << endl;
     
     if ( b_min == b_max ) {
-	write_airport( hull_list, b, root, true );
+	write_airport( index, hull_list, b, root, true );
     } else {
 	FGBucket b_cur;
 	int dx, dy, i, j;
@@ -185,9 +243,9 @@ void process_airport( string last_airport, list < string > & runway_list,
 	    for ( i = 0; i <= dx; i++ ) {
 		b_cur = fgBucketOffset(min.x, min.y, i, j);
 		if ( b_cur == b ) {
-		    write_airport( hull_list, b_cur, root, true );
+		    write_airport( index, hull_list, b_cur, root, true );
 		} else {
-		    write_airport( hull_list, b_cur, root, false );
+		    write_airport( index, hull_list, b_cur, root, false );
 		}
 	    }
 	}
@@ -208,16 +266,32 @@ int main( int argc, char **argv ) {
 
     if ( argc != 3 ) {
 	FG_LOG( FG_GENERAL, FG_ALERT, 
-		"Usage " << argv[0] << " <apt_file> <work dir>" );
+		"Usage " << argv[0] << " <apt_file> <work_dir>" );
 	exit(-1);
     }
 
+    // make work directory
+    string work_dir = argv[2];
+    string command = "mkdir -p " + work_dir;
+    system( command.c_str() );
+
+    // initialize persistant polygon counter
+    string counter_file = work_dir + "/polygon.counter";
+    poly_index_init( counter_file );
+
     fg_gzifstream in( argv[1] );
     if ( !in ) {
         FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << argv[1] );
         exit(-1);
     }
 
+    // throw away the first 3 lines
+    in.getline(tmp, 256);
+    in.getline(tmp, 256);
+    in.getline(tmp, 256);
+
+    last_airport = "";
+
     while ( ! in.eof() ) {
 	in.getline(tmp, 256);
 	line = tmp;
@@ -227,10 +301,7 @@ int main( int argc, char **argv ) {
 	    // empty, skip
 	} else if ( line[0] == '#' ) {
 	    // comment, skip
-	} else if ( line[0] == '\t' ) {
-	    // runway entry
-	    runway_list.push_back(line);
-	} else {
+	} else if ( (line[0] == 'A') || (line[0] == 'S') ) {
 	    // start of airport record
 	    airport = line;
 
@@ -243,6 +314,16 @@ int main( int argc, char **argv ) {
 	    runway_list.erase(runway_list.begin(), runway_list.end());
 
 	    last_airport = airport;
+	} else if ( line[0] == 'R' ) {
+	    // runway entry
+	    runway_list.push_back(line);
+	} else if ( line == "99" ) {
+	    // end of file
+	    break;
+	} else {
+	    FG_LOG( FG_GENERAL, FG_ALERT, 
+		    "Unknown line in file" << endl << line );
+	    exit(-1);
 	}
     }
 
@@ -256,6 +337,10 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.7  1999/02/25 21:32:49  curt
+// Modified to adhere to new polygon naming convention, and also to read the
+// new Robin Peel aiport format.
+//
 // Revision 1.6  1999/02/11 01:10:51  curt
 // Start of scenery revamp project.
 //

From 97ed4d05ba068976ba51706cc39a875e35e06374 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Feb 1999 21:33:14 +0000
Subject: [PATCH 190/283] Added a Polygon subdirectory.

---
 Tools/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index a98b77857..3526fead7 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -5,6 +5,7 @@ SUBDIRS = \
 	AssemTris \
 	Clipper \
 	DEM \
+	Polygon \
 	Dem2node \
 	DemInfo \
 	DemRaw2ascii \

From 08c4dcaf0c900f4c02a8fc83bc32eceb715c22dc Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 26 Feb 1999 22:10:42 +0000
Subject: [PATCH 191/283] Updated names and priorities of area types.

---
 Polygon/names.hxx | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/Polygon/names.hxx b/Polygon/names.hxx
index 50222d104..ce6236ee3 100644
--- a/Polygon/names.hxx
+++ b/Polygon/names.hxx
@@ -37,23 +37,25 @@
 #undef RAD_TO_DEG
 
 
-// Posible shape file types
+// Posible shape file types.  Note the order of these is important and
+// defines the priority of these shapes if they should intersect.  The
+// smaller the number, the higher the priority.
 enum AreaType {
-    AirportKeepArea = 0,
+    AirportKeepArea   = 0,
     AirportIgnoreArea = 1,
-    MarshArea = 2,
-    OceanArea = 3,
-    LakeArea = 4,
-    DryLakeArea = 5,
-    IntLakeArea = 6,
-    ReservoirArea = 7,
-    IntReservoirArea = 8,
-    StreamArea = 9,
-    CanalArea = 10,
-    GlacierArea = 11,
-    VoidArea = 9997,
-    NullArea = 9998,
-    UnknownArea = 9999
+    OceanArea         = 2,
+    LakeArea          = 3,
+    DryLakeArea       = 4,
+    IntLakeArea       = 5,
+    ReservoirArea     = 6,
+    IntReservoirArea  = 7,
+    StreamArea        = 8,
+    CanalArea         = 9,
+    GlacierArea       = 10,
+    MarshArea         = 11,
+    VoidArea          = 9997,
+    NullArea          = 9998,
+    UnknownArea       = 9999
 };
 
 
@@ -68,6 +70,9 @@ string get_area_name( AreaType area );
 
 
 // $Log$
+// Revision 1.2  1999/02/26 22:10:42  curt
+// Updated names and priorities of area types.
+//
 // Revision 1.1  1999/02/25 21:30:24  curt
 // Initial revision.
 //

From 60fc8b1c7e6cc579859798adaa40ec421f29dcd9 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Mar 1999 15:34:35 +0000
Subject: [PATCH 192/283] Build libraries first in sequence.

---
 Tools/Makefile.am | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 3526fead7..acfddf809 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -1,11 +1,12 @@
 EXTRA_DIST = process-dem.pl
 
 SUBDIRS = \
+	DEM \
 	Areas \
 	AssemTris \
-	Clipper \
 	DEM \
 	Polygon \
+	Clipper \
 	Dem2node \
 	DemInfo \
 	DemRaw2ascii \

From b30530bb94d5528e72495dde03d4ce8c9f4eb197 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Mar 1999 15:35:26 +0000
Subject: [PATCH 193/283] Fixed bug in output format generated.

---
 GenAirports/main.cxx | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index 77b9607c3..5ef504234 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -73,13 +73,20 @@ void write_airport( int p_index, list_container hull_list, FGBucket b,
         exit(-1);
     }
 
+    // polygon type
     if ( cut_and_keep ) {
 	fprintf( fd, "AirportKeep\n" );
     } else {
 	fprintf( fd, "AirportIgnore\n" );
     }
+
+    // number of contours
+    fprintf( fd, "1\n" );
+
+    // size of first contour
     fprintf( fd, "%d\n", hull_list.size() );
-    // write perimeter polygon
+
+    // write contour (polygon) points
     list_iterator current = hull_list.begin();
     list_iterator last = hull_list.end();
     for ( ; current != last ; ++current ) {
@@ -337,6 +344,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.8  1999/03/01 15:35:26  curt
+// Fixed bug in output format generated.
+//
 // Revision 1.7  1999/02/25 21:32:49  curt
 // Modified to adhere to new polygon naming convention, and also to read the
 // new Robin Peel aiport format.

From 7ac99494e5b8afc42f1ad08cfdfb445901e1aa58 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Mar 1999 15:35:52 +0000
Subject: [PATCH 194/283] Generalized the routines a bit to make them more
 useful.

---
 Polygon/names.cxx | 27 ++++++++++++++++++++-------
 Polygon/names.hxx |  8 +++++++-
 2 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/Polygon/names.cxx b/Polygon/names.cxx
index d01dd9b8d..6d94f88c1 100644
--- a/Polygon/names.cxx
+++ b/Polygon/names.cxx
@@ -29,7 +29,7 @@
 
 
 // return the type of the shapefile record
-AreaType get_area_type(GDBFile *dbf, int rec) {
+AreaType get_shapefile_type(GDBFile *dbf, int rec) {
     GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
     GDBFValue *fields;		//an array of field values
     char* dbf_rec;		//a record containing all the fields
@@ -47,6 +47,8 @@ AreaType get_area_type(GDBFile *dbf, int rec) {
     // parse it into individual fields
     if ( dbf_rec ) {
 	fields = dbf->recordDeform( dbf_rec );
+    } else {
+	return UnknownArea;
     }
 
     string area = fields[4].str_v;
@@ -63,11 +65,18 @@ AreaType get_area_type(GDBFile *dbf, int rec) {
 	area = area.substr(0, area.length() - 1);
     }
 
+    return get_area_type( area );
+}
+
+
+// return area type from text name
+AreaType get_area_type( string area ) {
     if ( area == "AirportKeep" ) {
 	return AirportKeepArea;
     } else if ( area == "AirportIgnore" ) {
 	return AirportIgnoreArea;
-    } else if ( area == "Swamp or Marsh" ) {
+    } else if ( (area == "Swamp or Marsh")
+		|| (area == "Marsh") ) {
 	return MarshArea;
     } else if ( area == "Bay  Estuary or Ocean" ) {
 	return OceanArea;
@@ -75,7 +84,8 @@ AreaType get_area_type(GDBFile *dbf, int rec) {
 	return LakeArea;
     } else if ( area == "Lake   Dry" ) {
 	return DryLakeArea;
-    } else if ( area == "Lake   Intermittent" ) {
+    } else if ( (area == "Lake   Intermittent")
+		|| (area == "IntermittentLake") ) {
 	return IntLakeArea;
     } else if ( area == "Reservoir" ) {
 	return ReservoirArea;
@@ -94,15 +104,15 @@ AreaType get_area_type(GDBFile *dbf, int rec) {
     } else {
 	cout << "unknown area = '" << area << "'" << endl;
 	// cout << "area = " << area << endl;
-	for ( int i = 0; i < area.length(); i++ ) {
-	    cout << i << ") " << (int)area[i] << endl;
-	}
+	// for ( int i = 0; i < area.length(); i++ ) {
+	//  cout << i << ") " << (int)area[i] << endl;
+	// }
 	return UnknownArea;
     }
 }
 
 
-// return text form of area name
+// return text from of area name
 string get_area_name( AreaType area ) {
     if ( area == AirportKeepArea ) {
 	return "AirportKeep";
@@ -140,6 +150,9 @@ string get_area_name( AreaType area ) {
 
 
 // $Log$
+// Revision 1.2  1999/03/01 15:35:52  curt
+// Generalized the routines a bit to make them more useful.
+//
 // Revision 1.1  1999/02/25 21:30:24  curt
 // Initial revision.
 //
diff --git a/Polygon/names.hxx b/Polygon/names.hxx
index ce6236ee3..168df64d8 100644
--- a/Polygon/names.hxx
+++ b/Polygon/names.hxx
@@ -60,7 +60,10 @@ enum AreaType {
 
 
 // return the type of the shapefile record
-AreaType get_area_type(GDBFile *dbf, int rec);
+AreaType get_shapefile_type(GDBFile *dbf, int rec);
+
+// return area type from text name
+AreaType get_area_type( string area );
 
 // return text form of area name
 string get_area_name( AreaType area );
@@ -70,6 +73,9 @@ string get_area_name( AreaType area );
 
 
 // $Log$
+// Revision 1.3  1999/03/01 15:35:53  curt
+// Generalized the routines a bit to make them more useful.
+//
 // Revision 1.2  1999/02/26 22:10:42  curt
 // Updated names and priorities of area types.
 //

From 64902b423ca655ce506aa0f527b7621bfda9d1eb Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Mar 1999 15:36:28 +0000
Subject: [PATCH 195/283] Tweaked a function call name in "names.hxx".

---
 ShapeFile/main.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
index 58ebf52a1..9666c3999 100644
--- a/ShapeFile/main.cxx
+++ b/ShapeFile/main.cxx
@@ -97,7 +97,7 @@ int main( int argc, char **argv ) {
 	FG_LOG( FG_GENERAL, FG_DEBUG, "Record = " << i << "  rings = " 
 		<< shape.numRings() );
 
-	AreaType area = get_area_type(dbf, i);
+	AreaType area = get_shapefile_type(dbf, i);
 	FG_LOG( FG_GENERAL, FG_DEBUG, "area type = " << get_area_name(area) 
 		<< " (" << (int)area << ")" );
 
@@ -261,6 +261,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.5  1999/03/01 15:36:28  curt
+// Tweaked a function call name in "names.hxx".
+//
 // Revision 1.4  1999/02/25 21:31:05  curt
 // First working version???
 //

From ad2505c880df3b4002a95343b2bfb91324c9f912 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 1 Mar 1999 15:39:39 +0000
Subject: [PATCH 196/283] Initial revision.

---
 Clipper/Makefile.am |  14 +++
 Clipper/clipper.cxx | 226 ++++++++++++++++++++++++++++++++++++++++++++
 Clipper/clipper.hxx |  87 +++++++++++++++++
 Clipper/main.cxx    | 114 ++++++++++++++++++++++
 4 files changed, 441 insertions(+)
 create mode 100644 Clipper/Makefile.am
 create mode 100644 Clipper/clipper.cxx
 create mode 100644 Clipper/clipper.hxx
 create mode 100644 Clipper/main.cxx

diff --git a/Clipper/Makefile.am b/Clipper/Makefile.am
new file mode 100644
index 000000000..21d1948aa
--- /dev/null
+++ b/Clipper/Makefile.am
@@ -0,0 +1,14 @@
+noinst_LIBRARIES = libClipper.a
+bin_PROGRAMS = clipper
+
+libClipper_a_SOURCES = clipper.cxx clipper.hxx
+clipper_SOURCES = main.cxx
+
+clipper_LDADD = $(top_builddir)/Tools/Clipper/libClipper.a \
+	$(top_builddir)/Tools/Polygon/libPolygon.a \
+	$(top_builddir)/Lib/Debug/libDebug.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
+	$(top_builddir)/Lib/zlib/libz.a \
+	-lgfc -lgpc
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
new file mode 100644
index 000000000..e4aaa76f0
--- /dev/null
+++ b/Clipper/clipper.cxx
@@ -0,0 +1,226 @@
+// clipper.cxx -- top level routines to take a series of arbitrary areas and
+//                produce a tight fitting puzzle pieces that combine to make a
+//                tile
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+
+
+#include "clipper.hxx"
+
+#include <Debug/logstream.hxx>
+#include <Include/fg_constants.h>
+#include <Misc/fgstream.hxx>
+#include <Polygon/names.hxx>
+
+
+#define EXTRA_SAFETY_CLIP
+
+#define FG_MAX_VERTICES 100000
+
+static gpc_vertex_list v_list;
+// static gpc_polygon poly;
+static FGPolyList polys_in, polys_out;
+
+
+// Initialize Clipper (allocate and/or connect structures)
+bool fgClipperInit() {
+    v_list.num_vertices = 0;
+    v_list.vertex = new gpc_vertex[FG_MAX_VERTICES];;
+
+    return true;
+}
+
+
+// Load a polygon definition file
+bool fgClipperLoadPolygons(const string& path) {
+    string poly_name;
+    AreaType poly_type;
+    int contours, count, i, j;
+    double startx, starty, x, y, lastx, lasty;
+
+    FG_LOG( FG_CLIPPER, FG_INFO, "Loading " << path << " ..." );
+
+    fg_gzifstream in( path );
+
+    if ( !in ) {
+        FG_LOG( FG_CLIPPER, FG_ALERT, "Cannot open file: " << path );
+	exit(-1);
+    }
+
+    in >> skipcomment;
+    while ( !in.eof() ) {
+	in >> poly_name;
+	cout << "poly name = " << poly_name << endl;
+	poly_type = get_area_type( poly_name );
+	cout << "poly type (int) = " << (int)poly_type << endl;
+	in >> contours;
+	cout << "num contours = " << contours << endl;
+
+	for ( i = 0; i < contours; ++i ) {
+	    in >> count;
+
+	    if ( count < 3 ) {
+		FG_LOG( FG_CLIPPER, FG_ALERT, 
+			"Polygon with less than 3 data points." );
+		exit(-1);
+	    }
+
+	    in >> startx;
+	    in >> starty;
+	    v_list.vertex[0].x = startx;
+	    v_list.vertex[0].y = starty;
+	    FG_LOG( FG_CLIPPER, FG_BULK, "0 = " 
+		    << startx << ", " << starty );
+
+	    for ( j = 1; j < count - 1; ++j ) {
+		in >> x;
+		in >> y;
+		v_list.vertex[j].x = x;
+		v_list.vertex[j].y = y;
+		FG_LOG( FG_CLIPPER, FG_BULK, j << " = " << x << ", " << y );
+	    }
+	    v_list.num_vertices = count - 1;
+
+	    in >> lastx;
+	    in >> lasty;
+
+	    if ( (fabs(startx - lastx) < FG_EPSILON) 
+		 && (fabs(starty - lasty) < FG_EPSILON) ) {
+		// last point same as first, discard
+	    } else {
+		v_list.vertex[count - 1].x = lastx;
+		v_list.vertex[count - 1].y = lasty;
+		++v_list.num_vertices;
+		FG_LOG( FG_CLIPPER, FG_BULK, count - 1 << " = " 
+			<< lastx << ", " << lasty );
+	    }
+
+	    gpc_polygon *poly = new gpc_polygon;
+	    poly->num_contours = 0;
+	    poly->contour = NULL;
+	    gpc_add_contour( poly, &v_list );
+
+	    int area = (int)poly_type;
+	    if ( area < FG_MAX_AREAS ) {
+		polys_in.polys[area].push_back(poly);
+	    } else {
+		FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = " 
+			<< poly_type);
+		exit(-1);
+	    }
+	}
+
+	in >> skipcomment;
+    }
+
+    // FILE *ofp= fopen("outfile", "w");
+    // gpc_write_polygon(ofp, &polys.landuse);
+
+    return true;
+}
+
+
+// Do actually clipping work
+bool fgClipperMaster(const point2d& min, const point2d& max) {
+    gpc_polygon accum, result_diff, result_union, tmp;
+    polylist_iterator current, last;
+
+    FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
+
+    accum.num_contours = 0;
+
+    cout << "  (" << min.x << "," << min.y << ") (" 
+	 << max.x << "," << max.y << ")" << endl;
+
+    // set up clipping tile
+    v_list.vertex[0].x = min.x;
+    v_list.vertex[0].y = min.y;
+
+    v_list.vertex[1].x = max.x;
+    v_list.vertex[1].y = min.y;
+
+    v_list.vertex[2].x = max.x;
+    v_list.vertex[2].y = max.y;
+
+    v_list.vertex[3].x = min.x;
+    v_list.vertex[3].y = max.y;
+
+    v_list.num_vertices = 4;
+
+    polys_in.safety_base.num_contours = 0;
+    polys_in.safety_base.contour = NULL;
+    gpc_add_contour( &polys_in.safety_base, &v_list );
+
+    // process polygons in priority order
+    for ( int i = 0; i < FG_MAX_AREAS; ++i ) {
+
+	current = polys_in.polys[i].begin();
+	last = polys_in.polys[i].end();
+	for ( ; current != last; ++current ) {
+	    FG_LOG( FG_CLIPPER, FG_DEBUG, get_area_name( (AreaType)i ) 
+		    << " = " << (*current)->contour->num_vertices );
+
+#ifdef EXTRA_SAFETY_CLIP
+	    // clip to base tile
+	    gpc_polygon_clip(GPC_INT, &polys_in.safety_base, *current, &tmp);
+#else
+	    &tmp = *current;
+#endif
+
+	    // clip current polygon against previous higher priority
+	    // stuff
+	    if ( accum.num_contours == 0 ) {
+		result_diff = tmp;
+		result_union = tmp;
+	    } else {
+		gpc_polygon_clip(GPC_DIFF, &accum, &tmp, &result_diff);
+		gpc_polygon_clip(GPC_UNION, &accum, &tmp, &result_union);
+	    }
+	    
+	    polys_out.polys[i].push_back(&result_diff);
+	    accum = result_union;
+	}
+    }
+
+    // finally, what ever is left over goes to base terrain
+
+    // clip to accum against original base tile
+    gpc_polygon_clip(GPC_DIFF, &polys_in.safety_base, &accum, 
+		     &polys_out.safety_base);
+
+    // tmp output accum
+    FILE *ofp= fopen("accum", "w");
+    gpc_write_polygon(ofp, &accum);
+
+    // tmp output safety_base
+    ofp= fopen("safety_base", "w");
+    gpc_write_polygon(ofp, &polys_out.safety_base);
+
+    return true;
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/01 15:39:39  curt
+// Initial revision.
+//
diff --git a/Clipper/clipper.hxx b/Clipper/clipper.hxx
new file mode 100644
index 000000000..79b7e16da
--- /dev/null
+++ b/Clipper/clipper.hxx
@@ -0,0 +1,87 @@
+// clipper.hxx -- top level routines to take a series of arbitrary areas and
+//                produce a tight fitting puzzle pieces that combine to make a
+//                tile
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+
+
+#ifndef _CLIPPER_HXX
+#define _CLIPPER_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+
+// include Generic Polygon Clipping Library
+//
+//    http://www.cs.man.ac.uk/aig/staff/alan/software/
+//
+extern "C" {
+#include <gpc.h>
+}
+
+#include STL_STRING
+#include <vector>
+
+typedef vector < gpc_polygon * > polylist;
+typedef polylist::iterator polylist_iterator;
+
+#define FG_MAX_AREAS 20
+
+class point2d {
+public:
+    double x, y;
+};
+
+
+class FGPolyList {
+public:
+    polylist polys[FG_MAX_AREAS];
+    gpc_polygon safety_base;
+};
+
+
+// Initialize Clipper (allocate and/or connect structures)
+bool fgClipperInit();
+
+
+// Load a polygon definition file
+bool fgClipperLoadPolygons(const string& path);
+
+
+// Do actually clipping work
+bool fgClipperMaster(const point2d& min, const point2d& max);
+
+
+#endif // _CLIPPER_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/01 15:39:39  curt
+// Initial revision.
+//
diff --git a/Clipper/main.cxx b/Clipper/main.cxx
new file mode 100644
index 000000000..4aa613a4e
--- /dev/null
+++ b/Clipper/main.cxx
@@ -0,0 +1,114 @@
+// main.cxx -- sample use of the clipper lib
+//
+// Written by Curtis Olson, started February 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+ 
+
+
+#include "clipper.hxx"
+
+#include <Debug/logstream.hxx>
+#include <Bucket/newbucket.hxx>
+
+
+int main( int argc, char **argv ) {
+    point2d global_min, global_max;
+
+    fglog().setLogLevels( FG_ALL, FG_DEBUG );
+
+    global_min.x = global_min.y = 200;
+    global_max.y = global_max.x = -200;
+
+    fgClipperInit();
+
+    if ( argc < 2 ) {
+	FG_LOG( FG_CLIPPER, FG_ALERT, "Usage: " << argv[0] 
+		<< " file1 file2 ..." );
+	exit(-1);
+    }
+
+    // process all specified polygon files
+    for ( int i = 1; i < argc; i++ ) {
+	string full_path = argv[i];
+
+	// determine bucket for this polygon
+	int pos = full_path.rfind("/");
+	string file_name = full_path.substr(pos + 1);
+	cout << "file name = " << file_name << endl;
+
+	pos = file_name.find(".");
+	string base_name = file_name.substr(0, pos);
+	cout << "base_name = " << base_name << endl;
+
+	long int index;
+	sscanf( base_name.c_str(), "%ld", &index);
+	FGBucket b(index);
+	cout << "bucket = " << b << endl;
+
+	// calculate bucket dimensions
+	point2d c, min, max;
+
+	c.x = b.get_center_lon();
+	c.y = b.get_center_lat();
+	double span = bucket_span(c.y);
+
+	if ( (c.y >= -89.0) && (c.y < 89.0) ) {
+	    min.x = c.x - span / 2.0;
+	    max.x = c.x + span / 2.0;
+	    min.y = c.y - FG_HALF_BUCKET_SPAN;
+	    max.y = c.y + FG_HALF_BUCKET_SPAN;
+	} else if ( c.y < -89.0) {
+	    min.x = -90.0;
+	    max.x = -89.0;
+	    min.y = -180.0;
+	    max.y = 180.0;
+	} else if ( c.y >= 89.0) {
+	    min.x = 89.0;
+	    max.x = 90.0;
+	    min.y = -180.0;
+	    max.y = 180.0;
+	} else {
+	    FG_LOG ( FG_GENERAL, FG_ALERT, 
+		     "Out of range latitude in clip_and_write_poly() = " 
+		     << c.y );
+	}
+
+	if ( min.x < global_min.x ) global_min.x = min.x;
+	if ( min.y < global_min.y ) global_min.y = min.y;
+	if ( max.x > global_max.x ) global_max.x = max.x;
+	if ( max.y > global_max.y ) global_max.y = max.y;
+
+	// finally, load the polygon(s) from this file
+	fgClipperLoadPolygons( full_path );
+    }
+
+    // do the clipping
+    fgClipperMaster(global_min, global_max);
+
+    FG_LOG( FG_CLIPPER, FG_INFO, "finished main" );
+
+    return 0;
+}
+
+// $Log$
+// Revision 1.1  1999/03/01 15:39:39  curt
+// Initial revision.
+//

From 1a4b54a331ddb53e41819788a6b1dc756333af43 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Mar 1999 01:03:58 +0000
Subject: [PATCH 197/283] Added more reverse lookup support.

---
 Polygon/names.cxx | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Polygon/names.cxx b/Polygon/names.cxx
index 6d94f88c1..e70b2d479 100644
--- a/Polygon/names.cxx
+++ b/Polygon/names.cxx
@@ -78,7 +78,8 @@ AreaType get_area_type( string area ) {
     } else if ( (area == "Swamp or Marsh")
 		|| (area == "Marsh") ) {
 	return MarshArea;
-    } else if ( area == "Bay  Estuary or Ocean" ) {
+    } else if ( (area == "Bay  Estuary or Ocean")
+                || (area == "Ocean") ) {
 	return OceanArea;
     } else if ( area == "Lake" ) {
 	return LakeArea;
@@ -150,6 +151,9 @@ string get_area_name( AreaType area ) {
 
 
 // $Log$
+// Revision 1.3  1999/03/02 01:03:58  curt
+// Added more reverse lookup support.
+//
 // Revision 1.2  1999/03/01 15:35:52  curt
 // Generalized the routines a bit to make them more useful.
 //

From 0b156394fa48479f6e8fc125bed7c43ab9573779 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 2 Mar 1999 01:04:28 +0000
Subject: [PATCH 198/283] Don't crash when work directory doesn't exist ...
 create it.

---
 ShapeFile/main.cxx | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
index 9666c3999..b123d26b7 100644
--- a/ShapeFile/main.cxx
+++ b/ShapeFile/main.cxx
@@ -67,9 +67,13 @@ int main( int argc, char **argv ) {
 
     FG_LOG( FG_GENERAL, FG_DEBUG, "Opening " << argv[1] << " for reading." );
 
+    // make work directory
+    string work_dir = argv[2];
+    string command = "mkdir -p " + work_dir;
+    system( command.c_str() );
+
     // initialize persistant polygon counter
-    string counter_file = argv[2];
-    counter_file += "/polygon.counter";
+    string counter_file = work_dir + "/polygon.counter";
     poly_index_init( counter_file );
 
     // initialize structure for building gpc polygons
@@ -261,6 +265,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.6  1999/03/02 01:04:28  curt
+// Don't crash when work directory doesn't exist ... create it.
+//
 // Revision 1.5  1999/03/01 15:36:28  curt
 // Tweaked a function call name in "names.hxx".
 //

From cf78794eaff7a09e2ef0744e579fcbeb3679bd2c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Mar 1999 22:00:35 +0000
Subject: [PATCH 199/283] Lots of directory layout reorganization.

---
 Clipper/Makefile.am     |  4 ++--
 DemInfo/Makefile.am     |  7 +++++--
 FixNode/Makefile.am     |  7 +++++--
 GenAirports/Makefile.am |  7 +++++--
 ShapeFile/Makefile.am   |  4 ++--
 Tools/Makefile.am       | 11 +++--------
 6 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/Clipper/Makefile.am b/Clipper/Makefile.am
index 21d1948aa..f6acb6b67 100644
--- a/Clipper/Makefile.am
+++ b/Clipper/Makefile.am
@@ -5,10 +5,10 @@ libClipper_a_SOURCES = clipper.cxx clipper.hxx
 clipper_SOURCES = main.cxx
 
 clipper_LDADD = $(top_builddir)/Tools/Clipper/libClipper.a \
-	$(top_builddir)/Tools/Polygon/libPolygon.a \
+	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	-lgfc -lgpc
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
diff --git a/DemInfo/Makefile.am b/DemInfo/Makefile.am
index 0b3c81ebf..355d81593 100644
--- a/DemInfo/Makefile.am
+++ b/DemInfo/Makefile.am
@@ -30,13 +30,13 @@ deminfo_SOURCES = \
 	deminfo.cxx
 
 deminfo_LDADD = \
-	$(top_builddir)/Tools/DEM/libDEM.a \
+	$(top_builddir)/Tools/Lib/DEM/libDEM.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
 
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
@@ -46,6 +46,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1999/03/08 22:00:46  curt
+# Lots of directory layout reorganization.
+#
 # Revision 1.5  1999/02/01 21:09:27  curt
 # Moving location of Lib/DEM/ to Tools/DEM/
 #
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index 0ec673276..68a89ed2e 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -31,13 +31,13 @@ fixnode_SOURCES = \
 	main.cxx
 
 fixnode_LDADD = \
-	$(top_builddir)/Tools/DEM/libDEM.a \
+	$(top_builddir)/Tools/Lib/DEM/libDEM.a \
         $(top_builddir)/Lib/Bucket/libBucket.a \
         $(top_builddir)/Lib/Misc/libMisc.a \
         $(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
 
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
@@ -47,6 +47,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.9  1999/03/08 22:00:45  curt
+# Lots of directory layout reorganization.
+#
 # Revision 1.8  1999/02/01 21:09:30  curt
 # Moving location of Lib/DEM/ to Tools/DEM/
 #
diff --git a/GenAirports/Makefile.am b/GenAirports/Makefile.am
index d1d6aaca5..86c8ecb16 100644
--- a/GenAirports/Makefile.am
+++ b/GenAirports/Makefile.am
@@ -33,18 +33,21 @@ genapts_SOURCES = \
 	point2d.cxx point2d.hxx
 
 genapts_LDADD = \
-	$(top_builddir)/Tools/Polygon/libPolygon.a \
+	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.6  1999/03/08 22:00:47  curt
+# Lots of directory layout reorganization.
+#
 # Revision 1.5  1999/02/25 21:32:47  curt
 # Modified to adhere to new polygon naming convention, and also to read the
 # new Robin Peel aiport format.
diff --git a/ShapeFile/Makefile.am b/ShapeFile/Makefile.am
index 6aec7fdec..b3c41b82b 100644
--- a/ShapeFile/Makefile.am
+++ b/ShapeFile/Makefile.am
@@ -3,7 +3,7 @@ bin_PROGRAMS = shape-decode
 shape_decode_SOURCES = main.cxx shape.cxx shape.hxx
 
 shape_decode_LDADD = \
-	$(top_builddir)/Tools/Polygon/libPolygon.a \
+	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
@@ -11,4 +11,4 @@ shape_decode_LDADD = \
 	-lgfc -lgpc
 
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index acfddf809..c7ca1f2c1 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -1,20 +1,15 @@
 EXTRA_DIST = process-dem.pl
 
 SUBDIRS = \
-	DEM \
+	Lib \
+	Prep \
+	Utils \
 	Areas \
 	AssemTris \
-	DEM \
-	Polygon \
 	Clipper \
 	Dem2node \
-	DemInfo \
-	DemRaw2ascii \
 	FixNode \
 	FixObj \
-	GenAirports \
-	Makedir \
-	ShapeFile \
 	SplitTris \
 	Stripe_w \
 	Tri2obj \

From 7794e0bf68468086c3b16fa48872eba49abfc7de Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 8 Mar 1999 22:04:29 +0000
Subject: [PATCH 200/283] Initial revision.

---
 Lib/Makefile.am   | 3 +++
 Prep/Makefile.am  | 5 +++++
 Utils/Makefile.am | 2 ++
 3 files changed, 10 insertions(+)
 create mode 100644 Lib/Makefile.am
 create mode 100644 Prep/Makefile.am
 create mode 100644 Utils/Makefile.am

diff --git a/Lib/Makefile.am b/Lib/Makefile.am
new file mode 100644
index 000000000..9b607f4c5
--- /dev/null
+++ b/Lib/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+	DEM \
+	Polygon
diff --git a/Prep/Makefile.am b/Prep/Makefile.am
new file mode 100644
index 000000000..51f8ae2bb
--- /dev/null
+++ b/Prep/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = \
+	DemInfo \
+	DemRaw2ascii \
+	GenAirports \
+	ShapeFile
diff --git a/Utils/Makefile.am b/Utils/Makefile.am
new file mode 100644
index 000000000..5c3f005b0
--- /dev/null
+++ b/Utils/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = \
+	Makedir

From d2d25cbc9314c1157f9b7af4468b5ae2b40f5c69 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 10 Mar 1999 01:02:54 +0000
Subject: [PATCH 201/283] Initial revision.

---
 DemChop/Makefile.am |  51 +++++++++++++++++++++
 DemChop/demchop.cxx | 107 ++++++++++++++++++++++++++++++++++++++++++++
 DemChop/point2d.cxx |  44 ++++++++++++++++++
 3 files changed, 202 insertions(+)
 create mode 100644 DemChop/Makefile.am
 create mode 100644 DemChop/demchop.cxx
 create mode 100644 DemChop/point2d.cxx

diff --git a/DemChop/Makefile.am b/DemChop/Makefile.am
new file mode 100644
index 000000000..ff5474731
--- /dev/null
+++ b/DemChop/Makefile.am
@@ -0,0 +1,51 @@
+#---------------------------------------------------------------------------
+# Makefile
+#
+# Written by Curtis Olson, started March 1999.
+#
+# Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Id$
+# (Log is kept at end of this file)
+#---------------------------------------------------------------------------
+
+
+bin_PROGRAMS = demchop
+
+demchop_SOURCES = \
+	demchop.cxx point2d.hxx
+
+demchop_LDADD = \
+	$(top_builddir)/Tools/Lib/DEM/libDEM.a \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
+	$(top_builddir)/Lib/zlib/libz.a \
+	$(base_LIBS)
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
+
+# We can't build this with "-O2" (optimization) since this causes a seg fault
+# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
+# setting it to "-g"
+CXXFLAGS = -g 
+
+
+#---------------------------------------------------------------------------
+# $Log$
+# Revision 1.1  1999/03/10 01:02:54  curt
+# Initial revision.
+#
diff --git a/DemChop/demchop.cxx b/DemChop/demchop.cxx
new file mode 100644
index 000000000..b311c7fcc
--- /dev/null
+++ b/DemChop/demchop.cxx
@@ -0,0 +1,107 @@
+// demchop.cxx -- chop up a dem file into it's corresponding pieces and stuff
+//                them into the workspace directory
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1997  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+#include <Debug/logstream.hxx>
+#include <Bucket/newbucket.hxx>
+#include <DEM/dem.hxx>
+
+FG_USING_STD(string);
+
+
+int main(int argc, char **argv) {
+    /*
+    fgDEM dem;
+    FGBucket p;
+    string fg_root;
+    string filename;
+    double error;
+    int i, j;
+    */
+
+    fglog().setLogLevels( FG_ALL, FG_DEBUG );
+
+    if ( argc != 4 ) {
+	FG_LOG( FG_GENERAL, FG_ALERT, 
+		"Usage " << argv[0] << " <dem_file> <work_dir>" );
+	exit(-1);
+    }
+
+    string dem_name = argv[1];
+    string work_dir = argv[2];
+    string command = "mkdir -p " + work_dir;
+    system( command.c_str() );
+
+    fgDEM dem(dem_name);
+    dem.parse();
+    dem.close();
+
+    point2d min, max;
+    min.x = dem.get_originx() / 3600.0;
+    min.y = dem.get_originy() / 3600.0;
+    FGBucket b_min( min.x, min.y );
+
+    max.x = min.x + ( dem.get_cols() * dem.get_col_step() ) / 3600.0;
+    max.y = min.y + ( dem.get_rows() * dem.get_row_step() ) / 3600.0;
+    FGBucket b_max( max.x, max.y );
+
+    if ( b_min == b_max ) {
+	dem.write_area( b_min );
+    } else {
+	FGBucket b_cur;
+	int dx, dy, i, j;
+
+	fgBucketDiff(b_min, b_max, &dx, &dy);
+	cout << "DEM file spans tile boundaries" << endl;
+	cout << "  dx = " << dx << "  dy = " << dy << endl;
+
+	if ( (dx > 20) || (dy > 20) ) {
+	    cout << "somethings really wrong!!!!" << endl;
+	    exit(-1);
+	}
+
+	for ( j = 0; j <= dy; j++ ) {
+	    for ( i = 0; i <= dx; i++ ) {
+		b_cur = fgBucketOffset(min.x, min.y, i, j);
+		if ( b_cur == b ) {
+		    dem.write_area( b_cur );
+		} else {
+		    dem.write_area( b_cur );
+		}
+	    }
+	}
+    }
+
+    return 0;
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/10 01:02:54  curt
+// Initial revision.
+//
diff --git a/DemChop/point2d.cxx b/DemChop/point2d.cxx
new file mode 100644
index 000000000..817015f8a
--- /dev/null
+++ b/DemChop/point2d.cxx
@@ -0,0 +1,44 @@
+// point2d.cxx -- 2d coordinate routines
+//
+// Written by Curtis Olson, started September 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#include <math.h>
+
+#include "point2d.hxx"
+
+
+// convert a point from cartesian to polar coordinates
+point2d cart_to_polar_2d(point2d in) {
+    point2d result;
+    result.dist = sqrt( in.x * in.x + in.y * in.y );
+    result.theta = atan2(in.y, in.x);    
+
+    return(result);
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/10 01:02:54  curt
+// Initial revision.
+//

From 3defec9ea5a8a8ddfcaccac691af98c9124e715d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 10 Mar 1999 01:09:12 +0000
Subject: [PATCH 202/283] Tweaks to go along with scenery tools overhaul. Added
 a new constructor that accepts the file name.

---
 DEM/dem.cxx | 54 ++++++++++-------------------------------------------
 DEM/dem.hxx | 13 +++++++++++--
 2 files changed, 21 insertions(+), 46 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 8fce8cc97..f59d4831e 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -77,59 +77,21 @@ FG_USING_NAMESPACE(std);
 
 
 fgDEM::fgDEM( void ) {
-    // printf("class fgDEM CONstructor called.\n");
+    // cout << "class fgDEM CONstructor called." << endl;
     dem_data = new float[DEM_SIZE_1][DEM_SIZE_1];
     output_data = new float[DEM_SIZE_1][DEM_SIZE_1];
 }
 
 
-#if 0
-#ifdef WIN32
+fgDEM::fgDEM( const string &file ) {
+    // cout << "class fgDEM CONstructor called." << endl;
+    dem_data = new float[DEM_SIZE_1][DEM_SIZE_1];
+    output_data = new float[DEM_SIZE_1][DEM_SIZE_1];
 
-// return the file path name ( foo/bar/file.ext = foo/bar )
-static void extract_path ( const char *in, char *base) {
-    int len, i;
-    
-    len = strlen (in);
-    strcpy (base, in);
-
-    i = len - 1;
-    while ( (i >= 0) && (in[i] != '/') ) {
-	i--;
-    }
-
-    base[i] = '\0';
+    fgDEM::open(file);
 }
 
 
-// Make a subdirectory
-static int my_mkdir (const char *dir) {
-    struct stat stat_buf;
-    int result;
-
-    printf ("mk_dir() ");
-
-    result = stat (dir, &stat_buf);
-
-    if (result != 0) {
-	MKDIR (dir);
-	result = stat (dir, &stat_buf);
-	if (result != 0) {
-	    printf ("problem creating %s\n", dir);
-	} else {
-	    printf ("%s created\n", dir);
-	}
-    } else {
-	printf ("%s already exists\n", dir);
-    }
-
-    return (result);
-}
-
-#endif // WIN32
-#endif //0
-
-
 // open a DEM file
 int fgDEM::open ( const string& file ) {
     // open input file (or read from stdin)
@@ -868,6 +830,10 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.23  1999/03/10 01:09:12  curt
+// Tweaks to go along with scenery tools overhaul.
+// Added a new constructor that accepts the file name.
+//
 // Revision 1.22  1999/01/19 20:56:56  curt
 // MacOS portability changes contributed by "Robert Puyol" <puyol@abvent.fr>
 //
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 1b24b6a29..44e91a8b0 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -96,6 +96,7 @@ public:
 
     // Constructor
     fgDEM( void );
+    fgDEM( const string& file );
 
     // open a DEM file (use "-" if input is coming from stdin)
     int open ( const string& file );
@@ -113,8 +114,12 @@ public:
     void read_b_record();
 
     // Informational methods
-    double info_originx( void ) { return(originx); }
-    double info_originy( void ) { return(originy); }
+    double get_originx( void ) { return originx; }
+    double get_originy( void ) { return originy; }
+    int get_cols( void ) { return cols; }
+    int get_rows( void ) { return rows; }
+    double get_col_step( void ) { return col_step; }
+    double get_row_step( void ) { return row_step; }
 
     // return the current altitude based on mesh data.  We should
     // rewrite this to interpolate exact values, but for now this is
@@ -145,6 +150,10 @@ public:
 
 
 // $Log$
+// Revision 1.10  1999/03/10 01:09:13  curt
+// Tweaks to go along with scenery tools overhaul.
+// Added a new constructor that accepts the file name.
+//
 // Revision 1.9  1998/10/16 19:08:14  curt
 // Portability updates from Bernie Bright.
 //

From fdfa4f48e5afec9f4452664a4458a4be8b3cc9ef Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 10 Mar 1999 01:12:35 +0000
Subject: [PATCH 203/283] Added DemChop

---
 Prep/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Prep/Makefile.am b/Prep/Makefile.am
index 51f8ae2bb..96c87b412 100644
--- a/Prep/Makefile.am
+++ b/Prep/Makefile.am
@@ -1,4 +1,5 @@
 SUBDIRS = \
+	DemChop \
 	DemInfo \
 	DemRaw2ascii \
 	GenAirports \

From 14888bd09fe53d3490cc9a57c3d0744f5c09b994 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 10 Mar 1999 16:09:44 +0000
Subject: [PATCH 204/283] Hacking towards the first working version.

---
 DemChop/demchop.cxx | 11 ++++----
 DemChop/point2d.hxx | 62 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 5 deletions(-)
 create mode 100644 DemChop/point2d.hxx

diff --git a/DemChop/demchop.cxx b/DemChop/demchop.cxx
index b311c7fcc..5a1b66dc6 100644
--- a/DemChop/demchop.cxx
+++ b/DemChop/demchop.cxx
@@ -31,6 +31,8 @@
 #include <Bucket/newbucket.hxx>
 #include <DEM/dem.hxx>
 
+#include "point2d.hxx"
+
 FG_USING_STD(string);
 
 
@@ -88,11 +90,7 @@ int main(int argc, char **argv) {
 	for ( j = 0; j <= dy; j++ ) {
 	    for ( i = 0; i <= dx; i++ ) {
 		b_cur = fgBucketOffset(min.x, min.y, i, j);
-		if ( b_cur == b ) {
-		    dem.write_area( b_cur );
-		} else {
-		    dem.write_area( b_cur );
-		}
+		dem.write_area( b_cur );
 	    }
 	}
     }
@@ -102,6 +100,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.2  1999/03/10 16:09:44  curt
+// Hacking towards the first working version.
+//
 // Revision 1.1  1999/03/10 01:02:54  curt
 // Initial revision.
 //
diff --git a/DemChop/point2d.hxx b/DemChop/point2d.hxx
new file mode 100644
index 000000000..e4df44488
--- /dev/null
+++ b/DemChop/point2d.hxx
@@ -0,0 +1,62 @@
+// point2d.hxx -- define a 2d point class
+//
+// Written by Curtis Olson, started February 1998.
+//
+// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+//
+
+
+#ifndef _POINT2D_HXX
+#define _POINT2D_HXX
+
+
+#include <list>
+
+
+class point2d {
+public:
+    union {
+	double x;
+	double dist;
+	double lon;
+    };
+    union {
+	double y;
+	double theta;
+	double lat;
+    };
+};
+
+
+// convert a point from cartesian to polar coordinates
+point2d cart_to_polar_2d(point2d in);
+
+
+#endif // _POINT2D_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/10 16:09:45  curt
+// Hacking towards the first working version.
+//
+// Revision 1.1  1998/09/04 23:04:53  curt
+// Beginning of convex hull genereration routine.
+//
+//

From 04b12c5c54938f6054141ff9dedff7c999392058 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 11 Mar 1999 23:31:56 +0000
Subject: [PATCH 205/283] Tweaks to use newbucket.hxx

---
 DEM/dem.cxx |  8 ++++++--
 DEM/dem.hxx | 36 ++++++++++++++++++++----------------
 2 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index f59d4831e..02d6ea16e 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -524,7 +524,7 @@ double fgDEM::interpolate_altitude( double lon, double lat ) {
 
 
 // Use least squares to fit a simpler data set to dem data
-void fgDEM::fit( double error, fgBUCKET *p ) {
+void fgDEM::fit( double error, const FGBucket& p ) {
     double x[DEM_SIZE_1], y[DEM_SIZE_1];
     double m, b, ave_error, max_error;
     double cury, lasty;
@@ -688,7 +688,8 @@ void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
 // Check for an optional "index.node.ex" file in case there is a .poly
 // file to go along with this node file.  Include these nodes first
 // since they are referenced by position from the .poly file.
-void fgDEM::outputmesh_output_nodes( const string& fg_root, fgBUCKET *p ) {
+void fgDEM::outputmesh_output_nodes( const string& fg_root, const FGBucket& p )
+{
     double exnodes[MAX_EX_NODES][3];
     struct stat stat_buf;
     string dir;
@@ -830,6 +831,9 @@ fgDEM::~fgDEM( void ) {
 
 
 // $Log$
+// Revision 1.24  1999/03/11 23:31:56  curt
+// Tweaks to use newbucket.hxx
+//
 // Revision 1.23  1999/03/10 01:09:12  curt
 // Tweaks to go along with scenery tools overhaul.
 // Added a new constructor that accepts the file name.
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 44e91a8b0..57969352a 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -35,9 +35,7 @@
 
 #include <stdio.h>
 
-#include <Bucket/bucketutils.h>
-
-//#include <zlib/zlib.h>
+#include <Bucket/newbucket.hxx>
 #include <Misc/fgstream.hxx>
 
 
@@ -46,6 +44,9 @@
 
 
 class fgDEM {
+
+private:
+
     // file pointer for input
     // gzFile fd;
     fg_gzifstream *in;
@@ -98,11 +99,14 @@ public:
     fgDEM( void );
     fgDEM( const string& file );
 
+    // Destructor
+    ~fgDEM( void );
+
     // open a DEM file (use "-" if input is coming from stdin)
     int open ( const string& file );
 
     // close a DEM file
-    int close ();
+    int close();
 
     // parse a DEM file
     int parse();
@@ -113,21 +117,13 @@ public:
     // read and parse DEM "B" record
     void read_b_record();
 
-    // Informational methods
-    double get_originx( void ) { return originx; }
-    double get_originy( void ) { return originy; }
-    int get_cols( void ) { return cols; }
-    int get_rows( void ) { return rows; }
-    double get_col_step( void ) { return col_step; }
-    double get_row_step( void ) { return row_step; }
-
     // return the current altitude based on mesh data.  We should
     // rewrite this to interpolate exact values, but for now this is
     // good enough
     double interpolate_altitude( double lon, double lat );
 
     // Use least squares to fit a simpler data set to dem data
-    void fit( double error, fgBUCKET *p );
+    void fit( double error, const FGBucket& p );
 
     // Initialize output mesh structure
     void outputmesh_init( void );
@@ -139,10 +135,15 @@ public:
     void outputmesh_set_pt( int i, int j, double value );
 
     // Write out a node file that can be used by the "triangle" program
-    void outputmesh_output_nodes( const string& fg_root, fgBUCKET *p );
+    void outputmesh_output_nodes( const string& fg_root, const FGBucket& p );
 
-    // Destructor
-    ~fgDEM( void );
+    // Informational methods
+    inline double get_originx() const { return originx; }
+    inline double get_originy() const { return originy; }
+    inline int get_cols() const { return cols; }
+    inline int get_rows() const { return rows; }
+    inline double get_col_step() const { return col_step; }
+    inline double get_row_step() const { return row_step; }
 };
 
 
@@ -150,6 +151,9 @@ public:
 
 
 // $Log$
+// Revision 1.11  1999/03/11 23:31:57  curt
+// Tweaks to use newbucket.hxx
+//
 // Revision 1.10  1999/03/10 01:09:13  curt
 // Tweaks to go along with scenery tools overhaul.
 // Added a new constructor that accepts the file name.

From 453178e3d5ebc6d1bb696674ba218ffebcd99db4 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 12 Mar 1999 22:53:07 +0000
Subject: [PATCH 206/283] Added a routine to dump out the portion of the dem
 data covered by a specified bucket.  Other changes related to needs of
 scenery tools overhaul.

---
 DEM/dem.cxx | 181 ++++++++++++++++++++++++++++++++++++----------------
 DEM/dem.hxx |  27 +++++---
 2 files changed, 145 insertions(+), 63 deletions(-)

diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 02d6ea16e..2e1ee2798 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -54,10 +54,11 @@
 #include <Misc/fgstream.hxx>
 #include <Misc/strutils.hxx>
 #include <Include/compiler.h>
+
 FG_USING_NAMESPACE(std);
 
 #include "dem.hxx"
-#include "leastsqs.hxx"
+// #include "leastsqs.hxx"
 
 #include <Include/fg_constants.h>
 
@@ -76,24 +77,25 @@ FG_USING_NAMESPACE(std);
 #endif //0
 
 
-fgDEM::fgDEM( void ) {
-    // cout << "class fgDEM CONstructor called." << endl;
+FGDem::FGDem( void ) {
+    // cout << "class FGDem CONstructor called." << endl;
     dem_data = new float[DEM_SIZE_1][DEM_SIZE_1];
     output_data = new float[DEM_SIZE_1][DEM_SIZE_1];
 }
 
 
-fgDEM::fgDEM( const string &file ) {
-    // cout << "class fgDEM CONstructor called." << endl;
+FGDem::FGDem( const string &file ) {
+    // cout << "class FGDem CONstructor called." << endl;
     dem_data = new float[DEM_SIZE_1][DEM_SIZE_1];
     output_data = new float[DEM_SIZE_1][DEM_SIZE_1];
 
-    fgDEM::open(file);
+    FGDem::open(file);
 }
 
 
 // open a DEM file
-int fgDEM::open ( const string& file ) {
+int
+FGDem::open ( const string& file ) {
     // open input file (or read from stdin)
     if ( file ==  "-" ) {
 	printf("Loading DEM data file: stdin\n");
@@ -115,7 +117,8 @@ int fgDEM::open ( const string& file ) {
 
 
 // close a DEM file
-int fgDEM::close () {
+int
+FGDem::close () {
     // the fg_gzifstream doesn't seem to have a close()
 
     delete in;
@@ -125,7 +128,8 @@ int fgDEM::close () {
 
 
 // return next token from input stream
-string fgDEM::next_token() {
+string
+FGDem::next_token() {
     string token;
 
     *in >> token;
@@ -137,7 +141,8 @@ string fgDEM::next_token() {
 
 
 // return next integer from input stream
-int fgDEM::next_int() {
+int
+FGDem::next_int() {
     int result;
     
     *in >> result;
@@ -147,7 +152,8 @@ int fgDEM::next_int() {
 
 
 // return next double from input stream
-double fgDEM::next_double() {
+double
+FGDem::next_double() {
     double result;
 
     *in >> result;
@@ -157,7 +163,8 @@ double fgDEM::next_double() {
 
 
 // return next exponential num from input stream
-double fgDEM::next_exp() {
+double
+FGDem::next_exp() {
     string token;
     double mantissa;
     int exp, acc;
@@ -201,7 +208,8 @@ double fgDEM::next_exp() {
 
 
 // read and parse DEM "A" record
-int fgDEM::read_a_record() {
+int
+FGDem::read_a_record() {
     int i, inum;
     double dnum;
     string name, token;
@@ -306,32 +314,10 @@ int fgDEM::read_a_record() {
     i = token.length();
     cout << "    length = " << i << "\n";
 
-#if 1
     inum = atoi( token.substr( 0, i - 36 ) );
-    row_step = atof( token.substr( i - 36, 12 ) );
-    col_step = atof( token.substr( i - 24, 12 ) );
-    //token.substr( 25, 12 )
-#else
-    ptr = token.c_str() + i - 12;
-    cout << "    last field = " << ptr << " = " << atof(ptr) << "\n";
-    ptr[0] = '\0';
-
-    ptr = ptr - 12;
-    col_step = atof(ptr);
-    cout << "    last field = " << ptr << " = " << col_step << "\n";
-    ptr[0] = '\0';
-
-    ptr = ptr - 12;
-    row_step = atof(ptr);
-    cout << "    last field = " << ptr << " = " << row_step << "\n";
-    ptr[0] = '\0';
-
-    // accuracy code = atod(token)
-    ptr = ptr - 12;
-    inum = atoi(ptr);
-#endif
+    row_step = atof( token.substr( i - 24, 12 ) );
+    col_step = atof( token.substr( i - 36, 12 ) );
     cout << "    Accuracy code = " << inum << "\n";
-
     cout << "    column step = " << col_step << 
 	"  row step = " << row_step << "\n";
 
@@ -347,7 +333,8 @@ int fgDEM::read_a_record() {
 
 
 // read and parse DEM "B" record
-void fgDEM::read_b_record( ) {
+void
+FGDem::read_b_record( ) {
     string token;
     int i;
 
@@ -384,7 +371,8 @@ void fgDEM::read_b_record( ) {
 
 
 // parse dem file
-int fgDEM::parse( ) {
+int
+FGDem::parse( ) {
     int i;
 
     cur_col = 0;
@@ -409,9 +397,87 @@ int fgDEM::parse( ) {
 }
 
 
-// return the current altitude based on mesh data.  We should rewrite
+// write out the area of data covered by the specified bucket.  Data
+// is written out column by column starting at the lower left hand
+// corner.
+int
+FGDem::write_area( const string& root, FGBucket& b, bool compress ) {
+    char tile_name[256];
+
+    // calculate some boundaries
+    double min_x = ( b.get_center_lon() - 0.5 * b.get_width() ) * 3600.0;
+    double max_x = ( b.get_center_lon() + 0.5 * b.get_width() ) * 3600.0;
+
+    double min_y = ( b.get_center_lat() - 0.5 * b.get_height() ) * 3600.0;
+    double max_y = ( b.get_center_lat() + 0.5 * b.get_height() ) * 3600.0;
+
+    cout << b << endl;
+    cout << "width = " << b.get_width() << " height = " << b.get_height() 
+	 << endl;
+
+    int start_x = (int)((min_x - originx) / col_step);
+    int span_x = (int)(b.get_width() * 3600.0 / col_step);
+
+    int start_y = (int)((min_y - originy) / row_step);
+    int span_y = (int)(b.get_height() * 3600.0 / row_step);
+
+    cout << "start_x = " << start_x << "  span_x = " << span_x << endl;
+    cout << "start_y = " << start_y << "  span_y = " << span_y << endl;
+
+    // Do a simple sanity checking.  But, please, please be nice to
+    // this write_area() routine and feed it buckets that coincide
+    // well with the underlying grid structure and spacing.
+
+    if ( ( min_x < originx )
+	 || ( max_x > originx + cols * col_step )
+	 || ( min_y < originy )
+	 || ( max_y > originy + rows * row_step ) ) {
+	cout << "  ERROR: bucket at least partially outside DEM data range!" <<
+	    endl;
+	return -1;
+    }
+
+    // generate output file name
+    string base = b.gen_base_path();
+    string path = root + "/Scenery/" + base;
+    string command = "mkdir -p " + path;
+    system( command.c_str() );
+
+    long int b_index = b.gen_index();
+    sprintf(tile_name, "%ld", b_index);
+    string demfile = path + "/" + tile_name + ".dem";
+    cout << "demfile = " << demfile << endl;
+
+    // write the file
+    FILE *fp;
+    if ( (fp = fopen(demfile.c_str(), "w")) == NULL ) {
+	cout << "cannot open " << demfile << " for writing!" << endl;
+	exit(-1);
+    }
+
+    fprintf( fp, "%d %d\n", (int)min_x, (int)min_y );
+    fprintf( fp, "%d %d %d %d\n", span_x + 1, (int)col_step, 
+	     span_y + 1, (int)row_step );
+    for ( int i = start_x; i <= start_x + span_x; ++i ) {
+	for ( int j = start_y; j <= start_y + span_y; ++j ) {
+	    fprintf( fp, "%d ", (int)dem_data[i][j] );
+	}
+	fprintf( fp, "\n" );
+    }
+    fclose(fp);
+
+    if ( compress ) {
+	string command = "gzip --best -f " + demfile;
+	system( command.c_str() );
+    }
+}
+
+
+#if 0
+
+// return the current altitude based on grid data.  We should rewrite
 // this to interpolate exact values, but for now this is good enough
-double fgDEM::interpolate_altitude( double lon, double lat ) {
+double FGDem::interpolate_altitude( double lon, double lat ) {
     // we expect incoming (lon,lat) to be in arcsec for now
 
     double xlocal, ylocal, dx, dy, zA, zB, elev;
@@ -524,7 +590,7 @@ double fgDEM::interpolate_altitude( double lon, double lat ) {
 
 
 // Use least squares to fit a simpler data set to dem data
-void fgDEM::fit( double error, const FGBucket& p ) {
+void FGDem::fit( double error, FGBucket& p ) {
     double x[DEM_SIZE_1], y[DEM_SIZE_1];
     double m, b, ave_error, max_error;
     double cury, lasty;
@@ -537,9 +603,9 @@ void fgDEM::fit( double error, const FGBucket& p ) {
     outputmesh_init();
 
     // determine dimensions
-    colmin = p->x * ( (cols - 1) / 8);
+    colmin = p.get_x() * ( (cols - 1) / 8);
     colmax = colmin + ( (cols - 1) / 8);
-    rowmin = p->y * ( (rows - 1) / 8);
+    rowmin = p.get_y() * ( (rows - 1) / 8);
     rowmax = rowmin + ( (rows - 1) / 8);
     printf("Fitting region = %d,%d to %d,%d\n", colmin, rowmin, colmax, rowmax);
     
@@ -660,7 +726,7 @@ void fgDEM::fit( double error, const FGBucket& p ) {
 
 
 // Initialize output mesh structure
-void fgDEM::outputmesh_init( void ) {
+void FGDem::outputmesh_init( void ) {
     int i, j;
     
     for ( j = 0; j < DEM_SIZE_1; j++ ) {
@@ -672,13 +738,13 @@ void fgDEM::outputmesh_init( void ) {
 
 
 // Get the value of a mesh node
-double fgDEM::outputmesh_get_pt( int i, int j ) {
+double FGDem::outputmesh_get_pt( int i, int j ) {
     return ( output_data[i][j] );
 }
 
 
 // Set the value of a mesh node
-void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
+void FGDem::outputmesh_set_pt( int i, int j, double value ) {
     // printf("Setting data[%d][%d] = %.2f\n", i, j, value);
    output_data[i][j] = value;
 }
@@ -688,12 +754,12 @@ void fgDEM::outputmesh_set_pt( int i, int j, double value ) {
 // Check for an optional "index.node.ex" file in case there is a .poly
 // file to go along with this node file.  Include these nodes first
 // since they are referenced by position from the .poly file.
-void fgDEM::outputmesh_output_nodes( const string& fg_root, const FGBucket& p )
+void FGDem::outputmesh_output_nodes( const string& fg_root, FGBucket& p )
 {
     double exnodes[MAX_EX_NODES][3];
     struct stat stat_buf;
     string dir;
-    char base_path[256], file[256], exfile[256];
+    char file[256], exfile[256];
 #ifdef WIN32
     char tmp_path[256];
 #endif
@@ -704,15 +770,15 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, const FGBucket& p )
     int i, j, count, excount, result;
 
     // determine dimensions
-    colmin = p->x * ( (cols - 1) / 8);
+    colmin = p.get_x() * ( (cols - 1) / 8);
     colmax = colmin + ( (cols - 1) / 8);
-    rowmin = p->y * ( (rows - 1) / 8);
+    rowmin = p.get_y() * ( (rows - 1) / 8);
     rowmax = rowmin + ( (rows - 1) / 8);
     cout << "  dumping region = " << colmin << "," << rowmin << " to " <<
 	colmax << "," << rowmax << "\n";
 
     // generate the base directory
-    fgBucketGenBasePath(p, base_path);
+    string base_path = p.gen_base_path();
     cout << "fg_root = " << fg_root << "  Base Path = " << base_path << endl;
     dir = fg_root + "/Scenery/" + base_path;
     cout << "Dir = " << dir << endl;
@@ -753,7 +819,7 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, const FGBucket& p )
     }
 
     // get index and generate output file name
-    index = fgBucketGenIndex(p);
+    index = p.gen_index();
     sprintf(file, "%s/%ld.node", dir.c_str(), index);
 
     // get (optional) extra node file name (in case there is matching
@@ -821,16 +887,21 @@ void fgDEM::outputmesh_output_nodes( const string& fg_root, const FGBucket& p )
 
     fclose(fd);
 }
+#endif
 
 
-fgDEM::~fgDEM( void ) {
-    // printf("class fgDEM DEstructor called.\n");
+FGDem::~FGDem( void ) {
+    // printf("class FGDem DEstructor called.\n");
     delete [] dem_data;
     delete [] output_data;
 }
 
 
 // $Log$
+// Revision 1.25  1999/03/12 22:53:07  curt
+// Added a routine to dump out the portion of the dem data covered by a
+// specified bucket.  Other changes related to needs of scenery tools overhaul.
+//
 // Revision 1.24  1999/03/11 23:31:56  curt
 // Tweaks to use newbucket.hxx
 //
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 57969352a..832a957ae 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -43,7 +43,7 @@
 #define DEM_SIZE_1 1201
 
 
-class fgDEM {
+class FGDem {
 
 private:
 
@@ -60,7 +60,7 @@ private:
     // Distance between column and row data points (in arc seconds)
     double col_step, row_step;
     
-    // pointers to the actual mesh data allocated here
+    // pointers to the actual grid data allocated here
     float (*dem_data)[DEM_SIZE_1];
     float (*output_data)[DEM_SIZE_1];
 
@@ -96,11 +96,11 @@ private:
 public:
 
     // Constructor
-    fgDEM( void );
-    fgDEM( const string& file );
+    FGDem( void );
+    FGDem( const string& file );
 
     // Destructor
-    ~fgDEM( void );
+    ~FGDem( void );
 
     // open a DEM file (use "-" if input is coming from stdin)
     int open ( const string& file );
@@ -117,13 +117,19 @@ public:
     // read and parse DEM "B" record
     void read_b_record();
 
-    // return the current altitude based on mesh data.  We should
+    // write out the area of data covered by the specified bucket.
+    // Data is written out column by column starting at the lower left
+    // hand corner.
+    int write_area( const string& root, FGBucket& b, bool compress );
+
+#if 0
+    // return the current altitude based on grid data.  We should
     // rewrite this to interpolate exact values, but for now this is
     // good enough
     double interpolate_altitude( double lon, double lat );
 
     // Use least squares to fit a simpler data set to dem data
-    void fit( double error, const FGBucket& p );
+    void fit( double error, FGBucket& p );
 
     // Initialize output mesh structure
     void outputmesh_init( void );
@@ -135,7 +141,8 @@ public:
     void outputmesh_set_pt( int i, int j, double value );
 
     // Write out a node file that can be used by the "triangle" program
-    void outputmesh_output_nodes( const string& fg_root, const FGBucket& p );
+    void outputmesh_output_nodes( const string& fg_root, FGBucket& p );
+#endif
 
     // Informational methods
     inline double get_originx() const { return originx; }
@@ -151,6 +158,10 @@ public:
 
 
 // $Log$
+// Revision 1.12  1999/03/12 22:53:09  curt
+// Added a routine to dump out the portion of the dem data covered by a
+// specified bucket.  Other changes related to needs of scenery tools overhaul.
+//
 // Revision 1.11  1999/03/11 23:31:57  curt
 // Tweaks to use newbucket.hxx
 //

From e2267b3f124ce8aa492f5950bda5b3e47da9f2b4 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 12 Mar 1999 22:53:45 +0000
Subject: [PATCH 207/283] First working version!

---
 DemChop/Makefile.am |  4 ++++
 DemChop/demchop.cxx | 21 +++++++++++++--------
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/DemChop/Makefile.am b/DemChop/Makefile.am
index ff5474731..46710ee44 100644
--- a/DemChop/Makefile.am
+++ b/DemChop/Makefile.am
@@ -33,6 +33,7 @@ demchop_LDADD = \
 	$(top_builddir)/Tools/Lib/DEM/libDEM.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
+	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/zlib/libz.a \
 	$(base_LIBS)
 
@@ -46,6 +47,9 @@ CXXFLAGS = -g
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.2  1999/03/12 22:53:45  curt
+# First working version!
+#
 # Revision 1.1  1999/03/10 01:02:54  curt
 # Initial revision.
 #
diff --git a/DemChop/demchop.cxx b/DemChop/demchop.cxx
index 5a1b66dc6..8182c8d8e 100644
--- a/DemChop/demchop.cxx
+++ b/DemChop/demchop.cxx
@@ -48,7 +48,7 @@ int main(int argc, char **argv) {
 
     fglog().setLogLevels( FG_ALL, FG_DEBUG );
 
-    if ( argc != 4 ) {
+    if ( argc != 3 ) {
 	FG_LOG( FG_GENERAL, FG_ALERT, 
 		"Usage " << argv[0] << " <dem_file> <work_dir>" );
 	exit(-1);
@@ -59,21 +59,23 @@ int main(int argc, char **argv) {
     string command = "mkdir -p " + work_dir;
     system( command.c_str() );
 
-    fgDEM dem(dem_name);
+    FGDem dem(dem_name);
     dem.parse();
     dem.close();
 
     point2d min, max;
-    min.x = dem.get_originx() / 3600.0;
-    min.y = dem.get_originy() / 3600.0;
+    min.x = dem.get_originx() / 3600.0 + FG_HALF_BUCKET_SPAN;
+    min.y = dem.get_originy() / 3600.0 + FG_HALF_BUCKET_SPAN;
     FGBucket b_min( min.x, min.y );
 
-    max.x = min.x + ( dem.get_cols() * dem.get_col_step() ) / 3600.0;
-    max.y = min.y + ( dem.get_rows() * dem.get_row_step() ) / 3600.0;
+    max.x = (dem.get_originx() + dem.get_cols() * dem.get_col_step()) / 3600.0 
+	- FG_HALF_BUCKET_SPAN;
+    max.y = (dem.get_originy() + dem.get_rows() * dem.get_row_step()) / 3600.0 
+	- FG_HALF_BUCKET_SPAN;
     FGBucket b_max( max.x, max.y );
 
     if ( b_min == b_max ) {
-	dem.write_area( b_min );
+	dem.write_area( work_dir, b_min, true );
     } else {
 	FGBucket b_cur;
 	int dx, dy, i, j;
@@ -90,7 +92,7 @@ int main(int argc, char **argv) {
 	for ( j = 0; j <= dy; j++ ) {
 	    for ( i = 0; i <= dx; i++ ) {
 		b_cur = fgBucketOffset(min.x, min.y, i, j);
-		dem.write_area( b_cur );
+		dem.write_area( work_dir, b_cur, true );
 	    }
 	}
     }
@@ -100,6 +102,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.3  1999/03/12 22:53:46  curt
+// First working version!
+//
 // Revision 1.2  1999/03/10 16:09:44  curt
 // Hacking towards the first working version.
 //

From 200ef3ceea4f676ac90afbe32f030748963d60e2 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 12 Mar 1999 22:54:04 +0000
Subject: [PATCH 208/283] Convert fgDEM to FGDem ...

---
 DemInfo/deminfo.cxx | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/DemInfo/deminfo.cxx b/DemInfo/deminfo.cxx
index 27f1f4357..75f9c2f55 100644
--- a/DemInfo/deminfo.cxx
+++ b/DemInfo/deminfo.cxx
@@ -37,7 +37,7 @@
 
 int main(int argc, char **argv) {
     // DEM data
-    fgDEM dem;
+    FGDem dem;
     string filename;
     double error;
     int i, j;
@@ -54,8 +54,8 @@ int main(int argc, char **argv) {
 
     if ( dem.read_a_record() ) {
 	cout << "Results = " << filename << "  "
-	     << dem.info_originx() / 3600.0 << " "
-	     << dem.info_originy() / 3600.0 << "\n";
+	     << dem.get_originx() / 3600.0 << " "
+	     << dem.get_originy() / 3600.0 << "\n";
     } else {
 	cout << "Error parsing DEM file.\n";
     }
@@ -67,6 +67,9 @@ int main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.3  1999/03/12 22:54:04  curt
+// Convert fgDEM to FGDem ...
+//
 // Revision 1.2  1998/09/19 18:01:22  curt
 // Support for changes to libDEM.a
 //

From 49f4a768939fbe9604362605ed8989ae1501c930 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 12 Mar 1999 22:54:19 +0000
Subject: [PATCH 209/283] Rearrange a bit of code ...

---
 GenAirports/main.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index 5ef504234..12501d0d8 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -53,12 +53,12 @@ void write_airport( int p_index, list_container hull_list, FGBucket b,
 		    const string& root, const bool cut_and_keep ) {
     char tile_name[256], poly_index[256];
 
-    long int b_index = b.gen_index();
     string base = b.gen_base_path();
     string path = root + "/Scenery/" + base;
     string command = "mkdir -p " + path;
     system( command.c_str() );
 
+    long int b_index = b.gen_index();
     sprintf(tile_name, "%ld", b_index);
     string aptfile = path + "/" + tile_name;
 
@@ -344,6 +344,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.9  1999/03/12 22:54:19  curt
+// Rearrange a bit of code ...
+//
 // Revision 1.8  1999/03/01 15:35:26  curt
 // Fixed bug in output format generated.
 //

From 5fe3a80ae34da61f1d2452b345c11b3eff3a82de Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 17:40:36 +0000
Subject: [PATCH 210/283] Moved point interpolation and least squares fitting
 to contruction program area. Moved leastsqs.* to Lib/Math/

---
 DEM/Makefile.am  |   4 +-
 DEM/dem.cxx      |  52 ++++++-------------
 DEM/dem.hxx      |  19 +++----
 DEM/leastsqs.cxx | 126 -----------------------------------------------
 DEM/leastsqs.hxx |  84 -------------------------------
 5 files changed, 26 insertions(+), 259 deletions(-)
 delete mode 100644 DEM/leastsqs.cxx
 delete mode 100644 DEM/leastsqs.hxx

diff --git a/DEM/Makefile.am b/DEM/Makefile.am
index ec72f2e38..91bfd90d6 100644
--- a/DEM/Makefile.am
+++ b/DEM/Makefile.am
@@ -1,11 +1,11 @@
 noinst_LIBRARIES = libDEM.a
 
-libDEM_a_SOURCES = dem.cxx dem.hxx leastsqs.cxx leastsqs.hxx
+libDEM_a_SOURCES = dem.cxx dem.hxx
 
 INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
 # setting it to "-g"
-CXXFLAGS = -g
+# CXXFLAGS = -g
 
diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index 2e1ee2798..b7fdbfc74 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -1,10 +1,8 @@
-// -*- Mode: C++ -*-
-//
-// dem.c -- DEM management class
+// dem.cxx -- DEM management class
 //
 // Written by Curtis Olson, started March 1998.
 //
-// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+// Copyright (C) 1998  Curtis L. Olson  - curt@flightgear.org
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
@@ -35,32 +33,26 @@
 #include <math.h>     // rint()
 #include <stdio.h>
 #include <string.h>
+
 #ifdef HAVE_SYS_STAT_H
 #  include <sys/stat.h> // stat()
 #endif
+
 #ifdef FG_HAVE_STD_INCLUDES
 #  include <cerrno>
 #else
 #  include <errno.h>
 #endif
+
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>   // stat()
 #endif
-#include <string>
 
-#include STL_IOSTREAM
-
-// #include <zlib/zlib.h>
 #include <Misc/fgstream.hxx>
 #include <Misc/strutils.hxx>
-#include <Include/compiler.h>
-
-FG_USING_NAMESPACE(std);
+#include <Include/fg_constants.h>
 
 #include "dem.hxx"
-// #include "leastsqs.hxx"
-
-#include <Include/fg_constants.h>
 
 
 #define MAX_EX_NODES 10000
@@ -166,13 +158,9 @@ FGDem::next_double() {
 double
 FGDem::next_exp() {
     string token;
-    double mantissa;
-    int exp, acc;
-    int i;
 
     token = next_token();
 
-#if 1
     const char* p = token.c_str();
     char buf[64];
     char* bp = buf;
@@ -186,24 +174,6 @@ FGDem::next_exp() {
     }
     *bp = 0;
     return ::atof( buf );
-#else
-    sscanf(token.c_str(), "%lfD%d", &mantissa, &exp);
-
-    // cout << "    Mantissa = " << mantissa << "  Exp = " << exp << "\n";
-
-    acc = 1;
-    if ( exp > 0 ) {
-	for ( i = 1; i <= exp; i++ ) {
-	    acc *= 10;
-	}
-    } else if ( exp < 0 ) {
-	for ( i = -1; i >= exp; i-- ) {
-	    acc /= 10;
-	}
-    }
-
-    return( (int)rint(mantissa * (double)acc) );
-#endif
 }
 
 
@@ -214,7 +184,6 @@ FGDem::read_a_record() {
     double dnum;
     string name, token;
     char c;
-    char *ptr;
 
     // get the name field (144 characters)
     for ( i = 0; i < 144; i++ ) {
@@ -434,7 +403,7 @@ FGDem::write_area( const string& root, FGBucket& b, bool compress ) {
 	 || ( max_y > originy + rows * row_step ) ) {
 	cout << "  ERROR: bucket at least partially outside DEM data range!" <<
 	    endl;
-	return -1;
+	return 0;
     }
 
     // generate output file name
@@ -470,6 +439,8 @@ FGDem::write_area( const string& root, FGBucket& b, bool compress ) {
 	string command = "gzip --best -f " + demfile;
 	system( command.c_str() );
     }
+
+    return 1;
 }
 
 
@@ -898,6 +869,11 @@ FGDem::~FGDem( void ) {
 
 
 // $Log$
+// Revision 1.26  1999/03/13 17:40:37  curt
+// Moved point interpolation and least squares fitting to contruction program
+// area.
+// Moved leastsqs.* to Lib/Math/
+//
 // Revision 1.25  1999/03/12 22:53:07  curt
 // Added a routine to dump out the portion of the dem data covered by a
 // specified bucket.  Other changes related to needs of scenery tools overhaul.
diff --git a/DEM/dem.hxx b/DEM/dem.hxx
index 832a957ae..46849e3a4 100644
--- a/DEM/dem.hxx
+++ b/DEM/dem.hxx
@@ -1,10 +1,8 @@
-// -*- Mode: C++ -*-
-//
-// dem.h -- DEM management class
+// dem.hxx -- DEM management class
 //
 // Written by Curtis Olson, started March 1998.
 //
-// Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
+// Copyright (C) 1998  Curtis L. Olson  - curt@flightgear.org
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
@@ -24,8 +22,8 @@
 // (Log is kept at end of this file)
 
 
-#ifndef _DEM_H
-#define _DEM_H
+#ifndef _DEM_HXX
+#define _DEM_HXX
 
 
 #ifndef __cplusplus                                                          
@@ -33,8 +31,6 @@
 #endif                                   
 
 
-#include <stdio.h>
-
 #include <Bucket/newbucket.hxx>
 #include <Misc/fgstream.hxx>
 
@@ -154,10 +150,15 @@ public:
 };
 
 
-#endif // _DEM_H
+#endif // _DEM_HXX
 
 
 // $Log$
+// Revision 1.13  1999/03/13 17:40:39  curt
+// Moved point interpolation and least squares fitting to contruction program
+// area.
+// Moved leastsqs.* to Lib/Math/
+//
 // Revision 1.12  1999/03/12 22:53:09  curt
 // Added a routine to dump out the portion of the dem data covered by a
 // specified bucket.  Other changes related to needs of scenery tools overhaul.
diff --git a/DEM/leastsqs.cxx b/DEM/leastsqs.cxx
deleted file mode 100644
index a97581de4..000000000
--- a/DEM/leastsqs.cxx
+++ /dev/null
@@ -1,126 +0,0 @@
-// leastsqs.c -- Implements a simple linear least squares best fit routine
-//
-// Written by Curtis Olson, started September 1997.
-//
-// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-// (Log is kept at end of this file)
-//
-
-
-#include <stdio.h>
-
-#include "leastsqs.hxx"
-
-
-/* 
-Least squares fit:
-
-y = b0 + b1x
-
-     n*sum(xi*yi) - (sum(xi)*sum(yi))
-b1 = --------------------------------
-     n*sum(xi^2) - (sum(xi))^2
-
-
-b0 = sum(yi)/n - b1*(sum(xi)/n)
-*/
-
-void least_squares(double *x, double *y, int n, double *m, double *b) {
-    double sum_xi, sum_yi, sum_xi_2, sum_xi_yi;
-    int i;
-
-    sum_xi = sum_yi = sum_xi_2 = sum_xi_yi = 0.0;
-
-    for ( i = 0; i < n; i++ ) {
-	sum_xi += x[i];
-	sum_yi += y[i];
-	sum_xi_2 += x[i] * x[i];
-	sum_xi_yi += x[i] * y[i];
-    }
-
-    /* printf("sum(xi)=%.2f  sum(yi)=%.2f  sum(xi^2)=%.2f  sum(xi*yi)=%.2f\n",
-	   sum_xi, sum_yi, sum_xi_2, sum_xi_yi); */
-
-    *m = ( (double)n * sum_xi_yi - sum_xi * sum_yi ) / 
-	( (double)n * sum_xi_2 - sum_xi * sum_xi );
-    *b = (sum_yi / (double)n) - (*m) * (sum_xi / (double)n);
-
-    /* printf("slope = %.2f  intercept = %.2f\n", *m, *b); */
-}
-
-
-/* 
-  return the least squares error:
-
-              (y[i] - y_hat[i])^2
-              -------------------
-                      n
- */
-double least_squares_error(double *x, double *y, int n, double m, double b) {
-    int i;
-    double error, sum;
-
-    sum = 0.0;
-
-    for ( i = 0; i < n; i++ ) {
-	error = y[i] - (m * x[i] + b);
-	sum += error * error;
-	// printf("%.2f %.2f\n", error, sum);
-    }
-
-    return ( sum / (double)n );
-}
-
-
-/* 
-  return the maximum least squares error:
-
-              (y[i] - y_hat[i])^2
- */
-double least_squares_max_error(double *x, double *y, int n, double m, double b){
-    int i;
-    double error, max_error;
-
-    max_error = 0.0;
-
-    for ( i = 0; i < n; i++ ) {
-	error = y[i] - (m * x[i] + b);
-	error = error * error;
-	if ( error > max_error ) {
-	    max_error = error;
-	}
-    }
-
-    return ( max_error );
-}
-
-
-// $Log$
-// Revision 1.2  1998/04/21 17:03:41  curt
-// Prepairing for C++ integration.
-//
-// Revision 1.1  1998/04/08 22:57:24  curt
-// Adopted Gnu automake/autoconf system.
-//
-// Revision 1.1  1998/03/19 02:54:47  curt
-// Reorganized into a class lib called fgDEM.
-//
-// Revision 1.1  1997/10/13 17:02:35  curt
-// Initial revision.
-//
diff --git a/DEM/leastsqs.hxx b/DEM/leastsqs.hxx
deleted file mode 100644
index 71760ba70..000000000
--- a/DEM/leastsqs.hxx
+++ /dev/null
@@ -1,84 +0,0 @@
-// leastsqs.h -- Implements a simple linear least squares best fit routine
-//
-// Written by Curtis Olson, started September 1997.
-//
-// Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-// (Log is kept at end of this file)
-///
-
-
-#ifndef _LEASTSQS_H
-#define _LEASTSQS_H
-
-
-#ifndef __cplusplus                                                          
-# error This library requires C++
-#endif                                   
-
-
-/* 
-Least squares fit:
-
-y = b0 + b1x
-
-     n*sum(xi*yi) - (sum(xi)*sum(yi))
-b1 = --------------------------------
-     n*sum(xi^2) - (sum(xi))^2
-
-
-b0 = sum(yi)/n - b1*(sum(xi)/n)
-*/
-
-void least_squares(double *x, double *y, int n, double *m, double *b);
-
-
-/* 
-  return the least squares error:
-
-              (y[i] - y_hat[i])^2
-              -------------------
-                      n
-*/
-double least_squares_error(double *x, double *y, int n, double m, double b);
-
-
-/* 
-  return the maximum least squares error:
-
-              (y[i] - y_hat[i])^2
-*/
-double least_squares_max_error(double *x, double *y, int n, double m, double b);
-
-
-#endif // _LEASTSQS_H
-
-
-// $Log$
-// Revision 1.2  1998/04/21 17:03:42  curt
-// Prepairing for C++ integration.
-//
-// Revision 1.1  1998/04/08 22:57:25  curt
-// Adopted Gnu automake/autoconf system.
-//
-// Revision 1.1  1998/03/19 02:54:48  curt
-// Reorganized into a class lib called fgDEM.
-//
-// Revision 1.1  1997/10/13 17:02:35  curt
-// Initial revision.
-//

From 2e20f3226746f2804acb40b375dc0b8842d1ab3c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 18:45:02 +0000
Subject: [PATCH 211/283] Initial revision. (derived from libDEM.a code.)

---
 Array/Makefile.am   |  22 ++
 Array/array.cxx     | 557 ++++++++++++++++++++++++++++++++++++++++++++
 Array/array.hxx     | 136 +++++++++++
 Array/testarray.cxx |  37 +++
 4 files changed, 752 insertions(+)
 create mode 100644 Array/Makefile.am
 create mode 100644 Array/array.cxx
 create mode 100644 Array/array.hxx
 create mode 100644 Array/testarray.cxx

diff --git a/Array/Makefile.am b/Array/Makefile.am
new file mode 100644
index 000000000..ea97e0d5f
--- /dev/null
+++ b/Array/Makefile.am
@@ -0,0 +1,22 @@
+noinst_LIBRARIES = libArray.a
+
+libArray_a_SOURCES = array.cxx array.hxx
+
+bin_PROGRAMS = testarray
+
+testarray_SOURCES = testarray.cxx
+
+testarray_LDADD = \
+	$(top_builddir)/Tools/Construct/Array/libArray.a \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/Math/libMath.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
+	$(top_builddir)/Lib/zlib/libz.a
+
+INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+
+# We can't build this with "-O2" (optimization) since this causes a seg fault
+# I haven't found a way to strip this out of the CXXFLAGS, so I'm just
+# setting it to "-g"
+CXXFLAGS = -g
+
diff --git a/Array/array.cxx b/Array/array.cxx
new file mode 100644
index 000000000..ddb1921f9
--- /dev/null
+++ b/Array/array.cxx
@@ -0,0 +1,557 @@
+// array.cxx -- Array management class
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998 - 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <Include/compiler.h>
+
+// #include <ctype.h>    // isspace()
+// #include <stdlib.h>   // atoi()
+// #include <math.h>     // rint()
+// #include <stdio.h>
+// #include <string.h>
+// #ifdef HAVE_SYS_STAT_H
+// #  include <sys/stat.h> // stat()
+// #endif
+// #ifdef FG_HAVE_STD_INCLUDES
+// #  include <cerrno>
+// #else
+// #  include <errno.h>
+// #endif
+// #ifdef HAVE_UNISTD_H
+// # include <unistd.h>   // stat()
+// #endif
+
+#include STL_STRING
+
+#include <Include/fg_constants.h>
+#include <Misc/fgstream.hxx>
+#include <Misc/strutils.hxx>
+#include <Math/leastsqs.hxx>
+
+#include "array.hxx"
+
+FG_USING_STD(string);
+
+
+FGArray::FGArray( void ) {
+    // cout << "class FGArray CONstructor called." << endl;
+    in_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
+    out_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
+}
+
+
+FGArray::FGArray( const string &file ) {
+    // cout << "class FGArray CONstructor called." << endl;
+    in_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
+    out_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
+
+    FGArray::open(file);
+}
+
+
+// open an Array file
+int
+FGArray::open( const string& file ) {
+    // open input file (or read from stdin)
+    if ( file ==  "-" ) {
+	cout << "Opening array data pipe from stdin" << endl;
+	// fd = stdin;
+	// fd = gzdopen(STDIN_FILENO, "r");
+	cout << "Not yet ported ..." << endl;
+	return 0;
+    } else {
+	in = new fg_gzifstream( file );
+	if ( !(*in) ) {
+	    cout << "Cannot open " << file << endl;
+	    return 0;
+	}
+	cout << "Opening array data file: " << file << endl;
+    }
+
+    return 1;
+}
+
+
+// close an Array file
+int
+FGArray::close() {
+    // the fg_gzifstream doesn't seem to have a close()
+
+    delete in;
+
+    return 1;
+}
+
+
+// parse Array file
+int
+FGArray::parse() {
+    int i;
+
+    // cur_col = 0;
+
+    *in >> originx >> originy;
+    *in >> cols >> col_step;
+    *in >> rows >> row_step;
+
+    cout << "    origin  = " << originx << "  " << originy << endl;
+    cout << "    cols = " << cols << "  rows = " << rows << endl;
+    cout << "    col_step = " << col_step << "  row_step = " << row_step <<endl;
+
+    for ( int i = 0; i < cols; i++ ) {
+	for ( int j = 0; j < rows; j++ ) {
+	    *in >> in_data[i][j];
+	}
+    }
+
+    cout << "    Done parsing\n";
+
+    return 1;
+}
+
+
+// Initialize output mesh structure
+void FGArray::outputmesh_init( void ) {
+    int i, j;
+    
+    for ( j = 0; j < ARRAY_SIZE_1; j++ ) {
+	for ( i = 0; i < ARRAY_SIZE_1; i++ ) {
+	    out_data[i][j] = -9999.0;
+	}
+    }
+}
+
+
+// Get the value of a mesh node
+double FGArray::outputmesh_get_pt( int i, int j ) {
+    return ( out_data[i][j] );
+}
+
+
+// Set the value of a mesh node
+void FGArray::outputmesh_set_pt( int i, int j, double value ) {
+    // cout << "Setting data[" << i << "][" << j << "] = " << value << endl;
+   out_data[i][j] = value;
+}
+
+
+// Use least squares to fit a simpler data set to dem data
+void FGArray::fit( FGBucket& p, double error ) {
+    double x[ARRAY_SIZE_1], y[ARRAY_SIZE_1];
+    double m, b, max_error, error_sq;
+    double x1, y1;
+    // double ave_error;
+    double cury, lasty;
+    int n, row, start, end;
+    int colmin, colmax, rowmin, rowmax;
+    bool good_fit;
+    // FILE *dem, *fit, *fit1;
+
+    error_sq = error * error;
+
+    cout << "Initializing output mesh structure" << endl;
+    outputmesh_init();
+
+    // determine dimensions
+    colmin = 0;
+    colmax = cols;
+    rowmin = 0;
+    rowmax = rows;
+    cout << "Fitting region = " << colmin << "," << rowmin << " to " 
+	 << colmax << "," << rowmax << endl;;
+    
+    // include the corners explicitly
+    outputmesh_set_pt(colmin, rowmin, in_data[colmin][rowmin]);
+    outputmesh_set_pt(colmin, rowmax, in_data[colmin][rowmax]);
+    outputmesh_set_pt(colmax, rowmax, in_data[colmax][rowmax]);
+    outputmesh_set_pt(colmax, rowmin, in_data[colmax][rowmin]);
+
+    cout << "Beginning best fit procedure" << endl;
+
+    for ( row = rowmin; row < rowmax; row++ ) {
+	// fit  = fopen("fit.dat",  "w");
+	// fit1 = fopen("fit1.dat", "w");
+
+	start = colmin;
+
+	// cout << "    fitting row = " << row << endl;
+
+	while ( start < colmax - 1 ) {
+	    end = start + 1;
+	    good_fit = true;
+
+	    x[0] = start * col_step;
+	    y[0] = in_data[start][row];
+
+	    x[1] = end * col_step;
+	    y[1] = in_data[end][row];
+
+	    n = 2;
+
+	    // cout << "Least square of first 2 points" << endl;
+	    least_squares(x, y, n, &m, &b);
+
+	    end++;
+
+	    while ( (end < colmax) && good_fit ) {
+		++n;
+		// cout << "Least square of first " << n << " points" << endl;
+		x[n-1] = x1 = end * col_step;
+		y[n-1] = y1 = in_data[end][row];
+		least_squares_update(x1, y1, &m, &b);
+		// ave_error = least_squares_error(x, y, n, m, b);
+		max_error = least_squares_max_error(x, y, n, m, b);
+
+		/*
+		printf("%d - %d  ave error = %.2f  max error = %.2f  y = %.2f*x + %.2f\n", 
+		start, end, ave_error, max_error, m, b);
+		
+		f = fopen("gnuplot.dat", "w");
+		for ( j = 0; j <= end; j++) {
+		    fprintf(f, "%.2f %.2f\n", 0.0 + ( j * col_step ), 
+			    in_data[row][j]);
+		}
+		for ( j = start; j <= end; j++) {
+		    fprintf(f, "%.2f %.2f\n", 0.0 + ( j * col_step ), 
+			    in_data[row][j]);
+		}
+		fclose(f);
+
+		printf("Please hit return: "); gets(junk);
+		*/
+
+		if ( max_error > error_sq ) {
+		    good_fit = false;
+		}
+		
+		end++;
+	    }
+
+	    if ( !good_fit ) {
+		// error exceeded the threshold, back up
+		end -= 2;  // back "end" up to the last good enough fit
+		n--;       // back "n" up appropriately too
+	    } else {
+		// we popped out of the above loop while still within
+		// the error threshold, so we must be at the end of
+		// the data set
+		end--;
+	    }
+	    
+	    least_squares(x, y, n, &m, &b);
+	    // ave_error = least_squares_error(x, y, n, m, b);
+	    max_error = least_squares_max_error(x, y, n, m, b);
+
+	    /*
+	    printf("\n");
+	    printf("%d - %d  ave error = %.2f  max error = %.2f  y = %.2f*x + %.2f\n", 
+		   start, end, ave_error, max_error, m, b);
+	    printf("\n");
+
+	    fprintf(fit1, "%.2f %.2f\n", x[0], m * x[0] + b);
+	    fprintf(fit1, "%.2f %.2f\n", x[end-start], m * x[end-start] + b);
+	    */
+
+	    if ( start > colmin ) {
+		// skip this for the first line segment
+		cury = m * x[0] + b;
+		outputmesh_set_pt(start, row, (lasty + cury) / 2);
+		// fprintf(fit, "%.2f %.2f\n", x[0], (lasty + cury) / 2);
+	    }
+
+	    lasty = m * x[end-start] + b;
+	    start = end;
+	}
+
+	/*
+	fclose(fit);
+	fclose(fit1);
+
+	dem = fopen("gnuplot.dat", "w");
+	for ( j = 0; j < ARRAY_SIZE_1; j++) {
+	    fprintf(dem, "%.2f %.2f\n", 0.0 + ( j * col_step ), 
+		    in_data[j][row]);
+	} 
+	fclose(dem);
+	*/
+
+	// NOTICE, this is for testing only.  This instance of
+        // output_nodes should be removed.  It should be called only
+        // once at the end once all the nodes have been generated.
+	// newmesh_output_nodes(&nm, "mesh.node");
+	// printf("Please hit return: "); gets(junk);
+    }
+
+    // outputmesh_output_nodes(fg_root, p);
+}
+
+
+// return the current altitude based on grid data.  We should rewrite
+// this to interpolate exact values, but for now this is good enough
+double FGArray::interpolate_altitude( double lon, double lat ) {
+    // we expect incoming (lon,lat) to be in arcsec for now
+
+    double xlocal, ylocal, dx, dy, zA, zB, elev;
+    int x1, x2, x3, y1, y2, y3;
+    float z1, z2, z3;
+    int xindex, yindex;
+
+    /* determine if we are in the lower triangle or the upper triangle 
+       ______
+       |   /|
+       |  / |
+       | /  |
+       |/   |
+       ------
+
+       then calculate our end points
+     */
+
+    xlocal = (lon - originx) / col_step;
+    ylocal = (lat - originy) / row_step;
+
+    xindex = (int)(xlocal);
+    yindex = (int)(ylocal);
+
+    // printf("xindex = %d  yindex = %d\n", xindex, yindex);
+
+    if ( xindex + 1 == cols ) {
+	xindex--;
+    }
+
+    if ( yindex + 1 == rows ) {
+	yindex--;
+    }
+
+    if ( (xindex < 0) || (xindex + 1 >= cols) ||
+	 (yindex < 0) || (yindex + 1 >= rows) ) {
+	cout << "WARNING: Attempt to interpolate value outside of array!!!" 
+	     << endl;
+	return(-9999);
+    }
+
+    dx = xlocal - xindex;
+    dy = ylocal - yindex;
+
+    if ( dx > dy ) {
+	// lower triangle
+	// printf("  Lower triangle\n");
+
+	x1 = xindex; 
+	y1 = yindex; 
+	z1 = in_data[x1][y1];
+
+	x2 = xindex + 1; 
+	y2 = yindex; 
+	z2 = in_data[x2][y2];
+				  
+	x3 = xindex + 1; 
+	y3 = yindex + 1; 
+	z3 = in_data[x3][y3];
+
+	// printf("  dx = %.2f  dy = %.2f\n", dx, dy);
+	// printf("  (x1,y1,z1) = (%d,%d,%d)\n", x1, y1, z1);
+	// printf("  (x2,y2,z2) = (%d,%d,%d)\n", x2, y2, z2);
+	// printf("  (x3,y3,z3) = (%d,%d,%d)\n", x3, y3, z3);
+
+	zA = dx * (z2 - z1) + z1;
+	zB = dx * (z3 - z1) + z1;
+	
+	// printf("  zA = %.2f  zB = %.2f\n", zA, zB);
+
+	if ( dx > FG_EPSILON ) {
+	    elev = dy * (zB - zA) / dx + zA;
+	} else {
+	    elev = zA;
+	}
+    } else {
+	// upper triangle
+	// printf("  Upper triangle\n");
+
+	x1 = xindex; 
+	y1 = yindex; 
+	z1 = in_data[x1][y1];
+
+	x2 = xindex; 
+	y2 = yindex + 1; 
+	z2 = in_data[x2][y2];
+				  
+	x3 = xindex + 1; 
+	y3 = yindex + 1; 
+	z3 = in_data[x3][y3];
+
+	// printf("  dx = %.2f  dy = %.2f\n", dx, dy);
+	// printf("  (x1,y1,z1) = (%d,%d,%d)\n", x1, y1, z1);
+	// printf("  (x2,y2,z2) = (%d,%d,%d)\n", x2, y2, z2);
+	// printf("  (x3,y3,z3) = (%d,%d,%d)\n", x3, y3, z3);
+ 
+	zA = dy * (z2 - z1) + z1;
+	zB = dy * (z3 - z1) + z1;
+	
+	// printf("  zA = %.2f  zB = %.2f\n", zA, zB );
+	// printf("  xB - xA = %.2f\n", col_step * dy / row_step);
+
+	if ( dy > FG_EPSILON ) {
+	    elev = dx * (zB - zA) / dy    + zA;
+	} else {
+	    elev = zA;
+	}
+    }
+
+    return(elev);
+}
+
+
+#if 0
+// Write out a node file that can be used by the "triangle" program.
+// Check for an optional "index.node.ex" file in case there is a .poly
+// file to go along with this node file.  Include these nodes first
+// since they are referenced by position from the .poly file.
+void FGArray::outputmesh_output_nodes( const string& fg_root, FGBucket& p )
+{
+    double exnodes[MAX_EX_NODES][3];
+    struct stat stat_buf;
+    string dir;
+    char file[256], exfile[256];
+#ifdef WIN32
+    char tmp_path[256];
+#endif
+    string command;
+    FILE *fd;
+    long int index;
+    int colmin, colmax, rowmin, rowmax;
+    int i, j, count, excount, result;
+
+    // determine dimensions
+    colmin = p.get_x() * ( (cols - 1) / 8);
+    colmax = colmin + ( (cols - 1) / 8);
+    rowmin = p.get_y() * ( (rows - 1) / 8);
+    rowmax = rowmin + ( (rows - 1) / 8);
+    cout << "  dumping region = " << colmin << "," << rowmin << " to " <<
+	colmax << "," << rowmax << "\n";
+
+    // generate the base directory
+    string base_path = p.gen_base_path();
+    cout << "fg_root = " << fg_root << "  Base Path = " << base_path << endl;
+    dir = fg_root + "/Scenery/" + base_path;
+    cout << "Dir = " << dir << endl;
+    
+    // stat() directory and create if needed
+    errno = 0;
+    result = stat(dir.c_str(), &stat_buf);
+    if ( result != 0 && errno == ENOENT ) {
+	cout << "Creating directory\n";
+
+	command = "mkdir -p " + dir + "\n";
+	system( command.c_str() );
+    } else {
+	// assume directory exists
+    }
+
+    // get index and generate output file name
+    index = p.gen_index();
+    sprintf(file, "%s/%ld.node", dir.c_str(), index);
+
+    // get (optional) extra node file name (in case there is matching
+    // .poly file.
+    strcpy(exfile, file);
+    strcat(exfile, ".ex");
+
+    // load extra nodes if they exist
+    excount = 0;
+    if ( (fd = fopen(exfile, "r")) != NULL ) {
+	int junki;
+	fscanf(fd, "%d %d %d %d", &excount, &junki, &junki, &junki);
+
+	if ( excount > MAX_EX_NODES - 1 ) {
+	    printf("Error, too many 'extra' nodes, increase array size\n");
+	    exit(-1);
+	} else {
+	    printf("    Expecting %d 'extra' nodes\n", excount);
+	}
+
+	for ( i = 1; i <= excount; i++ ) {
+	    fscanf(fd, "%d %lf %lf %lf\n", &junki, 
+		   &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]);
+	    printf("(extra) %d %.2f %.2f %.2f\n", 
+		    i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
+	}
+	fclose(fd);
+    }
+
+    printf("Creating node file:  %s\n", file);
+    fd = fopen(file, "w");
+
+    // first count regular nodes to generate header
+    count = 0;
+    for ( j = rowmin; j <= rowmax; j++ ) {
+	for ( i = colmin; i <= colmax; i++ ) {
+	    if ( out_data[i][j] > -9000.0 ) {
+		count++;
+	    }
+	}
+	// printf("    count = %d\n", count);
+    }
+    fprintf(fd, "%d 2 1 0\n", count + excount);
+
+    // now write out extra node data
+    for ( i = 1; i <= excount; i++ ) {
+	fprintf(fd, "%d %.2f %.2f %.2f\n", 
+		i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
+    }
+
+    // write out actual node data
+    count = excount + 1;
+    for ( j = rowmin; j <= rowmax; j++ ) {
+	for ( i = colmin; i <= colmax; i++ ) {
+	    if ( out_data[i][j] > -9000.0 ) {
+		fprintf(fd, "%d %.2f %.2f %.2f\n", 
+			count++, 
+			originx + (double)i * col_step, 
+			originy + (double)j * row_step,
+			out_data[i][j]);
+	    }
+	}
+	// printf("    count = %d\n", count);
+    }
+
+    fclose(fd);
+}
+#endif
+
+
+FGArray::~FGArray( void ) {
+    // printf("class FGArray DEstructor called.\n");
+    delete [] in_data;
+    delete [] out_data;
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/13 18:45:02  curt
+// Initial revision. (derived from libDEM.a code.)
+//
diff --git a/Array/array.hxx b/Array/array.hxx
new file mode 100644
index 000000000..c097dadfb
--- /dev/null
+++ b/Array/array.hxx
@@ -0,0 +1,136 @@
+// array.hxx -- Array management class
+//
+// Written by Curtis Olson, started March 1998.
+//
+// Copyright (C) 1998 - 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _ARRAY_HXX
+#define _ARRAY_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Bucket/newbucket.hxx>
+#include <Misc/fgstream.hxx>
+
+
+#define ARRAY_SIZE 1200
+#define ARRAY_SIZE_1 1201
+
+
+class FGArray {
+
+private:
+
+    // file pointer for input
+    // gzFile fd;
+    fg_gzifstream *in;
+
+    // coordinates (in arc seconds) of south west corner
+    double originx, originy;
+    
+    // number of columns and rows
+    int cols, rows;
+    
+    // Distance between column and row data points (in arc seconds)
+    double col_step, row_step;
+    
+    // pointers to the actual grid data allocated here
+    float (*in_data)[ARRAY_SIZE_1];
+    float (*out_data)[ARRAY_SIZE_1];
+
+    // Current "A" Record Information
+    // char dem_description[80], dem_quadrangle[80];
+    // double dem_x1, dem_y1, dem_x2, dem_y2, dem_x3, dem_y3, dem_x4, dem_y4;
+    // double dem_z1, dem_z2;
+    // int dem_resolution, dem_num_profiles;
+  
+    // Current "B" Record Information
+    // int prof_col, prof_row;
+    // int prof_num_cols, prof_num_rows;
+    // double prof_x1, prof_y1;
+    // int prof_data;
+
+    // temporary values for the class to use
+    // char option_name[32];
+    // int do_data;
+    // int cur_col, cur_row;
+
+    // Initialize output mesh structure
+    void outputmesh_init( void );
+
+    // Get the value of a mesh node
+    double outputmesh_get_pt( int i, int j );
+
+    // Set the value of a mesh node
+    void outputmesh_set_pt( int i, int j, double value );
+
+#if 0
+    // Write out a node file that can be used by the "triangle" program
+    void outputmesh_output_nodes( const string& fg_root, FGBucket& p );
+#endif
+
+public:
+
+    // Constructor
+    FGArray( void );
+    FGArray( const string& file );
+
+    // Destructor
+    ~FGArray( void );
+
+    // open an Array file (use "-" if input is coming from stdin)
+    int open ( const string& file );
+
+    // close a Array file
+    int close();
+
+    // parse a Array file
+    int parse();
+
+    // Use least squares to fit a simpler data set to dem data
+    void fit( FGBucket& p, double error );
+
+    // return the current altitude based on grid data.  We should
+    // rewrite this to interpolate exact values, but for now this is
+    // good enough
+    double interpolate_altitude( double lon, double lat );
+
+    // Informational methods
+    inline double get_originx() const { return originx; }
+    inline double get_originy() const { return originy; }
+    inline int get_cols() const { return cols; }
+    inline int get_rows() const { return rows; }
+    inline double get_col_step() const { return col_step; }
+    inline double get_row_step() const { return row_step; }
+};
+
+
+#endif // _ARRAY_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/13 18:45:02  curt
+// Initial revision. (derived from libDEM.a code.)
+//
diff --git a/Array/testarray.cxx b/Array/testarray.cxx
new file mode 100644
index 000000000..384d50d28
--- /dev/null
+++ b/Array/testarray.cxx
@@ -0,0 +1,37 @@
+#include <Bucket/newbucket.hxx>
+
+#include "array.hxx"
+
+main(int argc, char **argv) {
+    char tile_name[256];
+    double lon, lat;
+
+    if ( argc != 2 ) {
+	cout << "Usage: " << argv[0] << " work_dir" << endl;
+	exit(-1);
+    }
+
+    string work_dir = argv[1];
+
+   
+    lon = -146.248360; lat = 61.133950;  // PAVD (Valdez, AK)
+    lon = -110.664244; lat = 33.352890;  // P13
+
+    FGBucket b( lon, lat );
+    string base = b.gen_base_path();
+    string path = work_dir + "/Scenery/" + base;
+
+    long int b_index = b.gen_index();
+    sprintf(tile_name, "%ld", b_index);
+    string arrayfile = path + "/" + tile_name + ".dem";
+    cout << "arrayfile = " << arrayfile << endl;
+    
+    FGArray a(arrayfile);
+    a.parse();
+
+    lon *= 3600;
+    lat *= 3600;
+    cout << a.interpolate_altitude(lon, lat) << endl;
+
+    a.fit(b, 100);
+}

From df15fe0f8bfeb6bf2623d32864df13e5066b1418 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 18:46:01 +0000
Subject: [PATCH 212/283] Added Construct/ and moved Clipper/ to it.

---
 Tools/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index c7ca1f2c1..1fefe4ebc 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -3,10 +3,10 @@ EXTRA_DIST = process-dem.pl
 SUBDIRS = \
 	Lib \
 	Prep \
+	Construct \
 	Utils \
 	Areas \
 	AssemTris \
-	Clipper \
 	Dem2node \
 	FixNode \
 	FixObj \

From 4e4584ed8deb8ad89fd1138f8515a35d54458c30 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 18:46:37 +0000
Subject: [PATCH 213/283] renamed bin "clipper" to "testclipper".

---
 Clipper/Makefile.am | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Clipper/Makefile.am b/Clipper/Makefile.am
index f6acb6b67..07ddbce96 100644
--- a/Clipper/Makefile.am
+++ b/Clipper/Makefile.am
@@ -1,10 +1,12 @@
 noinst_LIBRARIES = libClipper.a
-bin_PROGRAMS = clipper
 
 libClipper_a_SOURCES = clipper.cxx clipper.hxx
-clipper_SOURCES = main.cxx
 
-clipper_LDADD = $(top_builddir)/Tools/Clipper/libClipper.a \
+bin_PROGRAMS = testclipper
+
+testclipper_SOURCES = main.cxx
+
+testclipper_LDADD = $(top_builddir)/Tools/Construct/Clipper/libClipper.a \
 	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \

From 5aaadef6ad35f48d01529c2c56cb9602c8a8306c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 18:47:04 +0000
Subject: [PATCH 214/283] Removed an unused variable.

---
 Polygon/names.cxx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Polygon/names.cxx b/Polygon/names.cxx
index e70b2d479..7e6d2a320 100644
--- a/Polygon/names.cxx
+++ b/Polygon/names.cxx
@@ -30,7 +30,7 @@
 
 // return the type of the shapefile record
 AreaType get_shapefile_type(GDBFile *dbf, int rec) {
-    GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
+    // GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
     GDBFValue *fields;		//an array of field values
     char* dbf_rec;		//a record containing all the fields
 
@@ -151,6 +151,9 @@ string get_area_name( AreaType area ) {
 
 
 // $Log$
+// Revision 1.4  1999/03/13 18:47:04  curt
+// Removed an unused variable.
+//
 // Revision 1.3  1999/03/02 01:03:58  curt
 // Added more reverse lookup support.
 //

From 016d55c8b80f8d51282713b696cddb6c3f874c98 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 18:50:08 +0000
Subject: [PATCH 215/283] Initial revision.

---
 Construct/Makefile.am | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 Construct/Makefile.am

diff --git a/Construct/Makefile.am b/Construct/Makefile.am
new file mode 100644
index 000000000..8516f43dd
--- /dev/null
+++ b/Construct/Makefile.am
@@ -0,0 +1,4 @@
+SUBDIRS = \
+	Array \
+	Clipper \
+	Main

From 1c180f19523c2b059c263544f761271f1c2b9962 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 23:49:53 +0000
Subject: [PATCH 216/283] Moved Triangle to Lib/Triangle

---
 Tools/Makefile.am | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index 1fefe4ebc..eca54bea6 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -12,7 +12,6 @@ SUBDIRS = \
 	FixObj \
 	SplitTris \
 	Stripe_w \
-	Tri2obj \
-	Triangle
+	Tri2obj
 
 bin_SCRIPTS = process-dem.pl

From cac521c151576bb4e05a590c163249c4374ecbb0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 23:50:26 +0000
Subject: [PATCH 217/283] Tweaked output formatting a bit.

---
 Array/array.cxx     | 25 ++++++++++++++-----------
 Array/array.hxx     |  5 ++++-
 Array/testarray.cxx |  2 +-
 3 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/Array/array.cxx b/Array/array.cxx
index ddb1921f9..200fcdc57 100644
--- a/Array/array.cxx
+++ b/Array/array.cxx
@@ -78,18 +78,18 @@ int
 FGArray::open( const string& file ) {
     // open input file (or read from stdin)
     if ( file ==  "-" ) {
-	cout << "Opening array data pipe from stdin" << endl;
+	cout << "  Opening array data pipe from stdin" << endl;
 	// fd = stdin;
 	// fd = gzdopen(STDIN_FILENO, "r");
-	cout << "Not yet ported ..." << endl;
+	cout << "  Not yet ported ..." << endl;
 	return 0;
     } else {
 	in = new fg_gzifstream( file );
 	if ( !(*in) ) {
-	    cout << "Cannot open " << file << endl;
+	    cout << "  Cannot open " << file << endl;
 	    return 0;
 	}
-	cout << "Opening array data file: " << file << endl;
+	cout << "  Opening array data file: " << file << endl;
     }
 
     return 1;
@@ -160,7 +160,7 @@ void FGArray::outputmesh_set_pt( int i, int j, double value ) {
 
 
 // Use least squares to fit a simpler data set to dem data
-void FGArray::fit( FGBucket& p, double error ) {
+void FGArray::fit( double error ) {
     double x[ARRAY_SIZE_1], y[ARRAY_SIZE_1];
     double m, b, max_error, error_sq;
     double x1, y1;
@@ -173,7 +173,7 @@ void FGArray::fit( FGBucket& p, double error ) {
 
     error_sq = error * error;
 
-    cout << "Initializing output mesh structure" << endl;
+    cout << "  Initializing output mesh structure" << endl;
     outputmesh_init();
 
     // determine dimensions
@@ -181,7 +181,7 @@ void FGArray::fit( FGBucket& p, double error ) {
     colmax = cols;
     rowmin = 0;
     rowmax = rows;
-    cout << "Fitting region = " << colmin << "," << rowmin << " to " 
+    cout << "  Fitting region = " << colmin << "," << rowmin << " to " 
 	 << colmax << "," << rowmax << endl;;
     
     // include the corners explicitly
@@ -190,7 +190,7 @@ void FGArray::fit( FGBucket& p, double error ) {
     outputmesh_set_pt(colmax, rowmax, in_data[colmax][rowmax]);
     outputmesh_set_pt(colmax, rowmin, in_data[colmax][rowmin]);
 
-    cout << "Beginning best fit procedure" << endl;
+    cout << "  Beginning best fit procedure" << endl;
 
     for ( row = rowmin; row < rowmax; row++ ) {
 	// fit  = fopen("fit.dat",  "w");
@@ -456,15 +456,15 @@ void FGArray::outputmesh_output_nodes( const string& fg_root, FGBucket& p )
 
     // generate the base directory
     string base_path = p.gen_base_path();
-    cout << "fg_root = " << fg_root << "  Base Path = " << base_path << endl;
+    cout << "  fg_root = " << fg_root << "  Base Path = " << base_path << endl;
     dir = fg_root + "/Scenery/" + base_path;
-    cout << "Dir = " << dir << endl;
+    cout << "  Dir = " << dir << endl;
     
     // stat() directory and create if needed
     errno = 0;
     result = stat(dir.c_str(), &stat_buf);
     if ( result != 0 && errno == ENOENT ) {
-	cout << "Creating directory\n";
+	cout << "  Creating directory\n";
 
 	command = "mkdir -p " + dir + "\n";
 	system( command.c_str() );
@@ -552,6 +552,9 @@ FGArray::~FGArray( void ) {
 
 
 // $Log$
+// Revision 1.2  1999/03/13 23:50:26  curt
+// Tweaked output formatting a bit.
+//
 // Revision 1.1  1999/03/13 18:45:02  curt
 // Initial revision. (derived from libDEM.a code.)
 //
diff --git a/Array/array.hxx b/Array/array.hxx
index c097dadfb..087c8c7d2 100644
--- a/Array/array.hxx
+++ b/Array/array.hxx
@@ -110,7 +110,7 @@ public:
     int parse();
 
     // Use least squares to fit a simpler data set to dem data
-    void fit( FGBucket& p, double error );
+    void fit( double error );
 
     // return the current altitude based on grid data.  We should
     // rewrite this to interpolate exact values, but for now this is
@@ -131,6 +131,9 @@ public:
 
 
 // $Log$
+// Revision 1.2  1999/03/13 23:50:27  curt
+// Tweaked output formatting a bit.
+//
 // Revision 1.1  1999/03/13 18:45:02  curt
 // Initial revision. (derived from libDEM.a code.)
 //
diff --git a/Array/testarray.cxx b/Array/testarray.cxx
index 384d50d28..de6e96aba 100644
--- a/Array/testarray.cxx
+++ b/Array/testarray.cxx
@@ -33,5 +33,5 @@ main(int argc, char **argv) {
     lat *= 3600;
     cout << a.interpolate_altitude(lon, lat) << endl;
 
-    a.fit(b, 100);
+    a.fit( 100 );
 }

From 58242933eb92eca020221556f884f075f5e96551 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 23:51:32 +0000
Subject: [PATCH 218/283] Renamed main.cxx to testclipper.cxx Converted clipper
 routines to a class FGClipper.

---
 Clipper/Makefile.am                   |  2 +-
 Clipper/clipper.cxx                   | 25 ++++++++++++--------
 Clipper/clipper.hxx                   | 33 ++++++++++++++++++++++-----
 Clipper/{main.cxx => testclipper.cxx} | 15 ++++++++----
 4 files changed, 53 insertions(+), 22 deletions(-)
 rename Clipper/{main.cxx => testclipper.cxx} (91%)

diff --git a/Clipper/Makefile.am b/Clipper/Makefile.am
index 07ddbce96..87a59e28b 100644
--- a/Clipper/Makefile.am
+++ b/Clipper/Makefile.am
@@ -4,7 +4,7 @@ libClipper_a_SOURCES = clipper.cxx clipper.hxx
 
 bin_PROGRAMS = testclipper
 
-testclipper_SOURCES = main.cxx
+testclipper_SOURCES = testclipper.cxx
 
 testclipper_LDADD = $(top_builddir)/Tools/Construct/Clipper/libClipper.a \
 	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index e4aaa76f0..3ea78c200 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -25,25 +25,26 @@
  
 
 
-#include "clipper.hxx"
-
 #include <Debug/logstream.hxx>
 #include <Include/fg_constants.h>
 #include <Misc/fgstream.hxx>
 #include <Polygon/names.hxx>
 
+#include "clipper.hxx"
 
-#define EXTRA_SAFETY_CLIP
 
-#define FG_MAX_VERTICES 100000
+// Constructor
+FGClipper::FGClipper( void ) {
+}
 
-static gpc_vertex_list v_list;
-// static gpc_polygon poly;
-static FGPolyList polys_in, polys_out;
+
+// Destructor
+FGClipper::~FGClipper( void ) {
+}
 
 
 // Initialize Clipper (allocate and/or connect structures)
-bool fgClipperInit() {
+bool FGClipper::init() {
     v_list.num_vertices = 0;
     v_list.vertex = new gpc_vertex[FG_MAX_VERTICES];;
 
@@ -52,7 +53,7 @@ bool fgClipperInit() {
 
 
 // Load a polygon definition file
-bool fgClipperLoadPolygons(const string& path) {
+bool FGClipper::load_polys(const string& path) {
     string poly_name;
     AreaType poly_type;
     int contours, count, i, j;
@@ -141,7 +142,7 @@ bool fgClipperLoadPolygons(const string& path) {
 
 
 // Do actually clipping work
-bool fgClipperMaster(const point2d& min, const point2d& max) {
+bool FGClipper::clip_all(const point2d& min, const point2d& max) {
     gpc_polygon accum, result_diff, result_union, tmp;
     polylist_iterator current, last;
 
@@ -221,6 +222,10 @@ bool fgClipperMaster(const point2d& min, const point2d& max) {
 
 
 // $Log$
+// Revision 1.2  1999/03/13 23:51:33  curt
+// Renamed main.cxx to testclipper.cxx
+// Converted clipper routines to a class FGClipper.
+//
 // Revision 1.1  1999/03/01 15:39:39  curt
 // Initial revision.
 //
diff --git a/Clipper/clipper.hxx b/Clipper/clipper.hxx
index 79b7e16da..b9f0d1bed 100644
--- a/Clipper/clipper.hxx
+++ b/Clipper/clipper.hxx
@@ -52,6 +52,8 @@ typedef vector < gpc_polygon * > polylist;
 typedef polylist::iterator polylist_iterator;
 
 #define FG_MAX_AREAS 20
+#define EXTRA_SAFETY_CLIP
+#define FG_MAX_VERTICES 100000
 
 class point2d {
 public:
@@ -66,22 +68,41 @@ public:
 };
 
 
-// Initialize Clipper (allocate and/or connect structures)
-bool fgClipperInit();
+class FGClipper {
 
+private:
 
-// Load a polygon definition file
-bool fgClipperLoadPolygons(const string& path);
+    gpc_vertex_list v_list;
+    // static gpc_polygon poly;
+    FGPolyList polys_in, polys_out;
 
+public:
 
-// Do actually clipping work
-bool fgClipperMaster(const point2d& min, const point2d& max);
+    // Constructor
+    FGClipper( void );
+
+    // Destructor
+    ~FGClipper( void );
+
+    // Initialize Clipper (allocate and/or connect structures)
+    bool init();
+
+    // Load a polygon definition file
+    bool load_polys(const string& path);
+
+    // Do actually clipping work
+    bool clip_all(const point2d& min, const point2d& max);
+};
 
 
 #endif // _CLIPPER_HXX
 
 
 // $Log$
+// Revision 1.2  1999/03/13 23:51:34  curt
+// Renamed main.cxx to testclipper.cxx
+// Converted clipper routines to a class FGClipper.
+//
 // Revision 1.1  1999/03/01 15:39:39  curt
 // Initial revision.
 //
diff --git a/Clipper/main.cxx b/Clipper/testclipper.cxx
similarity index 91%
rename from Clipper/main.cxx
rename to Clipper/testclipper.cxx
index 4aa613a4e..2a0477b48 100644
--- a/Clipper/main.cxx
+++ b/Clipper/testclipper.cxx
@@ -23,11 +23,11 @@
  
 
 
-#include "clipper.hxx"
-
 #include <Debug/logstream.hxx>
 #include <Bucket/newbucket.hxx>
 
+#include "clipper.hxx"
+
 
 int main( int argc, char **argv ) {
     point2d global_min, global_max;
@@ -37,7 +37,8 @@ int main( int argc, char **argv ) {
     global_min.x = global_min.y = 200;
     global_max.y = global_max.x = -200;
 
-    fgClipperInit();
+    FGClipper clipper;
+    clipper.init();
 
     if ( argc < 2 ) {
 	FG_LOG( FG_CLIPPER, FG_ALERT, "Usage: " << argv[0] 
@@ -97,11 +98,11 @@ int main( int argc, char **argv ) {
 	if ( max.y > global_max.y ) global_max.y = max.y;
 
 	// finally, load the polygon(s) from this file
-	fgClipperLoadPolygons( full_path );
+	clipper.load_polys( full_path );
     }
 
     // do the clipping
-    fgClipperMaster(global_min, global_max);
+    clipper.clip_all(global_min, global_max);
 
     FG_LOG( FG_CLIPPER, FG_INFO, "finished main" );
 
@@ -109,6 +110,10 @@ int main( int argc, char **argv ) {
 }
 
 // $Log$
+// Revision 1.1  1999/03/13 23:51:36  curt
+// Renamed main.cxx to testclipper.cxx
+// Converted clipper routines to a class FGClipper.
+//
 // Revision 1.1  1999/03/01 15:39:39  curt
 // Initial revision.
 //

From 3e176c6f8928cc101b16abc672e00f7349fdc83a Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 23:51:59 +0000
Subject: [PATCH 219/283] Moved ../Triangle ./Triangle

---
 Lib/Makefile.am | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Lib/Makefile.am b/Lib/Makefile.am
index 9b607f4c5..6c6ad9d3e 100644
--- a/Lib/Makefile.am
+++ b/Lib/Makefile.am
@@ -1,3 +1,4 @@
 SUBDIRS = \
 	DEM \
-	Polygon
+	Polygon \
+	Triangle

From 87ec69938d943ecae9795aa426028e991513b1b0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 13 Mar 1999 23:53:49 +0000
Subject: [PATCH 220/283] Build Triangle as a lib rather than as a program.

---
 Triangle/Makefile.am | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/Triangle/Makefile.am b/Triangle/Makefile.am
index 9753a8dad..f07cb8e4e 100644
--- a/Triangle/Makefile.am
+++ b/Triangle/Makefile.am
@@ -9,12 +9,11 @@
 #
 #   DEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
 
-DEFS += 
+DEFS += -DTRILIBRARY -DREDUCED
 
-bin_PROGRAMS = triangle # showme
+noinst_LIBRARIES = libTriangle.a
 
-triangle_SOURCES = triangle.c triangle.h
-
-triangle_LDADD = $(base_LIBS)
+libTriangle_a_SOURCES = triangle.c triangle.h
 
+# bin_PROGRAMS = showme
 # showme_SOURCES = showme.c

From 33544d79af42938e7441c9226029f38612c9af3c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 14 Mar 1999 00:03:24 +0000
Subject: [PATCH 221/283] Initial revision.

---
 Main/Makefile.am   |  19 +++++++
 Main/construct.cxx | 135 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 154 insertions(+)
 create mode 100644 Main/Makefile.am
 create mode 100644 Main/construct.cxx

diff --git a/Main/Makefile.am b/Main/Makefile.am
new file mode 100644
index 000000000..d532c780f
--- /dev/null
+++ b/Main/Makefile.am
@@ -0,0 +1,19 @@
+bin_PROGRAMS = construct
+
+construct_SOURCES = construct.cxx
+
+construct_LDADD = \
+	$(top_builddir)/Tools/Construct/Array/libArray.a \
+	$(top_builddir)/Tools/Construct/Clipper/libClipper.a \
+	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
+	$(top_builddir)/Lib/Bucket/libBucket.a \
+	$(top_builddir)/Lib/Math/libMath.a \
+	$(top_builddir)/Lib/Misc/libMisc.a \
+	$(top_builddir)/Lib/Debug/libDebug.a \
+	$(top_builddir)/Lib/zlib/libz.a \
+	-lgpc -lgfc
+
+INCLUDES += \
+	-I$(top_builddir) \
+	-I$(top_builddir)/Lib \
+	-I$(top_builddir)/Tools/Construct
diff --git a/Main/construct.cxx b/Main/construct.cxx
new file mode 100644
index 000000000..fc40fab48
--- /dev/null
+++ b/Main/construct.cxx
@@ -0,0 +1,135 @@
+// main.cxx -- top level construction routines
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include <sys/types.h>  // for directory reading
+#include <dirent.h>     // for directory reading
+
+#include <Bucket/newbucket.hxx>
+
+#include <Array/array.hxx>
+#include <Clipper/clipper.hxx>
+
+
+// load regular grid of elevation data (dem based)
+int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
+    char tile_name[256];
+    string base = b.gen_base_path();
+    long int b_index = b.gen_index();
+    sprintf(tile_name, "%ld", b_index);
+
+    string dem_path = work_base + ".dem" + "/Scenery/" + base 
+	+ "/" + tile_name + ".dem";
+    cout << "dem_path = " << dem_path << endl;
+
+    if ( ! array.open(dem_path) ) {
+	return 0;
+    }
+    array.parse();
+    array.fit( 100 );
+
+    return 1;
+}
+
+
+// load all 2d polygons matching the specified base path and clip
+// against each other to resolve any overlaps
+int load_polys( const string& work_base, FGBucket& b, FGClipper& clipper) {
+    char tile_char[256];
+    string base = b.gen_base_path();
+    long int b_index = b.gen_index();
+    sprintf(tile_char, "%ld", b_index);
+    string tile_str = tile_char;
+
+    string poly_path = work_base + ".shapes" + "/Scenery/" + base;
+    cout << "poly_path = " << poly_path << endl;
+
+    DIR *d;
+    struct dirent *de;
+
+    if ( (d = opendir( poly_path.c_str() )) == NULL ) {
+        cout << "cannot open directory " << poly_path << "\n";
+	return 0;
+    }
+
+    // initialize clipper
+    clipper.init();
+
+    // load all matching polygon files
+    string file, f_index, full_path;
+    int pos;
+    while ( (de = readdir(d)) != NULL ) {
+	file = de->d_name;
+	pos = file.find(".");
+	f_index = file.substr(0, pos);
+
+	if ( tile_str == f_index ) {
+	    cout << file << "  " << f_index << endl;
+	    full_path = poly_path + "/" + file;
+	    clipper.load_polys( full_path );
+	}
+    }
+
+    point2d min, max;
+    min.x = b.get_center_lon() - 0.5 * b.get_width();
+    min.y = b.get_center_lat() - 0.5 * b.get_height();
+    max.x = b.get_center_lon() + 0.5 * b.get_width();
+    max.y = b.get_center_lat() + 0.5 * b.get_height();
+
+    // do clipping
+    clipper.clip_all(min, max);
+
+    return 1;
+}
+
+
+main(int argc, char **argv) {
+    double lon, lat;
+
+    if ( argc != 2 ) {
+	cout << "Usage: " << argv[0] << " work_base" << endl;
+	exit(-1);
+    }
+
+    string work_base = argv[1];
+   
+    lon = -146.248360; lat = 61.133950;  // PAVD (Valdez, AK)
+    // lon = -110.664244; lat = 33.352890;  // P13
+    FGBucket b( lon, lat );
+
+    // load and fit grid of elevation data
+    FGArray array;
+    load_dem( work_base, b, array );
+
+    // load and clip 2d polygon data
+    FGClipper clipper;
+    load_polys( work_base, b, clipper );
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/14 00:03:24  curt
+// Initial revision.
+//
+
+

From 005eab5ed76c47718dab097e0bc6a948a0012bfd Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 17 Mar 1999 23:47:27 +0000
Subject: [PATCH 222/283] Added Triangulate/

---
 Construct/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Construct/Makefile.am b/Construct/Makefile.am
index 8516f43dd..ee75460ff 100644
--- a/Construct/Makefile.am
+++ b/Construct/Makefile.am
@@ -1,4 +1,5 @@
 SUBDIRS = \
 	Array \
 	Clipper \
+	Triangulate \
 	Main

From 685895dce464353f170caa424a7b6c98375b8286 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 17 Mar 1999 23:48:16 +0000
Subject: [PATCH 223/283] Removed forced -g compile flag. Fixed a couple
 compiler warnings.

---
 Array/Makefile.am   | 2 +-
 Array/array.cxx     | 9 +++++----
 Array/testarray.cxx | 2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/Array/Makefile.am b/Array/Makefile.am
index ea97e0d5f..8f9897423 100644
--- a/Array/Makefile.am
+++ b/Array/Makefile.am
@@ -18,5 +18,5 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
 # setting it to "-g"
-CXXFLAGS = -g
+# CXXFLAGS = -g
 
diff --git a/Array/array.cxx b/Array/array.cxx
index 200fcdc57..ad875f587 100644
--- a/Array/array.cxx
+++ b/Array/array.cxx
@@ -110,10 +110,6 @@ FGArray::close() {
 // parse Array file
 int
 FGArray::parse() {
-    int i;
-
-    // cur_col = 0;
-
     *in >> originx >> originy;
     *in >> cols >> col_step;
     *in >> rows >> row_step;
@@ -191,6 +187,7 @@ void FGArray::fit( double error ) {
     outputmesh_set_pt(colmax, rowmin, in_data[colmax][rowmin]);
 
     cout << "  Beginning best fit procedure" << endl;
+    lasty = 0;
 
     for ( row = rowmin; row < rowmax; row++ ) {
 	// fit  = fopen("fit.dat",  "w");
@@ -552,6 +549,10 @@ FGArray::~FGArray( void ) {
 
 
 // $Log$
+// Revision 1.3  1999/03/17 23:48:17  curt
+// Removed forced -g compile flag.
+// Fixed a couple compiler warnings.
+//
 // Revision 1.2  1999/03/13 23:50:26  curt
 // Tweaked output formatting a bit.
 //
diff --git a/Array/testarray.cxx b/Array/testarray.cxx
index de6e96aba..9d65c0bf7 100644
--- a/Array/testarray.cxx
+++ b/Array/testarray.cxx
@@ -31,7 +31,7 @@ main(int argc, char **argv) {
 
     lon *= 3600;
     lat *= 3600;
-    cout << a.interpolate_altitude(lon, lat) << endl;
+    cout << "  " << a.interpolate_altitude(lon, lat) << endl;
 
     a.fit( 100 );
 }

From 53a09c553f66d36b7607615ecf62c2be6407cb8f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 17 Mar 1999 23:48:58 +0000
Subject: [PATCH 224/283] minor renaming and a bit of rearranging.

---
 Clipper/clipper.cxx | 11 +++++++----
 Clipper/clipper.hxx | 22 +++++++++++++++++-----
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index 3ea78c200..9cadba246 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -144,7 +144,7 @@ bool FGClipper::load_polys(const string& path) {
 // Do actually clipping work
 bool FGClipper::clip_all(const point2d& min, const point2d& max) {
     gpc_polygon accum, result_diff, result_union, tmp;
-    polylist_iterator current, last;
+    gpcpoly_iterator current, last;
 
     FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
 
@@ -198,7 +198,7 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 		gpc_polygon_clip(GPC_UNION, &accum, &tmp, &result_union);
 	    }
 	    
-	    polys_out.polys[i].push_back(&result_diff);
+	    polys_clipped.polys[i].push_back(&result_diff);
 	    accum = result_union;
 	}
     }
@@ -207,7 +207,7 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
     // clip to accum against original base tile
     gpc_polygon_clip(GPC_DIFF, &polys_in.safety_base, &accum, 
-		     &polys_out.safety_base);
+		     &polys_clipped.safety_base);
 
     // tmp output accum
     FILE *ofp= fopen("accum", "w");
@@ -215,13 +215,16 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
     // tmp output safety_base
     ofp= fopen("safety_base", "w");
-    gpc_write_polygon(ofp, &polys_out.safety_base);
+    gpc_write_polygon(ofp, &polys_clipped.safety_base);
 
     return true;
 }
 
 
 // $Log$
+// Revision 1.3  1999/03/17 23:48:58  curt
+// minor renaming and a bit of rearranging.
+//
 // Revision 1.2  1999/03/13 23:51:33  curt
 // Renamed main.cxx to testclipper.cxx
 // Converted clipper routines to a class FGClipper.
diff --git a/Clipper/clipper.hxx b/Clipper/clipper.hxx
index b9f0d1bed..617b92f45 100644
--- a/Clipper/clipper.hxx
+++ b/Clipper/clipper.hxx
@@ -48,22 +48,28 @@ extern "C" {
 #include STL_STRING
 #include <vector>
 
-typedef vector < gpc_polygon * > polylist;
-typedef polylist::iterator polylist_iterator;
+FG_USING_STD(string);
+FG_USING_STD(vector);
+
+
+typedef vector < gpc_polygon * > gpcpoly_container;
+typedef gpcpoly_container::iterator gpcpoly_iterator;
+
 
 #define FG_MAX_AREAS 20
 #define EXTRA_SAFETY_CLIP
 #define FG_MAX_VERTICES 100000
 
+
 class point2d {
 public:
     double x, y;
 };
 
 
-class FGPolyList {
+class FGgpcPolyList {
 public:
-    polylist polys[FG_MAX_AREAS];
+    gpcpoly_container polys[FG_MAX_AREAS];
     gpc_polygon safety_base;
 };
 
@@ -74,7 +80,7 @@ private:
 
     gpc_vertex_list v_list;
     // static gpc_polygon poly;
-    FGPolyList polys_in, polys_out;
+    FGgpcPolyList polys_in, polys_clipped;
 
 public:
 
@@ -92,6 +98,9 @@ public:
 
     // Do actually clipping work
     bool clip_all(const point2d& min, const point2d& max);
+
+    // return output poly list
+    inline FGgpcPolyList get_polys_clipped() const { return polys_clipped; }
 };
 
 
@@ -99,6 +108,9 @@ public:
 
 
 // $Log$
+// Revision 1.3  1999/03/17 23:48:59  curt
+// minor renaming and a bit of rearranging.
+//
 // Revision 1.2  1999/03/13 23:51:34  curt
 // Renamed main.cxx to testclipper.cxx
 // Converted clipper routines to a class FGClipper.

From 16cf4eae49bb46759998454c1f86862572746198 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 17 Mar 1999 23:49:51 +0000
Subject: [PATCH 225/283] Started work on Triangulate/ section.

---
 Main/Makefile.am   |  1 +
 Main/construct.cxx | 77 +++++++++++++++++++++++++++++++++++++---------
 2 files changed, 64 insertions(+), 14 deletions(-)

diff --git a/Main/Makefile.am b/Main/Makefile.am
index d532c780f..09fbd2b20 100644
--- a/Main/Makefile.am
+++ b/Main/Makefile.am
@@ -5,6 +5,7 @@ construct_SOURCES = construct.cxx
 construct_LDADD = \
 	$(top_builddir)/Tools/Construct/Array/libArray.a \
 	$(top_builddir)/Tools/Construct/Clipper/libClipper.a \
+	$(top_builddir)/Tools/Construct/Triangulate/libTriangulate.a \
 	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Math/libMath.a \
diff --git a/Main/construct.cxx b/Main/construct.cxx
index fc40fab48..7d8b385b1 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -29,6 +29,7 @@
 
 #include <Array/array.hxx>
 #include <Clipper/clipper.hxx>
+#include <Triangulate/triangle.hxx>
 
 
 // load regular grid of elevation data (dem based)
@@ -52,29 +53,24 @@ int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
 }
 
 
-// load all 2d polygons matching the specified base path and clip
-// against each other to resolve any overlaps
-int load_polys( const string& work_base, FGBucket& b, FGClipper& clipper) {
+// do actual scan of directory and loading of files
+int actual_load_polys( const string& dir, FGBucket& b, FGClipper& clipper ) {
+    int counter = 0;
     char tile_char[256];
     string base = b.gen_base_path();
     long int b_index = b.gen_index();
     sprintf(tile_char, "%ld", b_index);
     string tile_str = tile_char;
-
-    string poly_path = work_base + ".shapes" + "/Scenery/" + base;
-    cout << "poly_path = " << poly_path << endl;
+    string ext;
 
     DIR *d;
     struct dirent *de;
 
-    if ( (d = opendir( poly_path.c_str() )) == NULL ) {
-        cout << "cannot open directory " << poly_path << "\n";
+    if ( (d = opendir( dir.c_str() )) == NULL ) {
+        cout << "cannot open directory " << dir << "\n";
 	return 0;
     }
 
-    // initialize clipper
-    clipper.init();
-
     // load all matching polygon files
     string file, f_index, full_path;
     int pos;
@@ -84,12 +80,44 @@ int load_polys( const string& work_base, FGBucket& b, FGClipper& clipper) {
 	f_index = file.substr(0, pos);
 
 	if ( tile_str == f_index ) {
-	    cout << file << "  " << f_index << endl;
-	    full_path = poly_path + "/" + file;
-	    clipper.load_polys( full_path );
+	    ext = file.substr(pos + 1);
+	    cout << file << "  " << f_index << "  '" << ext << "'" << endl;
+	    full_path = dir + "/" + file;
+	    if ( (ext == "dem") || (ext == "dem.gz") ) {
+		// skip
+	    } else {
+		cout << "ext = '" << ext << "'" << endl;
+		clipper.load_polys( full_path );
+		++counter;
+	    }
 	}
     }
 
+    return counter;
+}
+
+
+// load all 2d polygons matching the specified base path and clip
+// against each other to resolve any overlaps
+int load_polys( const string& work_base, FGBucket& b, FGClipper& clipper) {
+    string base = b.gen_base_path();
+    int result;
+
+    // initialize clipper
+    clipper.init();
+
+    // load airports
+    string poly_path = work_base + ".apt" + "/Scenery/" + base;
+    cout << "poly_path = " << poly_path << endl;
+    result = actual_load_polys( poly_path, b, clipper );
+    cout << "  loaded " << result << " polys" << endl;
+
+    // load hydro
+    poly_path = work_base + ".hydro" + "/Scenery/" + base;
+    cout << "poly_path = " << poly_path << endl;
+    result = actual_load_polys( poly_path, b, clipper );
+    cout << "  loaded " << result << " polys" << endl;
+
     point2d min, max;
     min.x = b.get_center_lon() - 0.5 * b.get_width();
     min.y = b.get_center_lat() - 0.5 * b.get_height();
@@ -97,12 +125,26 @@ int load_polys( const string& work_base, FGBucket& b, FGClipper& clipper) {
     max.y = b.get_center_lat() + 0.5 * b.get_height();
 
     // do clipping
+    cout << "clipping polygons" << endl;
     clipper.clip_all(min, max);
 
     return 1;
 }
 
 
+// triangulate the data for each polygon
+void triangulate( const FGArray& array, const FGClipper& clipper,
+		  FGTriangle& t ) {
+    // first we need to consolidate the points of all the polygons
+    // into a more "Triangle" friendly format
+    FGgpcPolyList gpc_polys;
+
+    gpc_polys = clipper.get_polys_clipped();
+
+    t.build( gpc_polys );
+}
+
+
 main(int argc, char **argv) {
     double lon, lat;
 
@@ -124,10 +166,17 @@ main(int argc, char **argv) {
     // load and clip 2d polygon data
     FGClipper clipper;
     load_polys( work_base, b, clipper );
+
+    // triangulate the data for each polygon
+    FGTriangle t;
+    triangulate( array, clipper, t );
 }
 
 
 // $Log$
+// Revision 1.2  1999/03/17 23:49:52  curt
+// Started work on Triangulate/ section.
+//
 // Revision 1.1  1999/03/14 00:03:24  curt
 // Initial revision.
 //

From 449092be5ba2628aeec5188d30792275d601236b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 17 Mar 1999 23:50:59 +0000
Subject: [PATCH 226/283] Removed forced -g compiler flag.

---
 DemChop/Makefile.am | 5 ++++-
 DemInfo/Makefile.am | 5 ++++-
 FixNode/Makefile.am | 5 ++++-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/DemChop/Makefile.am b/DemChop/Makefile.am
index 46710ee44..9103e673b 100644
--- a/DemChop/Makefile.am
+++ b/DemChop/Makefile.am
@@ -42,11 +42,14 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
 # setting it to "-g"
-CXXFLAGS = -g 
+# CXXFLAGS = -g 
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.3  1999/03/17 23:51:07  curt
+# Removed forced -g compiler flag.
+#
 # Revision 1.2  1999/03/12 22:53:45  curt
 # First working version!
 #
diff --git a/DemInfo/Makefile.am b/DemInfo/Makefile.am
index 355d81593..b3d8d3aa7 100644
--- a/DemInfo/Makefile.am
+++ b/DemInfo/Makefile.am
@@ -41,11 +41,14 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
 # setting it to "-g"
-CXXFLAGS = -g 
+# CXXFLAGS = -g 
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.7  1999/03/17 23:51:14  curt
+# Removed forced -g compiler flag.
+#
 # Revision 1.6  1999/03/08 22:00:46  curt
 # Lots of directory layout reorganization.
 #
diff --git a/FixNode/Makefile.am b/FixNode/Makefile.am
index 68a89ed2e..a245e6ac0 100644
--- a/FixNode/Makefile.am
+++ b/FixNode/Makefile.am
@@ -42,11 +42,14 @@ INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Tools/Lib
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
 # setting it to "-g"
-CXXFLAGS = -g
+# CXXFLAGS = -g
 
 
 #---------------------------------------------------------------------------
 # $Log$
+# Revision 1.10  1999/03/17 23:50:59  curt
+# Removed forced -g compiler flag.
+#
 # Revision 1.9  1999/03/08 22:00:45  curt
 # Lots of directory layout reorganization.
 #

From 24597f6854d5ce88cc70f1aa23a95a18c2fd48dc Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 17 Mar 1999 23:51:25 +0000
Subject: [PATCH 227/283] Changed polygon index counter file.

---
 GenAirports/main.cxx | 5 ++++-
 ShapeFile/main.cxx   | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index 12501d0d8..fbb937daf 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -283,7 +283,7 @@ int main( int argc, char **argv ) {
     system( command.c_str() );
 
     // initialize persistant polygon counter
-    string counter_file = work_dir + "/polygon.counter";
+    string counter_file = work_dir + "/../work.counter";
     poly_index_init( counter_file );
 
     fg_gzifstream in( argv[1] );
@@ -344,6 +344,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.10  1999/03/17 23:51:25  curt
+// Changed polygon index counter file.
+//
 // Revision 1.9  1999/03/12 22:54:19  curt
 // Rearrange a bit of code ...
 //
diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
index b123d26b7..f85ec18b4 100644
--- a/ShapeFile/main.cxx
+++ b/ShapeFile/main.cxx
@@ -73,7 +73,7 @@ int main( int argc, char **argv ) {
     system( command.c_str() );
 
     // initialize persistant polygon counter
-    string counter_file = work_dir + "/polygon.counter";
+    string counter_file = work_dir + "/../work.counter";
     poly_index_init( counter_file );
 
     // initialize structure for building gpc polygons
@@ -265,6 +265,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.7  1999/03/17 23:51:29  curt
+// Changed polygon index counter file.
+//
 // Revision 1.6  1999/03/02 01:04:28  curt
 // Don't crash when work directory doesn't exist ... create it.
 //

From 7e237e7572409a84651ec0e4cf22eeef97c6c859 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 17 Mar 1999 23:51:59 +0000
Subject: [PATCH 228/283] Initial revision.

---
 Triangulate/Makefile.am  | 10 +++++
 Triangulate/triangle.cxx | 73 +++++++++++++++++++++++++++++++++++++
 Triangulate/triangle.hxx | 79 ++++++++++++++++++++++++++++++++++++++++
 Triangulate/trinodes.cxx | 79 ++++++++++++++++++++++++++++++++++++++++
 Triangulate/trinodes.hxx | 79 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 320 insertions(+)
 create mode 100644 Triangulate/Makefile.am
 create mode 100644 Triangulate/triangle.cxx
 create mode 100644 Triangulate/triangle.hxx
 create mode 100644 Triangulate/trinodes.cxx
 create mode 100644 Triangulate/trinodes.hxx

diff --git a/Triangulate/Makefile.am b/Triangulate/Makefile.am
new file mode 100644
index 000000000..503e359b2
--- /dev/null
+++ b/Triangulate/Makefile.am
@@ -0,0 +1,10 @@
+noinst_LIBRARIES = libTriangulate.a
+
+libTriangulate_a_SOURCES = \
+	triangle.cxx triangle.hxx \
+	trinodes.cxx trinodes.hxx
+
+INCLUDES += \
+	-I$(top_builddir) \
+	-I$(top_builddir)/Lib \
+	-I$(top_builddir)/Tools/Construct
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
new file mode 100644
index 000000000..2a226dd3b
--- /dev/null
+++ b/Triangulate/triangle.cxx
@@ -0,0 +1,73 @@
+// triangle.cxx -- "Triangle" interface class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include "triangle.hxx"
+
+
+// Constructor
+FGTriangle::FGTriangle( void ) {
+}
+
+
+// Destructor
+FGTriangle::~FGTriangle( void ) {
+}
+
+
+// populate this class based on the specified gpc_polys list
+int FGTriangle::build( FGgpcPolyList gpc_polys ) {
+    // traverse the gpc_polys and build a unified node list and a set
+    // of Triangle PSLG that reference the node list by index
+    // (starting at zero)
+
+    gpc_polygon *gpc_poly;
+    gpcpoly_iterator current, last;
+
+    // process polygons in priority order
+    cout << "prepairing node list and polygons" << endl;
+
+    for ( int i = 0; i < FG_MAX_AREAS; ++i ) {
+	cout << "area type = " << i << endl;
+	current = gpc_polys.polys[i].begin();
+	last = gpc_polys.polys[i].end();
+	for ( ; current != last; ++current ) {
+	    gpc_poly = *current;
+
+	    for ( int j = 0; j < gpc_poly->num_contours; j++ ) {
+		for ( int k = 0; k < gpc_poly->contour[j].num_vertices; k++ ) {
+		    Point3D p( gpc_poly->contour[j].vertex[k].x,
+			       gpc_poly->contour[j].vertex[k].y,
+			       0 );
+		    cout << trinodes.unique_add( p ) << endl;
+		}
+	    }
+	}
+    }
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/17 23:51:59  curt
+// Initial revision.
+//
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
new file mode 100644
index 000000000..5879abd18
--- /dev/null
+++ b/Triangulate/triangle.hxx
@@ -0,0 +1,79 @@
+// triandgle.hxx -- "Triangle" interface class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _TRIANGLE_HXX
+#define _TRIANGLE_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+#include <vector>
+
+#include <Clipper/clipper.hxx>
+#include <Math/point3d.hxx>
+
+#include "trinodes.hxx"
+
+FG_USING_STD(vector);
+
+
+typedef vector < int > tripoly;
+typedef tripoly::iterator tripoly_iterator;
+typedef tripoly::const_iterator const_tripoly_iterator;
+
+typedef vector < int > tripoly_list;
+typedef tripoly_list::iterator tripoly_list_iterator;
+typedef tripoly_list::const_iterator const_tripoly_list_iterator;
+
+
+class FGTriangle {
+
+private:
+
+    FGTriNodes trinodes;
+    tripoly_list polylist;
+
+public:
+
+    // Constructor and destructor
+    FGTriangle( void );
+    ~FGTriangle( void );
+
+    // populate this class based on the specified gpc_polys list
+    int build( FGgpcPolyList gpc_polys );
+};
+
+
+#endif // _TRIANGLE_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/17 23:51:59  curt
+// Initial revision.
+//
diff --git a/Triangulate/trinodes.cxx b/Triangulate/trinodes.cxx
new file mode 100644
index 000000000..5c2508e00
--- /dev/null
+++ b/Triangulate/trinodes.cxx
@@ -0,0 +1,79 @@
+// trinodes.cxx -- "Triangle" nodes management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include "trinodes.hxx"
+
+
+// Constructor 
+FGTriNodes::FGTriNodes( void ) {
+}
+
+
+// Destructor
+FGTriNodes::~FGTriNodes( void ) {
+}
+
+
+// return true of the two points are "close enough" as defined by
+// FG_PROXIMITY_EPSILON
+inline bool FGTriNodes::close_enough( const Point3D& p1, const Point3D& p2 ) {
+    if ( ( fabs(p1.x() - p2.x()) < FG_PROXIMITY_EPSILON ) &&
+	 ( fabs(p1.y() - p2.y()) < FG_PROXIMITY_EPSILON ) ) {
+	return true;
+    } else {
+	return false;
+    }
+}
+
+
+// Add a point to the point list if it doesn't already exist.  Returns
+// the index (starting at zero) of the point in the list.
+int FGTriNodes::unique_add( const Point3D& p ) {
+    point_iterator current, last;
+    int counter = 0;
+
+    // see if point already exists
+    current = point_list.begin();
+    last = point_list.end();
+    for ( ; current != last; ++current ) {
+	if ( close_enough(p, *current) ) {
+	    return counter;
+	}
+	
+	++counter;
+    }
+
+    // add to list
+    point_list.push_back( p );
+
+    return counter;
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/17 23:52:00  curt
+// Initial revision.
+//
+
+
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
new file mode 100644
index 000000000..2245b5a8c
--- /dev/null
+++ b/Triangulate/trinodes.hxx
@@ -0,0 +1,79 @@
+// trinodes.hxx -- "Triangle" nodes management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _TRINODES_HXX
+#define _TRINODES_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+#include <vector>
+
+#include <Math/point3d.hxx>
+
+FG_USING_STD(vector);
+
+
+#define FG_PROXIMITY_EPSILON 0.000001
+
+
+typedef vector < Point3D > point_container;
+typedef point_container::iterator point_iterator;
+typedef point_container::const_iterator const_point_iterator;
+
+
+class FGTriNodes {
+
+private:
+
+    point_container point_list;
+
+    // return true of the two points are "close enough" as defined by
+    // FG_PROXIMITY_EPSILON
+    bool close_enough( const Point3D& p, const Point3D& p );
+
+public:
+
+    // Constructor and destructor
+    FGTriNodes( void );
+    ~FGTriNodes( void );
+
+    // Add a point to the point list if it doesn't already exist.
+    // Returns the index (starting at zero) of the point in the list.
+    int unique_add( const Point3D& p );
+};
+
+
+#endif // _TRINODES_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/17 23:52:00  curt
+// Initial revision.
+//

From 62670d0514bb049f73dd2e427cbdd2cdf4848c0b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 18 Mar 1999 04:31:10 +0000
Subject: [PATCH 229/283] Let's not pass copies of huge structures on the stack
 ... ye might see a segfault ... :-)

---
 Clipper/clipper.hxx      |  5 +++++
 Triangulate/triangle.cxx | 10 ++++++++--
 Triangulate/triangle.hxx |  6 +++++-
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/Clipper/clipper.hxx b/Clipper/clipper.hxx
index 617b92f45..874d49485 100644
--- a/Clipper/clipper.hxx
+++ b/Clipper/clipper.hxx
@@ -54,6 +54,7 @@ FG_USING_STD(vector);
 
 typedef vector < gpc_polygon * > gpcpoly_container;
 typedef gpcpoly_container::iterator gpcpoly_iterator;
+typedef gpcpoly_container::const_iterator const_gpcpoly_iterator;
 
 
 #define FG_MAX_AREAS 20
@@ -108,6 +109,10 @@ public:
 
 
 // $Log$
+// Revision 1.4  1999/03/18 04:31:10  curt
+// Let's not pass copies of huge structures on the stack ... ye might see a
+// segfault ... :-)
+//
 // Revision 1.3  1999/03/17 23:48:59  curt
 // minor renaming and a bit of rearranging.
 //
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 2a226dd3b..992549214 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -36,13 +36,13 @@ FGTriangle::~FGTriangle( void ) {
 
 
 // populate this class based on the specified gpc_polys list
-int FGTriangle::build( FGgpcPolyList gpc_polys ) {
+int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
     // traverse the gpc_polys and build a unified node list and a set
     // of Triangle PSLG that reference the node list by index
     // (starting at zero)
 
     gpc_polygon *gpc_poly;
-    gpcpoly_iterator current, last;
+    const_gpcpoly_iterator current, last;
 
     // process polygons in priority order
     cout << "prepairing node list and polygons" << endl;
@@ -64,10 +64,16 @@ int FGTriangle::build( FGgpcPolyList gpc_polys ) {
 	    }
 	}
     }
+
+    return 0;
 }
 
 
 // $Log$
+// Revision 1.2  1999/03/18 04:31:11  curt
+// Let's not pass copies of huge structures on the stack ... ye might see a
+// segfault ... :-)
+//
 // Revision 1.1  1999/03/17 23:51:59  curt
 // Initial revision.
 //
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index 5879abd18..1dbb85e24 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -66,7 +66,7 @@ public:
     ~FGTriangle( void );
 
     // populate this class based on the specified gpc_polys list
-    int build( FGgpcPolyList gpc_polys );
+    int build( const FGgpcPolyList& gpc_polys );
 };
 
 
@@ -74,6 +74,10 @@ public:
 
 
 // $Log$
+// Revision 1.2  1999/03/18 04:31:12  curt
+// Let's not pass copies of huge structures on the stack ... ye might see a
+// segfault ... :-)
+//
 // Revision 1.1  1999/03/17 23:51:59  curt
 // Initial revision.
 //

From d3f68ace943bb33bc1ee5c6090df0f1864091834 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 19 Mar 1999 00:26:18 +0000
Subject: [PATCH 230/283] Fixed a clipping bug (polygons specified in wrong
 order). Touched up a few compiler warnings.

---
 Clipper/clipper.cxx | 51 +++++++++++++++++++++++++++++++++++----------
 Clipper/clipper.hxx |  8 +++++--
 2 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index 9cadba246..0a10f3276 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -122,11 +122,11 @@ bool FGClipper::load_polys(const string& path) {
 	    gpc_add_contour( poly, &v_list );
 
 	    int area = (int)poly_type;
-	    if ( area < FG_MAX_AREAS ) {
+	    if ( area < FG_MAX_AREA_TYPES ) {
 		polys_in.polys[area].push_back(poly);
 	    } else {
 		FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = " 
-			<< poly_type);
+			<< (int)poly_type);
 		exit(-1);
 	    }
 	}
@@ -143,7 +143,8 @@ bool FGClipper::load_polys(const string& path) {
 
 // Do actually clipping work
 bool FGClipper::clip_all(const point2d& min, const point2d& max) {
-    gpc_polygon accum, result_diff, result_union, tmp;
+    gpc_polygon accum, result_union, tmp;
+    gpc_polygon *result_diff;
     gpcpoly_iterator current, last;
 
     FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
@@ -173,7 +174,7 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
     gpc_add_contour( &polys_in.safety_base, &v_list );
 
     // process polygons in priority order
-    for ( int i = 0; i < FG_MAX_AREAS; ++i ) {
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
 
 	current = polys_in.polys[i].begin();
 	last = polys_in.polys[i].end();
@@ -183,22 +184,46 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
 #ifdef EXTRA_SAFETY_CLIP
 	    // clip to base tile
-	    gpc_polygon_clip(GPC_INT, &polys_in.safety_base, *current, &tmp);
+	    gpc_polygon_clip(GPC_INT, *current, &polys_in.safety_base, &tmp);
 #else
-	    &tmp = *current;
+	    tmp = *current;
 #endif
 
 	    // clip current polygon against previous higher priority
 	    // stuff
+	    result_diff = new gpc_polygon;
+	    result_diff->num_contours = 0;
+	    result_diff->contour = NULL;
+
 	    if ( accum.num_contours == 0 ) {
-		result_diff = tmp;
+		*result_diff = tmp;
 		result_union = tmp;
 	    } else {
-		gpc_polygon_clip(GPC_DIFF, &accum, &tmp, &result_diff);
-		gpc_polygon_clip(GPC_UNION, &accum, &tmp, &result_union);
+		gpc_polygon_clip(GPC_DIFF, &tmp, &accum, result_diff);
+		gpc_polygon_clip(GPC_UNION, &tmp, &accum, &result_union);
 	    }
-	    
-	    polys_clipped.polys[i].push_back(&result_diff);
+
+	    /*
+	    cout << "original contours = " << tmp.num_contours << endl;
+
+	    for ( int j = 0; j < tmp.num_contours; j++ ) {
+		for (int k = 0;k < tmp.contour[j].num_vertices;k++ ) {
+		    cout << tmp.contour[j].vertex[k].x << ","
+			 << tmp.contour[j].vertex[k].y << endl;
+		}
+	    }
+
+	    cout << "clipped contours = " << result_diff->num_contours << endl;
+
+	    for ( int j = 0; j < result_diff->num_contours; j++ ) {
+		for (int k = 0;k < result_diff->contour[j].num_vertices;k++ ) {
+		    cout << result_diff->contour[j].vertex[k].x << ","
+			 << result_diff->contour[j].vertex[k].y << endl;
+		}
+	    }
+	    */
+
+	    polys_clipped.polys[i].push_back(result_diff);
 	    accum = result_union;
 	}
     }
@@ -222,6 +247,10 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
 
 // $Log$
+// Revision 1.4  1999/03/19 00:26:18  curt
+// Fixed a clipping bug (polygons specified in wrong order).
+// Touched up a few compiler warnings.
+//
 // Revision 1.3  1999/03/17 23:48:58  curt
 // minor renaming and a bit of rearranging.
 //
diff --git a/Clipper/clipper.hxx b/Clipper/clipper.hxx
index 874d49485..469691a2a 100644
--- a/Clipper/clipper.hxx
+++ b/Clipper/clipper.hxx
@@ -57,7 +57,7 @@ typedef gpcpoly_container::iterator gpcpoly_iterator;
 typedef gpcpoly_container::const_iterator const_gpcpoly_iterator;
 
 
-#define FG_MAX_AREAS 20
+#define FG_MAX_AREA_TYPES 20
 #define EXTRA_SAFETY_CLIP
 #define FG_MAX_VERTICES 100000
 
@@ -70,7 +70,7 @@ public:
 
 class FGgpcPolyList {
 public:
-    gpcpoly_container polys[FG_MAX_AREAS];
+    gpcpoly_container polys[FG_MAX_AREA_TYPES];
     gpc_polygon safety_base;
 };
 
@@ -109,6 +109,10 @@ public:
 
 
 // $Log$
+// Revision 1.5  1999/03/19 00:26:19  curt
+// Fixed a clipping bug (polygons specified in wrong order).
+// Touched up a few compiler warnings.
+//
 // Revision 1.4  1999/03/18 04:31:10  curt
 // Let's not pass copies of huge structures on the stack ... ye might see a
 // segfault ... :-)

From 0eed0e091800f6c13b33a8af61614ab9d4a0b31f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 19 Mar 1999 00:26:51 +0000
Subject: [PATCH 231/283] Minor tweaks ...

---
 Main/Makefile.am   | 1 +
 Main/construct.cxx | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/Main/Makefile.am b/Main/Makefile.am
index 09fbd2b20..2c4b964c5 100644
--- a/Main/Makefile.am
+++ b/Main/Makefile.am
@@ -17,4 +17,5 @@ construct_LDADD = \
 INCLUDES += \
 	-I$(top_builddir) \
 	-I$(top_builddir)/Lib \
+	-I$(top_builddir)/Tools/Lib \
 	-I$(top_builddir)/Tools/Construct
diff --git a/Main/construct.cxx b/Main/construct.cxx
index 7d8b385b1..815a799e3 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -141,7 +141,9 @@ void triangulate( const FGArray& array, const FGClipper& clipper,
 
     gpc_polys = clipper.get_polys_clipped();
 
+    cout << "ready to build node list and polygons" << endl;
     t.build( gpc_polys );
+    cout << "done building node list and polygons" << endl;
 }
 
 
@@ -157,6 +159,8 @@ main(int argc, char **argv) {
    
     lon = -146.248360; lat = 61.133950;  // PAVD (Valdez, AK)
     // lon = -110.664244; lat = 33.352890;  // P13
+    lon = -89.744682312011719; lat= 29.314495086669922;
+
     FGBucket b( lon, lat );
 
     // load and fit grid of elevation data
@@ -174,6 +178,9 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.3  1999/03/19 00:26:52  curt
+// Minor tweaks ...
+//
 // Revision 1.2  1999/03/17 23:49:52  curt
 // Started work on Triangulate/ section.
 //

From 7f2ab3559b4218a4e43e28094e26c62fe8b78357 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 19 Mar 1999 00:27:09 +0000
Subject: [PATCH 232/283] Continued work on triangulation preparation.

---
 Triangulate/Makefile.am  |  1 +
 Triangulate/triangle.cxx | 30 ++++++++++++++++++++++++++++--
 Triangulate/triangle.hxx |  8 ++++++--
 Triangulate/trinodes.cxx |  6 ++++++
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/Triangulate/Makefile.am b/Triangulate/Makefile.am
index 503e359b2..f28601c0d 100644
--- a/Triangulate/Makefile.am
+++ b/Triangulate/Makefile.am
@@ -7,4 +7,5 @@ libTriangulate_a_SOURCES = \
 INCLUDES += \
 	-I$(top_builddir) \
 	-I$(top_builddir)/Lib \
+	-I$(top_builddir)/Tools/Lib \
 	-I$(top_builddir)/Tools/Construct
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 992549214..1d90cbfbe 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -37,6 +37,9 @@ FGTriangle::~FGTriangle( void ) {
 
 // populate this class based on the specified gpc_polys list
 int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
+    int index;
+    tripoly poly;
+
     // traverse the gpc_polys and build a unified node list and a set
     // of Triangle PSLG that reference the node list by index
     // (starting at zero)
@@ -47,29 +50,52 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
     // process polygons in priority order
     cout << "prepairing node list and polygons" << endl;
 
-    for ( int i = 0; i < FG_MAX_AREAS; ++i ) {
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
 	cout << "area type = " << i << endl;
 	current = gpc_polys.polys[i].begin();
 	last = gpc_polys.polys[i].end();
 	for ( ; current != last; ++current ) {
 	    gpc_poly = *current;
+	    cout << "processing a polygon, contours = " 
+		 << gpc_poly->num_contours << endl;
+
+	    poly.erase(poly.begin(), poly.end());
+
+	    if (gpc_poly->num_contours <= 0 ) {
+		cout << "FATAL ERROR! no contours in this polygon" << endl;
+		exit(-1);
+	    }
+
+	    if (gpc_poly->num_contours > 1 ) {
+		cout << "FATAL ERROR! no multi-contour support" << endl;
+		exit(-1);
+	    }
 
 	    for ( int j = 0; j < gpc_poly->num_contours; j++ ) {
 		for ( int k = 0; k < gpc_poly->contour[j].num_vertices; k++ ) {
 		    Point3D p( gpc_poly->contour[j].vertex[k].x,
 			       gpc_poly->contour[j].vertex[k].y,
 			       0 );
-		    cout << trinodes.unique_add( p ) << endl;
+		    index = trinodes.unique_add( p );
+		    poly.push_back(index);
+		    // cout << index << endl;
 		}
+		polylist[i].push_back(poly);
 	    }
 	}
     }
 
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	cout << "polylist[" << i << "] = " << polylist[i].size() << endl;
+    }
     return 0;
 }
 
 
 // $Log$
+// Revision 1.3  1999/03/19 00:27:10  curt
+// Continued work on triangulation preparation.
+//
 // Revision 1.2  1999/03/18 04:31:11  curt
 // Let's not pass copies of huge structures on the stack ... ye might see a
 // segfault ... :-)
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index 1dbb85e24..9ba18005b 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -37,6 +37,7 @@
 
 #include <Clipper/clipper.hxx>
 #include <Math/point3d.hxx>
+#include <Polygon/names.hxx>
 
 #include "trinodes.hxx"
 
@@ -47,7 +48,7 @@ typedef vector < int > tripoly;
 typedef tripoly::iterator tripoly_iterator;
 typedef tripoly::const_iterator const_tripoly_iterator;
 
-typedef vector < int > tripoly_list;
+typedef vector < tripoly > tripoly_list;
 typedef tripoly_list::iterator tripoly_list_iterator;
 typedef tripoly_list::const_iterator const_tripoly_list_iterator;
 
@@ -57,7 +58,7 @@ class FGTriangle {
 private:
 
     FGTriNodes trinodes;
-    tripoly_list polylist;
+    tripoly_list polylist[FG_MAX_AREA_TYPES];
 
 public:
 
@@ -74,6 +75,9 @@ public:
 
 
 // $Log$
+// Revision 1.3  1999/03/19 00:27:11  curt
+// Continued work on triangulation preparation.
+//
 // Revision 1.2  1999/03/18 04:31:12  curt
 // Let's not pass copies of huge structures on the stack ... ye might see a
 // segfault ... :-)
diff --git a/Triangulate/trinodes.cxx b/Triangulate/trinodes.cxx
index 5c2508e00..82c2b6933 100644
--- a/Triangulate/trinodes.cxx
+++ b/Triangulate/trinodes.cxx
@@ -53,11 +53,14 @@ int FGTriNodes::unique_add( const Point3D& p ) {
     point_iterator current, last;
     int counter = 0;
 
+    // cout << p.x() << "," << p.y() << endl;
+
     // see if point already exists
     current = point_list.begin();
     last = point_list.end();
     for ( ; current != last; ++current ) {
 	if ( close_enough(p, *current) ) {
+	    cout << "found an existing match!" << endl;
 	    return counter;
 	}
 	
@@ -72,6 +75,9 @@ int FGTriNodes::unique_add( const Point3D& p ) {
 
 
 // $Log$
+// Revision 1.2  1999/03/19 00:27:12  curt
+// Continued work on triangulation preparation.
+//
 // Revision 1.1  1999/03/17 23:52:00  curt
 // Initial revision.
 //

From 44550e6b70a80574c7a56a96e6ed4e2a4ab32e88 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 19 Mar 1999 00:27:30 +0000
Subject: [PATCH 233/283] Use long int for index instead of just int.

---
 GenAirports/main.cxx | 19 +++++++++++--------
 Polygon/index.cxx    | 11 +++++++----
 Polygon/index.hxx    |  5 ++++-
 ShapeFile/shape.cxx  |  9 ++++++---
 4 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/GenAirports/main.cxx b/GenAirports/main.cxx
index fbb937daf..7ad07f6db 100644
--- a/GenAirports/main.cxx
+++ b/GenAirports/main.cxx
@@ -49,7 +49,7 @@
 
 
 // write out airport data
-void write_airport( int p_index, list_container hull_list, FGBucket b, 
+void write_airport( long int p_index, list_container hull_list, FGBucket b, 
 		    const string& root, const bool cut_and_keep ) {
     char tile_name[256], poly_index[256];
 
@@ -62,7 +62,7 @@ void write_airport( int p_index, list_container hull_list, FGBucket b,
     sprintf(tile_name, "%ld", b_index);
     string aptfile = path + "/" + tile_name;
 
-    sprintf( poly_index, "%d", p_index );
+    sprintf( poly_index, "%ld", p_index );
     aptfile += ".";
     aptfile += poly_index;
     cout << "apt file = " << aptfile << endl;
@@ -153,8 +153,8 @@ void process_airport( string airport, list < string > & runway_list,
 	string rwy_width = rwy_str.substr(43, 4);
 	sscanf( rwy_width.c_str(), "%d", &width);
 	string rwy_sfc = rwy_str.substr(47, 4);
-	string rwy_end1 = rwy_str.substr(52, 6);
-	string rwy_end2 = rwy_str.substr(59, 6);
+	string rwy_end1 = rwy_str.substr(52, 8);
+	string rwy_end2 = rwy_str.substr(61, 8);
 
 	/*
 	cout << "  no    = " << rwy_no << endl;
@@ -167,7 +167,7 @@ void process_airport( string airport, list < string > & runway_list,
 	cout << "  end1  = " << rwy_end1 << endl;
 	cout << "  end2  = " << rwy_end2 << endl;
 	*/
-	
+
 	rwy_list = gen_runway_area( lon, lat, hdg * DEG_TO_RAD, 
 				    (double)len * FEET_TO_METER,
 				    (double)width * FEET_TO_METER );
@@ -197,7 +197,7 @@ void process_airport( string airport, list < string > & runway_list,
     hull_list = convex_hull(apt_list);
 
     // get next polygon index
-    int index = poly_index_next();
+    long int index = poly_index_next();
 
     // find average center, min, and max point of convex hull
     point2d average, min, max;
@@ -241,7 +241,7 @@ void process_airport( string airport, list < string > & runway_list,
 	cout << "airport spans tile boundaries" << endl;
 	cout << "  dx = " << dx << "  dy = " << dy << endl;
 
-	if ( (dx > 1) || (dy > 1) ) {
+	if ( (dx > 2) || (dy > 2) ) {
 	    cout << "somethings really wrong!!!!" << endl;
 	    exit(-1);
 	}
@@ -324,7 +324,7 @@ int main( int argc, char **argv ) {
 	} else if ( line[0] == 'R' ) {
 	    // runway entry
 	    runway_list.push_back(line);
-	} else if ( line == "99" ) {
+	} else if ( line == "[End]" ) {
 	    // end of file
 	    break;
 	} else {
@@ -344,6 +344,9 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.11  1999/03/19 00:27:38  curt
+// Use long int for index instead of just int.
+//
 // Revision 1.10  1999/03/17 23:51:25  curt
 // Changed polygon index counter file.
 //
diff --git a/Polygon/index.cxx b/Polygon/index.cxx
index a467c0ba6..34352aacd 100644
--- a/Polygon/index.cxx
+++ b/Polygon/index.cxx
@@ -30,7 +30,7 @@
 #include "index.hxx"
 
 
-static int poly_index;
+static long int poly_index;
 static string poly_path;
 
 
@@ -46,14 +46,14 @@ bool poly_index_init( string path ) {
 	return false;
     }
 
-    fscanf( fp, "%d", &poly_index );
+    fscanf( fp, "%ld", &poly_index );
 
     fclose( fp );
 }
 
 
 // increment the persistant counter and return the next poly_index
-int poly_index_next() {
+long int poly_index_next() {
     ++poly_index;
 
     FILE *fp = fopen( poly_path.c_str(), "w" );
@@ -62,7 +62,7 @@ int poly_index_next() {
 	cout << "Error cannot open " << poly_path << " for writing" << endl;
     }
 
-    fprintf( fp, "%d\n", poly_index );
+    fprintf( fp, "%ld\n", poly_index );
 
     fclose( fp );
 
@@ -71,6 +71,9 @@ int poly_index_next() {
 
 
 // $Log$
+// Revision 1.2  1999/03/19 00:27:30  curt
+// Use long int for index instead of just int.
+//
 // Revision 1.1  1999/02/25 21:30:24  curt
 // Initial revision.
 //
diff --git a/Polygon/index.hxx b/Polygon/index.hxx
index ddc8acb6f..0ea6b5c06 100644
--- a/Polygon/index.hxx
+++ b/Polygon/index.hxx
@@ -35,7 +35,7 @@
 bool poly_index_init( string path );
 
 // increment the persistant counter and return the next poly_index
-int poly_index_next();
+long int poly_index_next();
 
 
 
@@ -43,6 +43,9 @@ int poly_index_next();
 
 
 // $Log$
+// Revision 1.2  1999/03/19 00:27:31  curt
+// Use long int for index instead of just int.
+//
 // Revision 1.1  1999/02/25 21:30:24  curt
 // Initial revision.
 //
diff --git a/ShapeFile/shape.cxx b/ShapeFile/shape.cxx
index ae3e1432f..badef8823 100644
--- a/ShapeFile/shape.cxx
+++ b/ShapeFile/shape.cxx
@@ -44,7 +44,7 @@ public:
 };
 
 
-static void clip_and_write_poly( string root, int p_index, AreaType area, 
+static void clip_and_write_poly( string root, long int p_index, AreaType area, 
 				 FGBucket b, gpc_polygon *shape ) {
     point2d c, min, max;
     c.x = b.get_center_lon();
@@ -115,7 +115,7 @@ static void clip_and_write_poly( string root, int p_index, AreaType area,
 	sprintf( tile_name, "%ld", t_index );
 	string polyfile = path + "/" + tile_name;
 
-	sprintf( poly_index, "%d", p_index );
+	sprintf( poly_index, "%ld", p_index );
 	polyfile += ".";
 	polyfile += poly_index;
 
@@ -168,7 +168,7 @@ void add_to_shape(int count, double *coords, gpc_polygon *shape) {
 // process shape (write polygon to all intersecting tiles)
 void process_shape(string path, AreaType area, gpc_polygon *gpc_shape) {
     point2d min, max;
-    int index;
+    long int index;
     int i, j;
 
     min.x = min.y = 200.0;
@@ -244,6 +244,9 @@ void free_shape(gpc_polygon *shape) {
 
 
 // $Log$
+// Revision 1.3  1999/03/19 00:27:41  curt
+// Use long int for index instead of just int.
+//
 // Revision 1.2  1999/02/25 21:31:08  curt
 // First working version???
 //

From 549c16796211b17458b9e31e1cc57aef2442b94b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 19 Mar 1999 22:28:46 +0000
Subject: [PATCH 234/283] Only add non-null polygons to output list.

---
 Clipper/clipper.cxx | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index 0a10f3276..2f9e4e3ca 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -223,7 +223,10 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 	    }
 	    */
 
-	    polys_clipped.polys[i].push_back(result_diff);
+	    // only add to output list if the clip left us with a polygon
+	    if ( result_diff->num_contours > 0 ) {
+		polys_clipped.polys[i].push_back(result_diff);
+	    }
 	    accum = result_union;
 	}
     }
@@ -247,6 +250,9 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
 
 // $Log$
+// Revision 1.5  1999/03/19 22:28:46  curt
+// Only add non-null polygons to output list.
+//
 // Revision 1.4  1999/03/19 00:26:18  curt
 // Fixed a clipping bug (polygons specified in wrong order).
 // Touched up a few compiler warnings.

From 453a82a03038da6febcfe44fed9e1a27072eeab3 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Fri, 19 Mar 1999 22:29:04 +0000
Subject: [PATCH 235/283] Working on preparationsn for triangulation.

---
 Triangulate/triangle.cxx | 56 ++++++++++++++++++++++++++++++++++++++--
 Triangulate/triangle.hxx | 17 ++++++++++++
 Triangulate/trinodes.hxx |  6 +++++
 3 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 1d90cbfbe..854b5b508 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -68,7 +68,8 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 
 	    if (gpc_poly->num_contours > 1 ) {
 		cout << "FATAL ERROR! no multi-contour support" << endl;
-		exit(-1);
+		sleep(5);
+		// exit(-1);
 	    }
 
 	    for ( int j = 0; j < gpc_poly->num_contours; j++ ) {
@@ -86,13 +87,64 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
     }
 
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	cout << "polylist[" << i << "] = " << polylist[i].size() << endl;
+	if ( polylist[i].size() ) {
+	    cout << get_area_name((AreaType)i) << " = " 
+		 << polylist[i].size() << endl;
+	}
     }
     return 0;
 }
 
 
+// do actual triangulation
+int FGTriangle::do_triangulate( const tripoly& poly ) {
+    point_container node_list;
+    struct triangulateio in, mid, out, vorout;
+    int counter;
+
+    // define input points
+    node_list = trinodes.get_node_list();
+
+    in.numberofpoints = node_list.size();
+    in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
+
+    point_iterator current, last;
+    current = node_list.begin();
+    last = node_list.end();
+    counter = 0;
+    for ( ; current != last; ++current ) {
+	in.pointlist[counter++] = current->x();
+	in.pointlist[counter++] = current->y();
+    }
+}
+
+
+// triangulate each of the polygon areas
+int FGTriangle::triangulate() {
+    tripoly poly;
+
+    tripoly_list_iterator current, last;
+
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	cout << "area type = " << i << endl;
+	current = polylist[i].begin();
+	last = polylist[i].end();
+	for ( ; current != last; ++current ) {
+	    poly = *current;
+	    cout << "triangulating a polygon, size = " << poly.size() << endl;
+
+	    do_triangulate( poly );
+	}
+    }
+
+    return 0;
+}
+
+
 // $Log$
+// Revision 1.4  1999/03/19 22:29:04  curt
+// Working on preparationsn for triangulation.
+//
 // Revision 1.3  1999/03/19 00:27:10  curt
 // Continued work on triangulation preparation.
 //
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index 9ba18005b..9c9b133cd 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -39,6 +39,11 @@
 #include <Math/point3d.hxx>
 #include <Polygon/names.hxx>
 
+#define REAL double
+extern "C" {
+#include <Triangle/triangle.h>
+}
+
 #include "trinodes.hxx"
 
 FG_USING_STD(vector);
@@ -66,8 +71,17 @@ public:
     FGTriangle( void );
     ~FGTriangle( void );
 
+    // add nodes from the dem fit
+    int add_nodes();
+
     // populate this class based on the specified gpc_polys list
     int build( const FGgpcPolyList& gpc_polys );
+
+    // do actual triangulation
+    int do_triangulate( const tripoly& poly );
+
+    // front end triangulator for polygon list
+    int triangulate();
 };
 
 
@@ -75,6 +89,9 @@ public:
 
 
 // $Log$
+// Revision 1.4  1999/03/19 22:29:05  curt
+// Working on preparationsn for triangulation.
+//
 // Revision 1.3  1999/03/19 00:27:11  curt
 // Continued work on triangulation preparation.
 //
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
index 2245b5a8c..1a540f981 100644
--- a/Triangulate/trinodes.hxx
+++ b/Triangulate/trinodes.hxx
@@ -67,6 +67,9 @@ public:
     // Add a point to the point list if it doesn't already exist.
     // Returns the index (starting at zero) of the point in the list.
     int unique_add( const Point3D& p );
+
+    // return the master node list
+    inline point_container get_node_list() const { return point_list; }
 };
 
 
@@ -74,6 +77,9 @@ public:
 
 
 // $Log$
+// Revision 1.2  1999/03/19 22:29:06  curt
+// Working on preparationsn for triangulation.
+//
 // Revision 1.1  1999/03/17 23:52:00  curt
 // Initial revision.
 //

From 45da0562fbf7bd11423ffea2b36101d136aa0714 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 20 Mar 1999 02:21:51 +0000
Subject: [PATCH 236/283] Continue shaping the code towards triangulation
 bliss.  Added code to calculate some point guaranteed to be inside a polygon.

---
 Triangulate/Makefile.am  |  3 ++-
 Triangulate/triangle.cxx | 23 +++++++++++++++--------
 Triangulate/triangle.hxx | 15 ++++++++-------
 Triangulate/trinodes.cxx | 14 +++++++++-----
 Triangulate/trinodes.hxx | 17 ++++++++++++-----
 5 files changed, 46 insertions(+), 26 deletions(-)

diff --git a/Triangulate/Makefile.am b/Triangulate/Makefile.am
index f28601c0d..8beeb47bf 100644
--- a/Triangulate/Makefile.am
+++ b/Triangulate/Makefile.am
@@ -2,7 +2,8 @@ noinst_LIBRARIES = libTriangulate.a
 
 libTriangulate_a_SOURCES = \
 	triangle.cxx triangle.hxx \
-	trinodes.cxx trinodes.hxx
+	trinodes.cxx trinodes.hxx \
+	tripoly.cxx tripoly.hxx
 
 INCLUDES += \
 	-I$(top_builddir) \
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 854b5b508..74b5d2fa2 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -23,6 +23,7 @@
 
 
 #include "triangle.hxx"
+#include "tripoly.hxx"
 
 
 // Constructor
@@ -38,8 +39,6 @@ FGTriangle::~FGTriangle( void ) {
 // populate this class based on the specified gpc_polys list
 int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
     int index;
-    tripoly poly;
-
     // traverse the gpc_polys and build a unified node list and a set
     // of Triangle PSLG that reference the node list by index
     // (starting at zero)
@@ -59,7 +58,7 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 	    cout << "processing a polygon, contours = " 
 		 << gpc_poly->num_contours << endl;
 
-	    poly.erase(poly.begin(), poly.end());
+	    FGTriPoly poly;
 
 	    if (gpc_poly->num_contours <= 0 ) {
 		cout << "FATAL ERROR! no contours in this polygon" << endl;
@@ -78,9 +77,11 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 			       gpc_poly->contour[j].vertex[k].y,
 			       0 );
 		    index = trinodes.unique_add( p );
-		    poly.push_back(index);
+		    poly.add_node(index);
 		    // cout << index << endl;
 		}
+		poly.calc_point_inside( trinodes );
+		cout << endl;
 		polylist[i].push_back(poly);
 	    }
 	}
@@ -97,8 +98,8 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 
 
 // do actual triangulation
-int FGTriangle::do_triangulate( const tripoly& poly ) {
-    point_container node_list;
+int FGTriangle::do_triangulate( const FGTriPoly& poly ) {
+    trinode_list node_list;
     struct triangulateio in, mid, out, vorout;
     int counter;
 
@@ -108,7 +109,7 @@ int FGTriangle::do_triangulate( const tripoly& poly ) {
     in.numberofpoints = node_list.size();
     in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
 
-    point_iterator current, last;
+    trinode_list_iterator current, last;
     current = node_list.begin();
     last = node_list.end();
     counter = 0;
@@ -116,12 +117,14 @@ int FGTriangle::do_triangulate( const tripoly& poly ) {
 	in.pointlist[counter++] = current->x();
 	in.pointlist[counter++] = current->y();
     }
+
+    return 0;
 }
 
 
 // triangulate each of the polygon areas
 int FGTriangle::triangulate() {
-    tripoly poly;
+    FGTriPoly poly;
 
     tripoly_list_iterator current, last;
 
@@ -142,6 +145,10 @@ int FGTriangle::triangulate() {
 
 
 // $Log$
+// Revision 1.5  1999/03/20 02:21:52  curt
+// Continue shaping the code towards triangulation bliss.  Added code to
+// calculate some point guaranteed to be inside a polygon.
+//
 // Revision 1.4  1999/03/19 22:29:04  curt
 // Working on preparationsn for triangulation.
 //
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index 9c9b133cd..58fa1bd26 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -1,4 +1,4 @@
-// triandgle.hxx -- "Triangle" interface class
+// triangle.hxx -- "Triangle" interface class
 //
 // Written by Curtis Olson, started March 1999.
 //
@@ -45,15 +45,12 @@ extern "C" {
 }
 
 #include "trinodes.hxx"
+#include "tripoly.hxx"
 
 FG_USING_STD(vector);
 
 
-typedef vector < int > tripoly;
-typedef tripoly::iterator tripoly_iterator;
-typedef tripoly::const_iterator const_tripoly_iterator;
-
-typedef vector < tripoly > tripoly_list;
+typedef vector < FGTriPoly > tripoly_list;
 typedef tripoly_list::iterator tripoly_list_iterator;
 typedef tripoly_list::const_iterator const_tripoly_list_iterator;
 
@@ -78,7 +75,7 @@ public:
     int build( const FGgpcPolyList& gpc_polys );
 
     // do actual triangulation
-    int do_triangulate( const tripoly& poly );
+    int do_triangulate( const FGTriPoly& poly );
 
     // front end triangulator for polygon list
     int triangulate();
@@ -89,6 +86,10 @@ public:
 
 
 // $Log$
+// Revision 1.5  1999/03/20 02:21:53  curt
+// Continue shaping the code towards triangulation bliss.  Added code to
+// calculate some point guaranteed to be inside a polygon.
+//
 // Revision 1.4  1999/03/19 22:29:05  curt
 // Working on preparationsn for triangulation.
 //
diff --git a/Triangulate/trinodes.cxx b/Triangulate/trinodes.cxx
index 82c2b6933..d29e907b1 100644
--- a/Triangulate/trinodes.cxx
+++ b/Triangulate/trinodes.cxx
@@ -50,17 +50,17 @@ inline bool FGTriNodes::close_enough( const Point3D& p1, const Point3D& p2 ) {
 // Add a point to the point list if it doesn't already exist.  Returns
 // the index (starting at zero) of the point in the list.
 int FGTriNodes::unique_add( const Point3D& p ) {
-    point_iterator current, last;
+    trinode_list_iterator current, last;
     int counter = 0;
 
     // cout << p.x() << "," << p.y() << endl;
 
     // see if point already exists
-    current = point_list.begin();
-    last = point_list.end();
+    current = node_list.begin();
+    last = node_list.end();
     for ( ; current != last; ++current ) {
 	if ( close_enough(p, *current) ) {
-	    cout << "found an existing match!" << endl;
+	    // cout << "found an existing match!" << endl;
 	    return counter;
 	}
 	
@@ -68,13 +68,17 @@ int FGTriNodes::unique_add( const Point3D& p ) {
     }
 
     // add to list
-    point_list.push_back( p );
+    node_list.push_back( p );
 
     return counter;
 }
 
 
 // $Log$
+// Revision 1.3  1999/03/20 02:21:54  curt
+// Continue shaping the code towards triangulation bliss.  Added code to
+// calculate some point guaranteed to be inside a polygon.
+//
 // Revision 1.2  1999/03/19 00:27:12  curt
 // Continued work on triangulation preparation.
 //
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
index 1a540f981..3a3d31beb 100644
--- a/Triangulate/trinodes.hxx
+++ b/Triangulate/trinodes.hxx
@@ -43,16 +43,16 @@ FG_USING_STD(vector);
 #define FG_PROXIMITY_EPSILON 0.000001
 
 
-typedef vector < Point3D > point_container;
-typedef point_container::iterator point_iterator;
-typedef point_container::const_iterator const_point_iterator;
+typedef vector < Point3D > trinode_list;
+typedef trinode_list::iterator trinode_list_iterator;
+typedef trinode_list::const_iterator const_trinode_list_iterator;
 
 
 class FGTriNodes {
 
 private:
 
-    point_container point_list;
+    trinode_list node_list;
 
     // return true of the two points are "close enough" as defined by
     // FG_PROXIMITY_EPSILON
@@ -69,7 +69,10 @@ public:
     int unique_add( const Point3D& p );
 
     // return the master node list
-    inline point_container get_node_list() const { return point_list; }
+    inline trinode_list get_node_list() const { return node_list; }
+
+    // return the ith point
+    inline Point3D get_node( int i ) const { return node_list[i]; }
 };
 
 
@@ -77,6 +80,10 @@ public:
 
 
 // $Log$
+// Revision 1.3  1999/03/20 02:21:55  curt
+// Continue shaping the code towards triangulation bliss.  Added code to
+// calculate some point guaranteed to be inside a polygon.
+//
 // Revision 1.2  1999/03/19 22:29:06  curt
 // Working on preparationsn for triangulation.
 //

From 6708a15ff37a02993d90a7e241755ab51b4301a6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 20 Mar 1999 13:21:36 +0000
Subject: [PATCH 237/283] Initial revision.

---
 Triangulate/tripoly.cxx | 185 ++++++++++++++++++++++++++++++++++++++++
 Triangulate/tripoly.hxx |  79 +++++++++++++++++
 Triangulate/trisegs.cxx |  31 +++++++
 Triangulate/trisegs.hxx |  83 ++++++++++++++++++
 4 files changed, 378 insertions(+)
 create mode 100644 Triangulate/tripoly.cxx
 create mode 100644 Triangulate/tripoly.hxx
 create mode 100644 Triangulate/trisegs.cxx
 create mode 100644 Triangulate/trisegs.hxx

diff --git a/Triangulate/tripoly.cxx b/Triangulate/tripoly.cxx
new file mode 100644
index 000000000..763e369e4
--- /dev/null
+++ b/Triangulate/tripoly.cxx
@@ -0,0 +1,185 @@
+// tripoly.cxx -- "Triangle" polygon management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include <Include/fg_constants.h>
+#include <Math/point3d.hxx>
+
+#include "tripoly.hxx"
+
+
+// Constructor 
+FGTriPoly::FGTriPoly( void ) {
+}
+
+
+// Destructor
+FGTriPoly::~FGTriPoly( void ) {
+}
+
+
+// Given a line segment specified by two endpoints p1 and p2, return
+// the slope of the line.
+static double slope( const Point3D& p0, const Point3D& p1 ) {
+    if ( fabs(p0.x() - p1.x()) > FG_EPSILON ) {
+	return (p0.y() - p1.y()) / (p0.x() - p1.x());
+    } else {
+	return 1.0e+999; // really big number
+    }
+}
+
+
+// Given a line segment specified by two endpoints p1 and p2, return
+// the y value of a point on the line that intersects with the
+// verticle line through x.  Return true if an intersection is found,
+// false otherwise.
+static bool intersects( const Point3D& p0, const Point3D& p1, double x, 
+			 Point3D *result ) {
+    // equation of a line through (x0,y0) and (x1,y1):
+    // 
+    //     y = y1 + (x - x1) * (y0 - y1) / (x0 - x1)
+
+    double y;
+
+    if ( fabs(p0.x() - p1.x()) > FG_EPSILON ) {
+	y = p1.y() + (x - p1.x()) * (p0.y() - p1.y()) / (p0.x() - p1.x());
+    } else {
+	return false;
+    }
+    result->setx(x);
+    result->sety(y);
+
+    if ( p0.y() <= p1.y() ) {
+	if ( (p0.y() <= y) && (y <= p1.y()) ) {
+	    return true;
+	}
+    } else {
+ 	if ( (p0.y() >= y) && (y >= p1.y()) ) {
+	    return true;
+	}
+    }
+
+    return false;
+}
+
+
+// calculate an "arbitrary" point inside this polygon for assigning
+// attribute areas
+void FGTriPoly::calc_point_inside( const FGTriNodes& trinodes ) {
+    Point3D tmp, min, ln, p1, p2, p3, m, result;
+
+    // 1. find point, min, with smallest y
+
+    // min.y() starts greater than the biggest possible lat (degrees)
+    min.sety( 100.0 );
+    // int min_index;
+    int min_node_index = 0;
+
+    tripoly_iterator current, last;
+    current = poly.begin();
+    last = poly.end();
+
+    int counter = 0;
+    for ( ; current != last; ++current ) {
+	tmp = trinodes.get_node( *current );
+	if ( tmp.y() < min.y() ) {
+	    min = tmp;
+	    // min_index = *current;
+	    min_node_index = counter;
+
+	    // cout << "min index = " << *current 
+	    //      << " value = " << min_y << endl;
+	} else {
+	    // cout << "  index = " << *current << endl;
+	}
+	++counter;
+    }
+    cout << "min node index = " << min_node_index << endl;
+    cout << "min index = " << poly[min_node_index] 
+	 << " value = " << trinodes.get_node( poly[min_node_index] ) 
+	 << " == " << min << endl;
+
+    // 2. take midpoint, m, of min with neighbor having lowest
+    // fabs(slope)
+
+    if ( min_node_index == 0 ) {
+	p1 = trinodes.get_node( poly[1] );
+	p2 = trinodes.get_node( poly[poly.size() - 1] );
+    } else if ( min_node_index == (int)(poly.size()) - 1 ) {
+	p1 = trinodes.get_node( poly[0] );
+	p2 = trinodes.get_node( poly[poly.size() - 1] );
+    } else {
+	p1 = trinodes.get_node( poly[min_node_index - 1] );
+	p2 = trinodes.get_node( poly[min_node_index + 1] );
+    }
+    double s1 = fabs( slope(min, p1) );
+    double s2 = fabs( slope(min, p2) );
+    if ( s1 < s2  ) {
+	ln = p1;
+    } else {
+	ln = p2;
+    }
+
+    m.setx( (min.x() + ln.x()) / 2.0 );
+    m.sety( (min.y() + ln.y()) / 2.0 );
+    cout << "low mid point = " << m << endl;
+
+    // 3. intersect vertical line through m and all other segments.
+    // save point, p3, with smallest y > m.y
+
+    p3.sety(100);
+    for ( int i = 0; i < (int)(poly.size()) - 1; ++i ) {
+	p1 = trinodes.get_node( poly[i] );
+	p2 = trinodes.get_node( poly[i+1] );
+
+	if ( intersects(p1, p2, m.x(), &result) ) {
+	    // cout << "intersection = " << result << endl;
+	    if ( ( result.y() < p3.y() ) &&
+		 ( fabs(result.y() - m.y()) > FG_EPSILON ) ) {
+		p3 = result;
+	    }
+	}
+    }
+    p1 = trinodes.get_node( poly[0] );
+    p2 = trinodes.get_node( poly[poly.size() - 1] );
+    if ( intersects(p1, p2, m.x(), &result) ) {
+	// cout << "intersection = " << result << endl;
+	if ( ( result.y() < p3.y() ) &&
+	     ( fabs(result.y() - m.y()) > FG_EPSILON ) ) {
+	    p3 = result;
+	}
+    }
+    cout << "low intersection of other segment = " << p3 << endl;
+
+    // 4. take midpoint of p2 && m as an arbitrary point inside polygon
+
+    inside.setx( (m.x() + p3.x()) / 2.0 );
+    inside.sety( (m.y() + p3.y()) / 2.0 );
+    cout << "inside point = " << inside << endl;
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/20 13:21:36  curt
+// Initial revision.
+//
diff --git a/Triangulate/tripoly.hxx b/Triangulate/tripoly.hxx
new file mode 100644
index 000000000..92986247c
--- /dev/null
+++ b/Triangulate/tripoly.hxx
@@ -0,0 +1,79 @@
+// tripoly.hxx -- "Triangle" polygon management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _TRIPOLY_HXX
+#define _TRIPOLY_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+#include <vector>
+
+#include "trinodes.hxx"
+
+FG_USING_STD(vector);
+
+
+typedef vector < int > tripoly;
+typedef tripoly::iterator tripoly_iterator;
+typedef tripoly::const_iterator const_tripoly_iterator;
+
+
+class FGTriPoly {
+
+private:
+
+    tripoly poly;
+    Point3D inside;
+
+public:
+
+    // Constructor and destructor
+    FGTriPoly( void );
+    ~FGTriPoly( void );
+
+    // Add the specified node (index) to the polygon
+    inline void add_node( int index ) { poly.push_back( index ); }
+
+    // return size
+    inline int size() const { return poly.size(); }
+
+    // calculate an "arbitrary" point inside this polygon for
+    // assigning attribute areas
+    void calc_point_inside( const FGTriNodes& trinodes );
+};
+
+
+#endif // _TRIPOLY_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/20 13:21:36  curt
+// Initial revision.
+//
diff --git a/Triangulate/trisegs.cxx b/Triangulate/trisegs.cxx
new file mode 100644
index 000000000..55853e6ce
--- /dev/null
+++ b/Triangulate/trisegs.cxx
@@ -0,0 +1,31 @@
+// trisegs.cxx -- "Triangle" segment management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include "trisegs.hxx"
+
+
+// $Log$
+// Revision 1.1  1999/03/20 13:21:36  curt
+// Initial revision.
+//
diff --git a/Triangulate/trisegs.hxx b/Triangulate/trisegs.hxx
new file mode 100644
index 000000000..534b694f5
--- /dev/null
+++ b/Triangulate/trisegs.hxx
@@ -0,0 +1,83 @@
+// trisegs.hxx -- "Triangle" segment management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _TRISEGS_HXX
+#define _TRISEGS_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+#include <vector>
+
+FG_USING_STD(vector);
+
+
+// a segment is two integer pointers into the node list
+class FGTriSeg {
+public:
+    int n1, n2;
+};
+
+
+typedef vector < FGTriSeg > triseg_list;
+typedef triseg_list::iterator triseg_list_iterator;
+typedef triseg_list::const_iterator const_triseg_list_iterator;
+
+
+class FGTriSegments {
+
+private:
+
+    triseg_list seg_list;
+
+public:
+
+    // Constructor and destructor
+    FGTriSegments( void );
+    ~FGTriSegments( void );
+
+    // Add a point to the point list if it doesn't already exist.
+    // Returns the index (starting at zero) of the point in the list.
+    int unique_add( const FGTriSeg& s );
+
+    // return the master node list
+    inline triseg_list get_seg_list() const { return seg_list; }
+
+    // return the ith segment
+    inline FGTriSeg get_seg( int i ) const { return seg_list[i]; }
+};
+
+
+#endif // _TRISEGS_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/20 13:21:36  curt
+// Initial revision.
+//

From e07ae2989e4d7f13252fb69d3301d0c812c13294 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 20 Mar 1999 13:22:10 +0000
Subject: [PATCH 238/283] Added trisegs.[ch]xx tripoly.[ch]xx.

---
 Triangulate/Makefile.am  |  3 ++-
 Triangulate/triangle.cxx | 56 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/Triangulate/Makefile.am b/Triangulate/Makefile.am
index 8beeb47bf..42ba81984 100644
--- a/Triangulate/Makefile.am
+++ b/Triangulate/Makefile.am
@@ -3,7 +3,8 @@ noinst_LIBRARIES = libTriangulate.a
 libTriangulate_a_SOURCES = \
 	triangle.cxx triangle.hxx \
 	trinodes.cxx trinodes.hxx \
-	tripoly.cxx tripoly.hxx
+	tripoly.cxx tripoly.hxx \
+	trisegs.cxx trisegs.hxx
 
 INCLUDES += \
 	-I$(top_builddir) \
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 74b5d2fa2..6db46c16c 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -81,7 +81,7 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 		    // cout << index << endl;
 		}
 		poly.calc_point_inside( trinodes );
-		cout << endl;
+
 		polylist[i].push_back(poly);
 	    }
 	}
@@ -100,13 +100,14 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 // do actual triangulation
 int FGTriangle::do_triangulate( const FGTriPoly& poly ) {
     trinode_list node_list;
-    struct triangulateio in, mid, out, vorout;
+    struct triangulateio in, out;
     int counter;
 
     // define input points
     node_list = trinodes.get_node_list();
 
     in.numberofpoints = node_list.size();
+    in.numberofpointattributes = 0;
     in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
 
     trinode_list_iterator current, last;
@@ -125,9 +126,53 @@ int FGTriangle::do_triangulate( const FGTriPoly& poly ) {
 // triangulate each of the polygon areas
 int FGTriangle::triangulate() {
     FGTriPoly poly;
+    struct triangulateio in, out;
 
+    trinode_list node_list = trinodes.get_node_list();
+
+    // point list
+    in.numberofpoints = node_list.size();
+    in.numberofpointattributes = 1;
+    in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
+
+    trinode_list_iterator tn_current, tn_last;
+    tn_current = node_list.begin();
+    tn_last = node_list.end();
+    int counter = 0;
+    for ( ; tn_current != tn_last; ++tn_current ) {
+	in.pointlist[counter++] = tn_current->x();
+	in.pointlist[counter++] = tn_current->y();
+    }
+
+    in.pointattributelist = (REAL *) NULL;
+    in.pointmarkerlist = (int *) NULL;
+
+    // segment list
+    in.numberofsegments = 0;
+
+    tripoly_list_iterator tp_current, tp_last;
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	cout << "area type = " << i << endl;
+	tp_current = polylist[i].begin();
+	tp_last = polylist[i].end();
+	for ( ; tp_current != tp_last; ++tp_current ) {
+	    poly = *tp_current;
+	    in.numberofsegments += poly.size() + 1;
+	}
+    }
+
+    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. */
+
+  /*
     tripoly_list_iterator current, last;
-
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
 	cout << "area type = " << i << endl;
 	current = polylist[i].begin();
@@ -139,12 +184,15 @@ int FGTriangle::triangulate() {
 	    do_triangulate( poly );
 	}
     }
-
+    */
     return 0;
 }
 
 
 // $Log$
+// Revision 1.6  1999/03/20 13:22:11  curt
+// Added trisegs.[ch]xx tripoly.[ch]xx.
+//
 // Revision 1.5  1999/03/20 02:21:52  curt
 // Continue shaping the code towards triangulation bliss.  Added code to
 // calculate some point guaranteed to be inside a polygon.

From b4a9bde0e9d5a8c578d9002d555d2b933f58117c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 20 Mar 1999 20:32:51 +0000
Subject: [PATCH 239/283] First mostly successful tile triangulation works. 
 There's plenty of tweaking to do, but we are marching in the right direction.

---
 Array/array.cxx          |  33 ++++--
 Array/array.hxx          |  49 ++++----
 Main/Makefile.am         |   1 +
 Main/construct.cxx       |  29 +++--
 Triangulate/triangle.cxx | 239 +++++++++++++++++++++++++++++----------
 Triangulate/triangle.hxx |  21 +++-
 Triangulate/tripoly.hxx  |   8 ++
 Triangulate/trisegs.cxx  |  41 +++++++
 Triangulate/trisegs.hxx  |  27 ++++-
 9 files changed, 341 insertions(+), 107 deletions(-)

diff --git a/Array/array.cxx b/Array/array.cxx
index ad875f587..90e04142d 100644
--- a/Array/array.cxx
+++ b/Array/array.cxx
@@ -60,14 +60,14 @@ FG_USING_STD(string);
 FGArray::FGArray( void ) {
     // cout << "class FGArray CONstructor called." << endl;
     in_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
-    out_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
+    // out_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
 }
 
 
 FGArray::FGArray( const string &file ) {
     // cout << "class FGArray CONstructor called." << endl;
     in_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
-    out_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
+    // out_data = new float[ARRAY_SIZE_1][ARRAY_SIZE_1];
 
     FGArray::open(file);
 }
@@ -130,6 +130,16 @@ FGArray::parse() {
 }
 
 
+// add a node to the output (fitted) node list
+void FGArray::add_fit_node( int i, int j, double val ) {
+    double x = (originx + i * col_step) / 3600.0;
+    double y = (originy + j * row_step) / 3600.0;
+    cout << Point3D(x, y, val) << endl;
+    node_list.push_back( Point3D(x, y, val) );
+}
+
+
+#if 0
 // Initialize output mesh structure
 void FGArray::outputmesh_init( void ) {
     int i, j;
@@ -153,6 +163,7 @@ void FGArray::outputmesh_set_pt( int i, int j, double value ) {
     // cout << "Setting data[" << i << "][" << j << "] = " << value << endl;
    out_data[i][j] = value;
 }
+#endif
 
 
 // Use least squares to fit a simpler data set to dem data
@@ -170,7 +181,7 @@ void FGArray::fit( double error ) {
     error_sq = error * error;
 
     cout << "  Initializing output mesh structure" << endl;
-    outputmesh_init();
+    // outputmesh_init();
 
     // determine dimensions
     colmin = 0;
@@ -181,10 +192,10 @@ void FGArray::fit( double error ) {
 	 << colmax << "," << rowmax << endl;;
     
     // include the corners explicitly
-    outputmesh_set_pt(colmin, rowmin, in_data[colmin][rowmin]);
-    outputmesh_set_pt(colmin, rowmax, in_data[colmin][rowmax]);
-    outputmesh_set_pt(colmax, rowmax, in_data[colmax][rowmax]);
-    outputmesh_set_pt(colmax, rowmin, in_data[colmax][rowmin]);
+    add_fit_node( colmin, rowmin, in_data[colmin][rowmin] );
+    add_fit_node( colmin, rowmax-1, in_data[colmin][rowmax] );
+    add_fit_node( colmax-1, rowmin, in_data[colmax][rowmin] );
+    add_fit_node( colmax-1, rowmax-1, in_data[colmax][rowmax] );
 
     cout << "  Beginning best fit procedure" << endl;
     lasty = 0;
@@ -276,7 +287,7 @@ void FGArray::fit( double error ) {
 	    if ( start > colmin ) {
 		// skip this for the first line segment
 		cury = m * x[0] + b;
-		outputmesh_set_pt(start, row, (lasty + cury) / 2);
+		add_fit_node( start, row, (lasty + cury) / 2 );
 		// fprintf(fit, "%.2f %.2f\n", x[0], (lasty + cury) / 2);
 	    }
 
@@ -544,11 +555,15 @@ void FGArray::outputmesh_output_nodes( const string& fg_root, FGBucket& p )
 FGArray::~FGArray( void ) {
     // printf("class FGArray DEstructor called.\n");
     delete [] in_data;
-    delete [] out_data;
+    // delete [] out_data;
 }
 
 
 // $Log$
+// Revision 1.4  1999/03/20 20:32:51  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.3  1999/03/17 23:48:17  curt
 // Removed forced -g compile flag.
 // Fixed a couple compiler warnings.
diff --git a/Array/array.hxx b/Array/array.hxx
index 087c8c7d2..f90b88b92 100644
--- a/Array/array.hxx
+++ b/Array/array.hxx
@@ -31,14 +31,26 @@
 #endif                                   
 
 
+#include <Include/compiler.h>
+
+#include <vector>
+
 #include <Bucket/newbucket.hxx>
+#include <Math/point3d.hxx>
 #include <Misc/fgstream.hxx>
 
+FG_USING_STD(vector);
+
 
 #define ARRAY_SIZE 1200
 #define ARRAY_SIZE_1 1201
 
 
+typedef vector < Point3D > fitnode_list;
+typedef fitnode_list::iterator fitnode_list_iterator;
+typedef fitnode_list::const_iterator const_fitnode_list_iterator;
+
+
 class FGArray {
 
 private:
@@ -58,37 +70,23 @@ private:
     
     // pointers to the actual grid data allocated here
     float (*in_data)[ARRAY_SIZE_1];
-    float (*out_data)[ARRAY_SIZE_1];
+    // float (*out_data)[ARRAY_SIZE_1];
 
-    // Current "A" Record Information
-    // char dem_description[80], dem_quadrangle[80];
-    // double dem_x1, dem_y1, dem_x2, dem_y2, dem_x3, dem_y3, dem_x4, dem_y4;
-    // double dem_z1, dem_z2;
-    // int dem_resolution, dem_num_profiles;
-  
-    // Current "B" Record Information
-    // int prof_col, prof_row;
-    // int prof_num_cols, prof_num_rows;
-    // double prof_x1, prof_y1;
-    // int prof_data;
-
-    // temporary values for the class to use
-    // char option_name[32];
-    // int do_data;
-    // int cur_col, cur_row;
+    // output nodes
+    fitnode_list node_list;
 
     // Initialize output mesh structure
-    void outputmesh_init( void );
+    // void outputmesh_init( void );
 
     // Get the value of a mesh node
-    double outputmesh_get_pt( int i, int j );
+    // double outputmesh_get_pt( int i, int j );
 
     // Set the value of a mesh node
-    void outputmesh_set_pt( int i, int j, double value );
+    // void outputmesh_set_pt( int i, int j, double value );
 
 #if 0
     // Write out a node file that can be used by the "triangle" program
-    void outputmesh_output_nodes( const string& fg_root, FGBucket& p );
+    // void outputmesh_output_nodes( const string& fg_root, FGBucket& p );
 #endif
 
 public:
@@ -112,6 +110,9 @@ public:
     // Use least squares to fit a simpler data set to dem data
     void fit( double error );
 
+    // add a node to the output (fitted) node list
+    void add_fit_node( int i, int j, double val );
+
     // return the current altitude based on grid data.  We should
     // rewrite this to interpolate exact values, but for now this is
     // good enough
@@ -124,6 +125,8 @@ public:
     inline int get_rows() const { return rows; }
     inline double get_col_step() const { return col_step; }
     inline double get_row_step() const { return row_step; }
+
+    inline fitnode_list get_fit_node_list() const { return node_list; }
 };
 
 
@@ -131,6 +134,10 @@ public:
 
 
 // $Log$
+// Revision 1.3  1999/03/20 20:32:52  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.2  1999/03/13 23:50:27  curt
 // Tweaked output formatting a bit.
 //
diff --git a/Main/Makefile.am b/Main/Makefile.am
index 2c4b964c5..618351e7f 100644
--- a/Main/Makefile.am
+++ b/Main/Makefile.am
@@ -7,6 +7,7 @@ construct_LDADD = \
 	$(top_builddir)/Tools/Construct/Clipper/libClipper.a \
 	$(top_builddir)/Tools/Construct/Triangulate/libTriangulate.a \
 	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
+	$(top_builddir)/Tools/Lib/Triangle/libTriangle.a \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Math/libMath.a \
 	$(top_builddir)/Lib/Misc/libMisc.a \
diff --git a/Main/construct.cxx b/Main/construct.cxx
index 815a799e3..2857b3a75 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -32,8 +32,10 @@
 #include <Triangulate/triangle.hxx>
 
 
-// load regular grid of elevation data (dem based)
+// load regular grid of elevation data (dem based), return list of
+// fitted nodes
 int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
+    fitnode_list result;
     char tile_name[256];
     string base = b.gen_base_path();
     long int b_index = b.gen_index();
@@ -44,8 +46,10 @@ int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
     cout << "dem_path = " << dem_path << endl;
 
     if ( ! array.open(dem_path) ) {
+	cout << "ERROR: cannot open " << dem_path << endl;
 	return 0;
     }
+
     array.parse();
     array.fit( 100 );
 
@@ -133,21 +137,26 @@ int load_polys( const string& work_base, FGBucket& b, FGClipper& clipper) {
 
 
 // triangulate the data for each polygon
-void triangulate( const FGArray& array, const FGClipper& clipper,
+void do_triangulate( const FGArray& array, const FGClipper& clipper,
 		  FGTriangle& t ) {
-    // first we need to consolidate the points of all the polygons
-    // into a more "Triangle" friendly format
-    FGgpcPolyList gpc_polys;
+    // first we need to consolidate the points of the DEM fit list and
+    // all the polygons into a more "Triangle" friendly format
 
-    gpc_polys = clipper.get_polys_clipped();
+    fitnode_list fit_list = array.get_fit_node_list();
+    FGgpcPolyList gpc_polys = clipper.get_polys_clipped();
 
     cout << "ready to build node list and polygons" << endl;
-    t.build( gpc_polys );
+    t.build( fit_list, gpc_polys );
     cout << "done building node list and polygons" << endl;
+
+    cout << "ready to do triangulation" << endl;
+    t.run_triangulate();
+    cout << "finished triangulation" << endl;
 }
 
 
 main(int argc, char **argv) {
+    fitnode_list fit_list;
     double lon, lat;
 
     if ( argc != 2 ) {
@@ -173,11 +182,15 @@ main(int argc, char **argv) {
 
     // triangulate the data for each polygon
     FGTriangle t;
-    triangulate( array, clipper, t );
+    do_triangulate( array, clipper, t );
 }
 
 
 // $Log$
+// Revision 1.4  1999/03/20 20:32:54  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.3  1999/03/19 00:26:52  curt
 // Minor tweaks ...
 //
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 6db46c16c..ad03d3eb1 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -25,7 +25,6 @@
 #include "triangle.hxx"
 #include "tripoly.hxx"
 
-
 // Constructor
 FGTriangle::FGTriangle( void ) {
 }
@@ -37,11 +36,23 @@ FGTriangle::~FGTriangle( void ) {
 
 
 // populate this class based on the specified gpc_polys list
-int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
+int 
+FGTriangle::build( const fitnode_list& fit_list, 
+		   const FGgpcPolyList& gpc_polys )
+{
     int index;
-    // traverse the gpc_polys and build a unified node list and a set
-    // of Triangle PSLG that reference the node list by index
-    // (starting at zero)
+
+    // traverse the dem fit list and gpc_polys building a unified node
+    // list and converting the polygons so that they reference the
+    // node list by index (starting at zero) rather than listing the
+    // points explicitely
+
+    const_fitnode_list_iterator f_current, f_last;
+    f_current = fit_list.begin();
+    f_last = fit_list.end();
+    for ( ; f_current != f_last; ++f_current ) {
+	index = trinodes.unique_add( *f_current );
+    }
 
     gpc_polygon *gpc_poly;
     const_gpcpoly_iterator current, last;
@@ -67,7 +78,7 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 
 	    if (gpc_poly->num_contours > 1 ) {
 		cout << "FATAL ERROR! no multi-contour support" << endl;
-		sleep(5);
+		sleep(2);
 		// exit(-1);
 	    }
 
@@ -93,30 +104,31 @@ int FGTriangle::build( const FGgpcPolyList& gpc_polys ) {
 		 << polylist[i].size() << endl;
 	}
     }
-    return 0;
-}
 
+    // traverse the polygon lists and build the segment (edge) list
+    // that is used by the "Triangle" lib.
 
-// do actual triangulation
-int FGTriangle::do_triangulate( const FGTriPoly& poly ) {
-    trinode_list node_list;
-    struct triangulateio in, out;
-    int counter;
+    FGTriPoly poly;
+    int i1, i2;
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	cout << "area type = " << i << endl;
+	tripoly_list_iterator tp_current, tp_last;
+	tp_current = polylist[i].begin();
+	tp_last = polylist[i].end();
 
-    // define input points
-    node_list = trinodes.get_node_list();
+	// process each polygon in list
+	for ( ; tp_current != tp_last; ++tp_current ) {
+	    poly = *tp_current;
 
-    in.numberofpoints = node_list.size();
-    in.numberofpointattributes = 0;
-    in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
-
-    trinode_list_iterator current, last;
-    current = node_list.begin();
-    last = node_list.end();
-    counter = 0;
-    for ( ; current != last; ++current ) {
-	in.pointlist[counter++] = current->x();
-	in.pointlist[counter++] = current->y();
+	    for ( int j = 0; j < (int)(poly.size()) - 1; ++j ) {
+		i1 = poly.get_pt_index( j );
+		i2 = poly.get_pt_index( j + 1 );
+		trisegs.unique_add( FGTriSeg(i1, i2) );
+	    }
+	    i1 = poly.get_pt_index( 0 );
+	    i2 = poly.get_pt_index( poly.size() - 1 );
+	    trisegs.unique_add( FGTriSeg(i1, i2) );
+	}
     }
 
     return 0;
@@ -124,72 +136,175 @@ int FGTriangle::do_triangulate( const FGTriPoly& poly ) {
 
 
 // triangulate each of the polygon areas
-int FGTriangle::triangulate() {
+int FGTriangle::run_triangulate() {
     FGTriPoly poly;
-    struct triangulateio in, out;
-
-    trinode_list node_list = trinodes.get_node_list();
+    Point3D p;
+    struct triangulateio in, out, vorout;
+    int counter;
 
     // point list
+    trinode_list node_list = trinodes.get_node_list();
     in.numberofpoints = node_list.size();
-    in.numberofpointattributes = 1;
     in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
 
     trinode_list_iterator tn_current, tn_last;
     tn_current = node_list.begin();
     tn_last = node_list.end();
-    int counter = 0;
+    counter = 0;
     for ( ; tn_current != tn_last; ++tn_current ) {
 	in.pointlist[counter++] = tn_current->x();
 	in.pointlist[counter++] = tn_current->y();
     }
 
-    in.pointattributelist = (REAL *) NULL;
-    in.pointmarkerlist = (int *) NULL;
+    in.numberofpointattributes = 1;
+    in.pointattributelist = (REAL *) malloc(in.numberofpoints *
+					    in.numberofpointattributes *
+					    sizeof(REAL));
+    for ( int i = 0; i < in.numberofpoints * in.numberofpointattributes; i++) {
+	in.pointattributelist[i] = 0.0;
+    }
+
+    in.pointmarkerlist = (int *) malloc(in.numberofpoints * sizeof(int));
+    for ( int i = 0; i < in.numberofpoints; i++) {
+	in.pointmarkerlist[i] = 0;
+    }
 
     // segment list
-    in.numberofsegments = 0;
+    triseg_list seg_list = trisegs.get_seg_list();
+    in.numberofsegments = seg_list.size();
+    in.segmentlist = (int *) malloc(in.numberofsegments * 2 * sizeof(int));
 
-    tripoly_list_iterator tp_current, tp_last;
+    triseg_list_iterator s_current, s_last;
+    s_current = seg_list.begin();
+    s_last = seg_list.end();
+    counter = 0;
+    for ( ; s_current != s_last; ++s_current ) {
+	in.segmentlist[counter++] = s_current->get_n1();
+	in.segmentlist[counter++] = s_current->get_n2();
+    }
+
+    // hole list (make holes for airport ignore areas)
+    in.numberofholes = polylist[(int)AirportIgnoreArea].size();
+    in.holelist = (REAL *) malloc(in.numberofholes * 2 * sizeof(REAL));
+
+    tripoly_list_iterator h_current, h_last;
+    h_current = polylist[(int)AirportIgnoreArea].begin();
+    h_last = polylist[(int)AirportIgnoreArea].end();
+    counter = 0;
+    for ( ; h_current != h_last; ++h_current ) {
+	poly = *h_current;
+	p = poly.get_point_inside();
+	in.holelist[counter++] = p.x();
+	in.holelist[counter++] = p.y();
+    }
+
+    // region list
+    in.numberofregions = 0;
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	cout << "area type = " << i << endl;
-	tp_current = polylist[i].begin();
-	tp_last = polylist[i].end();
-	for ( ; tp_current != tp_last; ++tp_current ) {
-	    poly = *tp_current;
-	    in.numberofsegments += poly.size() + 1;
+	in.numberofregions += polylist[i].size();
+    }
+
+    in.regionlist = (REAL *) malloc(in.numberofregions * 4 * sizeof(REAL));
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	tripoly_list_iterator h_current, h_last;
+	h_current = polylist[(int)AirportIgnoreArea].begin();
+	h_last = polylist[(int)AirportIgnoreArea].end();
+	counter = 0;
+	for ( ; h_current != h_last; ++h_current ) {
+	    poly = *h_current;
+	    p = poly.get_point_inside();
+	    in.regionlist[counter++] = p.x();  // x coord
+	    in.regionlist[counter++] = p.y();  // y coord
+	    in.regionlist[counter++] = i;      // region attribute
+	    in.regionlist[counter++] = -1.0;   // area constraint (unused)
 	}
     }
 
-    in.numberofsegments = 0;
+    // prep the output structures
+    out.pointlist = (REAL *) NULL;        // Not needed if -N switch used.
+    // Not needed if -N switch used or number of point attributes is zero:
+    out.pointattributelist = (REAL *) NULL;
+    out.pointmarkerlist = (int *) NULL;   // Not needed if -N or -B switch used.
+    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;
+    out.neighborlist = (int *) NULL;      // Needed only if -n switch used.
+    // Needed only if segments are output (-p or -c) and -P not used:
+    out.segmentlist = (int *) NULL;
+    // Needed only if segments are output (-p or -c) and -P and -B not used:
+    out.segmentmarkerlist = (int *) NULL;
+    out.edgelist = (int *) NULL;          // Needed only if -e switch used.
+    out.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), and a triangle neighbor list (n).
 
-  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. */
+    triangulate("pczAen", &in, &out, &vorout);
 
-  /*
-    tripoly_list_iterator current, last;
-    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	cout << "area type = " << i << endl;
-	current = polylist[i].begin();
-	last = polylist[i].end();
-	for ( ; current != last; ++current ) {
-	    poly = *current;
-	    cout << "triangulating a polygon, size = " << poly.size() << endl;
+    // TEMPORARY
+    //
 
-	    do_triangulate( poly );
-	}
+    // Write out the triangulated data to files so we can check
+    // visually that things seem reasonable
+
+    FILE *node = fopen("tile.node", "w");
+    fprintf(node, "%d 2 %d 0\n", 
+	    out.numberofpoints, out.numberofpointattributes);
+    for (int i = 0; i < out.numberofpoints; i++) {
+	fprintf(node, "%d %.6f %.6f %.2f\n", 
+		i, out.pointlist[2*i], out.pointlist[2*i + 1], 0.0);
     }
-    */
+    fclose(node);
+
+    FILE *ele = fopen("tile.ele", "w");
+    fprintf(ele, "%d 3 0\n", out.numberoftriangles);
+    for (int i = 0; i < out.numberoftriangles; i++) {
+        fprintf(ele, "%d ", i);
+        for (int j = 0; j < out.numberofcorners; j++) {
+	    fprintf(ele, "%d ", out.trianglelist[i * out.numberofcorners + j]);
+        }
+        fprintf(ele, "\n");
+    }
+    fclose(ele);
+
+    // free mem allocated to the "Triangle" structures
+    free(in.pointlist);
+    free(in.pointattributelist);
+    free(in.pointmarkerlist);
+    free(in.regionlist);
+    free(out.pointlist);
+    free(out.pointattributelist);
+    free(out.pointmarkerlist);
+    free(out.trianglelist);
+    free(out.triangleattributelist);
+    // free(out.trianglearealist);
+    free(out.neighborlist);
+    free(out.segmentlist);
+    free(out.segmentmarkerlist);
+    free(out.edgelist);
+    free(out.edgemarkerlist);
+    free(vorout.pointlist);
+    free(vorout.pointattributelist);
+    free(vorout.edgelist);
+    free(vorout.normlist);
+
     return 0;
 }
 
 
 // $Log$
+// Revision 1.7  1999/03/20 20:32:55  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.6  1999/03/20 13:22:11  curt
 // Added trisegs.[ch]xx tripoly.[ch]xx.
 //
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index 58fa1bd26..0a115fd73 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -35,6 +35,7 @@
 
 #include <vector>
 
+#include <Array/array.hxx>
 #include <Clipper/clipper.hxx>
 #include <Math/point3d.hxx>
 #include <Polygon/names.hxx>
@@ -46,6 +47,7 @@ extern "C" {
 
 #include "trinodes.hxx"
 #include "tripoly.hxx"
+#include "trisegs.hxx"
 
 FG_USING_STD(vector);
 
@@ -59,9 +61,15 @@ class FGTriangle {
 
 private:
 
+    // list of nodes
     FGTriNodes trinodes;
-    tripoly_list polylist[FG_MAX_AREA_TYPES];
 
+    // list of segments
+    FGTriSegments trisegs;
+
+    // polygon list
+    tripoly_list polylist[FG_MAX_AREA_TYPES];
+    
 public:
 
     // Constructor and destructor
@@ -72,13 +80,10 @@ public:
     int add_nodes();
 
     // populate this class based on the specified gpc_polys list
-    int build( const FGgpcPolyList& gpc_polys );
-
-    // do actual triangulation
-    int do_triangulate( const FGTriPoly& poly );
+    int build( const fitnode_list& fit_list, const FGgpcPolyList& gpc_polys );
 
     // front end triangulator for polygon list
-    int triangulate();
+    int run_triangulate();
 };
 
 
@@ -86,6 +91,10 @@ public:
 
 
 // $Log$
+// Revision 1.6  1999/03/20 20:32:56  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.5  1999/03/20 02:21:53  curt
 // Continue shaping the code towards triangulation bliss.  Added code to
 // calculate some point guaranteed to be inside a polygon.
diff --git a/Triangulate/tripoly.hxx b/Triangulate/tripoly.hxx
index 92986247c..73a5e8338 100644
--- a/Triangulate/tripoly.hxx
+++ b/Triangulate/tripoly.hxx
@@ -64,9 +64,13 @@ public:
     // return size
     inline int size() const { return poly.size(); }
 
+    // return the ith polygon point index
+    inline int get_pt_index( int i ) const { return poly[i]; }
+
     // calculate an "arbitrary" point inside this polygon for
     // assigning attribute areas
     void calc_point_inside( const FGTriNodes& trinodes );
+    inline Point3D get_point_inside() const { return inside; }
 };
 
 
@@ -74,6 +78,10 @@ public:
 
 
 // $Log$
+// Revision 1.2  1999/03/20 20:32:58  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.1  1999/03/20 13:21:36  curt
 // Initial revision.
 //
diff --git a/Triangulate/trisegs.cxx b/Triangulate/trisegs.cxx
index 55853e6ce..d3ce0eec1 100644
--- a/Triangulate/trisegs.cxx
+++ b/Triangulate/trisegs.cxx
@@ -25,7 +25,48 @@
 #include "trisegs.hxx"
 
 
+// Constructor 
+FGTriSegments::FGTriSegments( void ) {
+}
+
+
+// Destructor
+FGTriSegments::~FGTriSegments( void ) {
+}
+
+
+// Add a point to the point list if it doesn't already exist.
+// Returns the index (starting at zero) of the point in the list.
+int FGTriSegments::unique_add( const FGTriSeg& s ) {
+    triseg_list_iterator current, last;
+    int counter = 0;
+
+    cout << s.get_n1() << "," << s.get_n2() << endl;
+
+    // see if point already exists
+    current = seg_list.begin();
+    last = seg_list.end();
+    for ( ; current != last; ++current ) {
+	if ( s == *current ) {
+	    cout << "found an existing segment match" << endl;
+	    return counter;
+	}
+	
+	++counter;
+    }
+
+    // add to list
+    seg_list.push_back( s );
+
+    return counter;
+}
+
+
 // $Log$
+// Revision 1.2  1999/03/20 20:32:59  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.1  1999/03/20 13:21:36  curt
 // Initial revision.
 //
diff --git a/Triangulate/trisegs.hxx b/Triangulate/trisegs.hxx
index 534b694f5..31189d591 100644
--- a/Triangulate/trisegs.hxx
+++ b/Triangulate/trisegs.hxx
@@ -40,10 +40,31 @@ FG_USING_STD(vector);
 
 // a segment is two integer pointers into the node list
 class FGTriSeg {
-public:
     int n1, n2;
+
+public:
+
+    // Constructor and destructor
+    inline FGTriSeg( void ) { };
+    inline FGTriSeg( int i1, int i2 ) { n1 = i1; n2 = i2; }
+
+    inline ~FGTriSeg( void ) { };
+
+    inline int get_n1() const { return n1; }
+    inline void set_n1( int i ) { n1 = i; }
+    inline int get_n2() const { return n2; }
+    inline void set_n2( int i ) { n2 = i; }
+
+    friend bool operator == (const FGTriSeg& a, const FGTriSeg& b);
+
 };
 
+inline bool operator == (const FGTriSeg& a, const FGTriSeg& b)
+{
+    return ((a.n1 == b.n1) && (a.n2 == b.n2)) 
+	|| ((a.n1 == b.n2) && (a.n2 == b.n1));
+}
+
 
 typedef vector < FGTriSeg > triseg_list;
 typedef triseg_list::iterator triseg_list_iterator;
@@ -78,6 +99,10 @@ public:
 
 
 // $Log$
+// Revision 1.2  1999/03/20 20:33:00  curt
+// First mostly successful tile triangulation works.  There's plenty of tweaking
+// to do, but we are marching in the right direction.
+//
 // Revision 1.1  1999/03/20 13:21:36  curt
 // Initial revision.
 //

From 033af0d05c2f8ebd7f85db12c8e7d78b53412ec2 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 21 Mar 1999 14:02:05 +0000
Subject: [PATCH 240/283] Added a mechanism to dump out the triangle structures
 for viewing. Fixed a couple bugs in first pass at triangulation. - needed to
 explicitely initialize the polygon accumulator in triangle.cxx   before each
 polygon rather than depending on the default behavior. - Fixed a problem with
 region attribute propagation where I wasn't generating   the hole points
 correctly.

---
 Main/construct.cxx       |  16 +++++-
 Triangulate/triangle.cxx | 116 +++++++++++++++++++++++++++++----------
 Triangulate/tripoly.hxx  |  10 ++++
 3 files changed, 109 insertions(+), 33 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index 2857b3a75..0c5ccb7c3 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -166,9 +166,11 @@ main(int argc, char **argv) {
 
     string work_base = argv[1];
    
-    lon = -146.248360; lat = 61.133950;  // PAVD (Valdez, AK)
-    // lon = -110.664244; lat = 33.352890;  // P13
-    lon = -89.744682312011719; lat= 29.314495086669922;
+    // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
+    // lon = -110.664244; lat = 33.352890;     // P13
+    // lon = -93.211389; lat = 45.145000;      // KANE
+    lon = -92.486188; lat = 44.590190;      // KRGK
+    // lon = -89.744682312011719; lat= 29.314495086669922;
 
     FGBucket b( lon, lat );
 
@@ -187,6 +189,14 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.5  1999/03/21 14:02:05  curt
+// Added a mechanism to dump out the triangle structures for viewing.
+// Fixed a couple bugs in first pass at triangulation.
+// - needed to explicitely initialize the polygon accumulator in triangle.cxx
+//   before each polygon rather than depending on the default behavior.
+// - Fixed a problem with region attribute propagation where I wasn't generating
+//   the hole points correctly.
+//
 // Revision 1.4  1999/03/20 20:32:54  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index ad03d3eb1..ddef5bf03 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -40,8 +40,14 @@ int
 FGTriangle::build( const fitnode_list& fit_list, 
 		   const FGgpcPolyList& gpc_polys )
 {
+    FGTriPoly poly;
     int index;
 
+    // Point3D junkp;
+    // int junkc = 0;
+    // char junkn[256];
+    // FILE *junkfp;
+
     // traverse the dem fit list and gpc_polys building a unified node
     // list and converting the polygons so that they reference the
     // node list by index (starting at zero) rather than listing the
@@ -69,8 +75,6 @@ FGTriangle::build( const fitnode_list& fit_list,
 	    cout << "processing a polygon, contours = " 
 		 << gpc_poly->num_contours << endl;
 
-	    FGTriPoly poly;
-
 	    if (gpc_poly->num_contours <= 0 ) {
 		cout << "FATAL ERROR! no contours in this polygon" << endl;
 		exit(-1);
@@ -83,14 +87,27 @@ FGTriangle::build( const fitnode_list& fit_list,
 	    }
 
 	    for ( int j = 0; j < gpc_poly->num_contours; j++ ) {
+
+		poly.erase();
+
+		// sprintf(junkn, "g.%d", junkc++);
+		// junkfp = fopen(junkn, "w");
+
 		for ( int k = 0; k < gpc_poly->contour[j].num_vertices; k++ ) {
 		    Point3D p( gpc_poly->contour[j].vertex[k].x,
 			       gpc_poly->contour[j].vertex[k].y,
 			       0 );
 		    index = trinodes.unique_add( p );
+		    // junkp = trinodes.get_node( index );
+		    // fprintf(junkfp, "%.4f %.4f\n", junkp.x(), junkp.y());
 		    poly.add_node(index);
 		    // cout << index << endl;
 		}
+		// fprintf(junkfp, "%.4f %.4f\n", 
+		//    gpc_poly->contour[j].vertex[0].x, 
+		//    gpc_poly->contour[j].vertex[0].y);
+		// fclose(junkfp);
+
 		poly.calc_point_inside( trinodes );
 
 		polylist[i].push_back(poly);
@@ -108,7 +125,6 @@ FGTriangle::build( const fitnode_list& fit_list,
     // traverse the polygon lists and build the segment (edge) list
     // that is used by the "Triangle" lib.
 
-    FGTriPoly poly;
     int i1, i2;
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
 	cout << "area type = " << i << endl;
@@ -135,6 +151,55 @@ FGTriangle::build( const fitnode_list& fit_list,
 }
 
 
+static void write_out_data(struct triangulateio *out) {
+    FILE *node = fopen("tile.node", "w");
+    fprintf(node, "%d 2 %d 0\n", 
+	    out->numberofpoints, out->numberofpointattributes);
+    for (int i = 0; i < out->numberofpoints; i++) {
+	fprintf(node, "%d %.6f %.6f %.2f\n", 
+		i, out->pointlist[2*i], out->pointlist[2*i + 1], 0.0);
+    }
+    fclose(node);
+
+    FILE *ele = fopen("tile.ele", "w");
+    fprintf(ele, "%d 3 0\n", out->numberoftriangles);
+    for (int i = 0; i < out->numberoftriangles; i++) {
+        fprintf(ele, "%d ", i);
+        for (int j = 0; j < out->numberofcorners; j++) {
+	    fprintf(ele, "%d ", out->trianglelist[i * out->numberofcorners + j]);
+        }
+        for (int j = 0; j < out->numberoftriangleattributes; j++) {
+	    fprintf(ele, "%.6f ", 
+		    out->triangleattributelist[i 
+					      * out->numberoftriangleattributes
+					      + j]
+		    );
+        }
+	fprintf(ele, "\n");
+    }
+    fclose(ele);
+
+    FILE *fp = fopen("tile.poly", "w");
+    fprintf(fp, "0 2 1 0\n");
+    fprintf(fp, "%d 0\n", out->numberofsegments);
+    for (int i = 0; i < out->numberofsegments; ++i) {
+	fprintf(fp, "%d %d %d\n", 
+		i, out->segmentlist[2*i], out->segmentlist[2*i + 1]);
+    }
+    fprintf(fp, "%d\n", out->numberofholes);
+    for (int i = 0; i < out->numberofholes; i++) {
+	fprintf(fp, "%d %.6f %.6f\n", 
+		i, out->holelist[2*i], out->holelist[2*i + 1]);
+    }
+    fprintf(fp, "%d\n", out->numberofregions);
+    for (int i = 0; i < out->numberofregions; i++) {
+	fprintf(fp, "%d %.6f %.6f %.6f\n", 
+		i, out->regionlist[4*i], out->regionlist[4*i + 1],
+		out->regionlist[4*i + 2]);
+    }
+}
+
+
 // triangulate each of the polygon areas
 int FGTriangle::run_triangulate() {
     FGTriPoly poly;
@@ -169,6 +234,9 @@ int FGTriangle::run_triangulate() {
 	in.pointmarkerlist[i] = 0;
     }
 
+    // triangle list
+    in.numberoftriangles = 0;
+
     // segment list
     triseg_list seg_list = trisegs.get_seg_list();
     in.numberofsegments = seg_list.size();
@@ -205,11 +273,11 @@ int FGTriangle::run_triangulate() {
     }
 
     in.regionlist = (REAL *) malloc(in.numberofregions * 4 * sizeof(REAL));
+    counter = 0;
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
 	tripoly_list_iterator h_current, h_last;
-	h_current = polylist[(int)AirportIgnoreArea].begin();
-	h_last = polylist[(int)AirportIgnoreArea].end();
-	counter = 0;
+	h_current = polylist[(int)i].begin();
+	h_last = polylist[(int)i].end();
 	for ( ; h_current != h_last; ++h_current ) {
 	    poly = *h_current;
 	    p = poly.get_point_inside();
@@ -242,6 +310,9 @@ int FGTriangle::run_triangulate() {
     vorout.edgelist = (int *) NULL;       // Needed only if -v switch used.
     vorout.normlist = (REAL *) NULL;      // Needed only if -v switch used.
     
+    // TEMPORARY
+    // write_out_data(&in);
+
     // 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),
@@ -250,30 +321,7 @@ int FGTriangle::run_triangulate() {
     triangulate("pczAen", &in, &out, &vorout);
 
     // TEMPORARY
-    //
-
-    // Write out the triangulated data to files so we can check
-    // visually that things seem reasonable
-
-    FILE *node = fopen("tile.node", "w");
-    fprintf(node, "%d 2 %d 0\n", 
-	    out.numberofpoints, out.numberofpointattributes);
-    for (int i = 0; i < out.numberofpoints; i++) {
-	fprintf(node, "%d %.6f %.6f %.2f\n", 
-		i, out.pointlist[2*i], out.pointlist[2*i + 1], 0.0);
-    }
-    fclose(node);
-
-    FILE *ele = fopen("tile.ele", "w");
-    fprintf(ele, "%d 3 0\n", out.numberoftriangles);
-    for (int i = 0; i < out.numberoftriangles; i++) {
-        fprintf(ele, "%d ", i);
-        for (int j = 0; j < out.numberofcorners; j++) {
-	    fprintf(ele, "%d ", out.trianglelist[i * out.numberofcorners + j]);
-        }
-        fprintf(ele, "\n");
-    }
-    fclose(ele);
+    write_out_data(&out);
 
     // free mem allocated to the "Triangle" structures
     free(in.pointlist);
@@ -301,6 +349,14 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.8  1999/03/21 14:02:06  curt
+// Added a mechanism to dump out the triangle structures for viewing.
+// Fixed a couple bugs in first pass at triangulation.
+// - needed to explicitely initialize the polygon accumulator in triangle.cxx
+//   before each polygon rather than depending on the default behavior.
+// - Fixed a problem with region attribute propagation where I wasn't generating
+//   the hole points correctly.
+//
 // Revision 1.7  1999/03/20 20:32:55  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.
diff --git a/Triangulate/tripoly.hxx b/Triangulate/tripoly.hxx
index 73a5e8338..8115a8969 100644
--- a/Triangulate/tripoly.hxx
+++ b/Triangulate/tripoly.hxx
@@ -71,6 +71,8 @@ public:
     // assigning attribute areas
     void calc_point_inside( const FGTriNodes& trinodes );
     inline Point3D get_point_inside() const { return inside; }
+
+    inline void erase() { poly.erase( poly.begin(), poly.end() ); }
 };
 
 
@@ -78,6 +80,14 @@ public:
 
 
 // $Log$
+// Revision 1.3  1999/03/21 14:02:07  curt
+// Added a mechanism to dump out the triangle structures for viewing.
+// Fixed a couple bugs in first pass at triangulation.
+// - needed to explicitely initialize the polygon accumulator in triangle.cxx
+//   before each polygon rather than depending on the default behavior.
+// - Fixed a problem with region attribute propagation where I wasn't generating
+//   the hole points correctly.
+//
 // Revision 1.2  1999/03/20 20:32:58  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.

From 6090cde756cffbc0d0e99a6207c0778d72e71c6c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 21 Mar 1999 14:04:11 +0000
Subject: [PATCH 241/283] Define -DANSI_DECLARATORS so that library get's built
 with ANSI function prototyping.

---
 Triangle/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Triangle/Makefile.am b/Triangle/Makefile.am
index f07cb8e4e..6095c3b69 100644
--- a/Triangle/Makefile.am
+++ b/Triangle/Makefile.am
@@ -9,7 +9,7 @@
 #
 #   DEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
 
-DEFS += -DTRILIBRARY -DREDUCED
+DEFS += -DTRILIBRARY -DREDUCED -DANSI_DECLARATORS
 
 noinst_LIBRARIES = libTriangle.a
 

From 2f890285e059269565f590d235697e5705f16cca Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 21 Mar 1999 14:09:04 +0000
Subject: [PATCH 242/283] Changed the way I handle #define ANSI_DECLARATORS

---
 Triangle/Makefile.am | 2 +-
 Triangle/triangle.h  | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Triangle/Makefile.am b/Triangle/Makefile.am
index 6095c3b69..f07cb8e4e 100644
--- a/Triangle/Makefile.am
+++ b/Triangle/Makefile.am
@@ -9,7 +9,7 @@
 #
 #   DEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
 
-DEFS += -DTRILIBRARY -DREDUCED -DANSI_DECLARATORS
+DEFS += -DTRILIBRARY -DREDUCED
 
 noinst_LIBRARIES = libTriangle.a
 
diff --git a/Triangle/triangle.h b/Triangle/triangle.h
index 8fb543044..b9be696c3 100644
--- a/Triangle/triangle.h
+++ b/Triangle/triangle.h
@@ -245,6 +245,11 @@
 /*                                                                           */
 /*****************************************************************************/
 
+/* CLO: 3/21/99 - this could be done as a compile flag, but I always want
+this defined and I don't want to sprinkle extra stuff throughout the 
+Makefile system if I don't have to. */
+#define ANSI_DECLARATORS 1
+
 struct triangulateio {
   REAL *pointlist;                                               /* In / out */
   REAL *pointattributelist;                                      /* In / out */

From 88dd01563918ee273bebd71c1f4f2ff514e2275c Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sun, 21 Mar 1999 15:48:00 +0000
Subject: [PATCH 243/283] Removed Dem2node from the Tools fold. Tweaked the
 triangulator options to add quality mesh refinement.

---
 Main/construct.cxx       | 8 ++++++--
 Tools/Makefile.am        | 1 -
 Triangulate/triangle.cxx | 6 +++++-
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index 0c5ccb7c3..ddc15922d 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -169,8 +169,8 @@ main(int argc, char **argv) {
     // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
     // lon = -110.664244; lat = 33.352890;     // P13
     // lon = -93.211389; lat = 45.145000;      // KANE
-    lon = -92.486188; lat = 44.590190;      // KRGK
-    // lon = -89.744682312011719; lat= 29.314495086669922;
+    // lon = -92.486188; lat = 44.590190;      // KRGK
+    lon = -89.744682312011719; lat= 29.314495086669922;
 
     FGBucket b( lon, lat );
 
@@ -189,6 +189,10 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.6  1999/03/21 15:48:01  curt
+// Removed Dem2node from the Tools fold.
+// Tweaked the triangulator options to add quality mesh refinement.
+//
 // Revision 1.5  1999/03/21 14:02:05  curt
 // Added a mechanism to dump out the triangle structures for viewing.
 // Fixed a couple bugs in first pass at triangulation.
diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index eca54bea6..a448801a7 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -7,7 +7,6 @@ SUBDIRS = \
 	Utils \
 	Areas \
 	AssemTris \
-	Dem2node \
 	FixNode \
 	FixObj \
 	SplitTris \
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index ddef5bf03..1c2476837 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -318,7 +318,7 @@ int FGTriangle::run_triangulate() {
     // from zero (z), assign a regional attribute to each element (A),
     // and produce an edge list (e), and a triangle neighbor list (n).
 
-    triangulate("pczAen", &in, &out, &vorout);
+    triangulate("pczq15Aen", &in, &out, &vorout);
 
     // TEMPORARY
     write_out_data(&out);
@@ -349,6 +349,10 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.9  1999/03/21 15:48:02  curt
+// Removed Dem2node from the Tools fold.
+// Tweaked the triangulator options to add quality mesh refinement.
+//
 // Revision 1.8  1999/03/21 14:02:06  curt
 // Added a mechanism to dump out the triangle structures for viewing.
 // Fixed a couple bugs in first pass at triangulation.

From b8c705fb281b25114c8ad0a6a810713ab91b1029 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 22 Mar 1999 23:48:20 +0000
Subject: [PATCH 244/283] Added GenOutput/

---
 Construct/Makefile.am | 1 +
 Main/Makefile.am      | 1 +
 Main/construct.cxx    | 7 +++++++
 3 files changed, 9 insertions(+)

diff --git a/Construct/Makefile.am b/Construct/Makefile.am
index ee75460ff..d3901496a 100644
--- a/Construct/Makefile.am
+++ b/Construct/Makefile.am
@@ -1,5 +1,6 @@
 SUBDIRS = \
 	Array \
 	Clipper \
+	GenOutput \
 	Triangulate \
 	Main
diff --git a/Main/Makefile.am b/Main/Makefile.am
index 618351e7f..06acce5b2 100644
--- a/Main/Makefile.am
+++ b/Main/Makefile.am
@@ -5,6 +5,7 @@ construct_SOURCES = construct.cxx
 construct_LDADD = \
 	$(top_builddir)/Tools/Construct/Array/libArray.a \
 	$(top_builddir)/Tools/Construct/Clipper/libClipper.a \
+	$(top_builddir)/Tools/Construct/GenOutput/libGenOutput.a \
 	$(top_builddir)/Tools/Construct/Triangulate/libTriangulate.a \
 	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Tools/Lib/Triangle/libTriangle.a \
diff --git a/Main/construct.cxx b/Main/construct.cxx
index ddc15922d..629df1918 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -29,6 +29,7 @@
 
 #include <Array/array.hxx>
 #include <Clipper/clipper.hxx>
+#include <GenOutput/genobj.hxx>
 #include <Triangulate/triangle.hxx>
 
 
@@ -185,10 +186,16 @@ main(int argc, char **argv) {
     // triangulate the data for each polygon
     FGTriangle t;
     do_triangulate( array, clipper, t );
+
+    // generate the output
+    fgGenOutput( t );
 }
 
 
 // $Log$
+// Revision 1.7  1999/03/22 23:48:29  curt
+// Added GenOutput/
+//
 // Revision 1.6  1999/03/21 15:48:01  curt
 // Removed Dem2node from the Tools fold.
 // Tweaked the triangulator options to add quality mesh refinement.

From 4c1565c869ab4da8b2b34e91b1ea41aa1c9c2a2b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 22 Mar 1999 23:49:01 +0000
Subject: [PATCH 245/283] Modifications to facilitate conversion to output
 format.

---
 Triangulate/Makefile.am  |  1 +
 Triangulate/triangle.cxx | 35 ++++++++++++++++++++++++++++++-----
 Triangulate/triangle.hxx | 16 +++++++++++++++-
 Triangulate/trinodes.cxx | 11 +++++++++++
 Triangulate/trinodes.hxx |  6 ++++++
 5 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/Triangulate/Makefile.am b/Triangulate/Makefile.am
index 42ba81984..34c320f91 100644
--- a/Triangulate/Makefile.am
+++ b/Triangulate/Makefile.am
@@ -2,6 +2,7 @@ noinst_LIBRARIES = libTriangulate.a
 
 libTriangulate_a_SOURCES = \
 	triangle.cxx triangle.hxx \
+	trieles.cxx trieles.hxx \
 	trinodes.cxx trinodes.hxx \
 	tripoly.cxx tripoly.hxx \
 	trisegs.cxx trisegs.hxx
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 1c2476837..4e5265bb2 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -57,7 +57,7 @@ FGTriangle::build( const fitnode_list& fit_list,
     f_current = fit_list.begin();
     f_last = fit_list.end();
     for ( ; f_current != f_last; ++f_current ) {
-	index = trinodes.unique_add( *f_current );
+	index = in_nodes.unique_add( *f_current );
     }
 
     gpc_polygon *gpc_poly;
@@ -97,8 +97,8 @@ FGTriangle::build( const fitnode_list& fit_list,
 		    Point3D p( gpc_poly->contour[j].vertex[k].x,
 			       gpc_poly->contour[j].vertex[k].y,
 			       0 );
-		    index = trinodes.unique_add( p );
-		    // junkp = trinodes.get_node( index );
+		    index = in_nodes.unique_add( p );
+		    // junkp = in_nodes.get_node( index );
 		    // fprintf(junkfp, "%.4f %.4f\n", junkp.x(), junkp.y());
 		    poly.add_node(index);
 		    // cout << index << endl;
@@ -108,7 +108,7 @@ FGTriangle::build( const fitnode_list& fit_list,
 		//    gpc_poly->contour[j].vertex[0].y);
 		// fclose(junkfp);
 
-		poly.calc_point_inside( trinodes );
+		poly.calc_point_inside( in_nodes );
 
 		polylist[i].push_back(poly);
 	    }
@@ -208,7 +208,7 @@ int FGTriangle::run_triangulate() {
     int counter;
 
     // point list
-    trinode_list node_list = trinodes.get_node_list();
+    trinode_list node_list = in_nodes.get_node_list();
     in.numberofpoints = node_list.size();
     in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
 
@@ -241,6 +241,7 @@ int FGTriangle::run_triangulate() {
     triseg_list seg_list = trisegs.get_seg_list();
     in.numberofsegments = seg_list.size();
     in.segmentlist = (int *) malloc(in.numberofsegments * 2 * sizeof(int));
+    in.segmentmarkerlist = (int *) NULL;
 
     triseg_list_iterator s_current, s_last;
     s_current = seg_list.begin();
@@ -323,6 +324,27 @@ int FGTriangle::run_triangulate() {
     // TEMPORARY
     write_out_data(&out);
 
+    // now copy the results back into the corresponding FGTriangle
+    // structures
+
+    // nodes
+    for ( int i = 0; i < out.numberofpoints; i++ ) {
+	Point3D p( out.pointlist[2*i], out.pointlist[2*i + 1], 0.0 );
+	// cout << "point = " << p << endl;
+	out_nodes.simple_add( p );
+    }
+
+    // triangles
+    int n1, n2, n3;
+    for ( int i = 0; i < out.numberoftriangles; i++ ) {
+	n1 = out.trianglelist[i * 3];
+	n2 = out.trianglelist[i * 3 + 1];
+	n3 = out.trianglelist[i * 3 + 2];
+	// cout << "triangle = " << n1 << " " << n2 << " " << n3 << endl;
+
+	elelist.push_back( FGTriEle( n1, n2, n3 ) );
+    }
+
     // free mem allocated to the "Triangle" structures
     free(in.pointlist);
     free(in.pointattributelist);
@@ -349,6 +371,9 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.10  1999/03/22 23:49:02  curt
+// Modifications to facilitate conversion to output format.
+//
 // Revision 1.9  1999/03/21 15:48:02  curt
 // Removed Dem2node from the Tools fold.
 // Tweaked the triangulator options to add quality mesh refinement.
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index 0a115fd73..de26cd625 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -45,6 +45,7 @@ extern "C" {
 #include <Triangle/triangle.h>
 }
 
+#include "trieles.hxx"
 #include "trinodes.hxx"
 #include "tripoly.hxx"
 #include "trisegs.hxx"
@@ -56,13 +57,18 @@ typedef vector < FGTriPoly > tripoly_list;
 typedef tripoly_list::iterator tripoly_list_iterator;
 typedef tripoly_list::const_iterator const_tripoly_list_iterator;
 
+typedef vector < FGTriEle > triele_list;
+typedef triele_list::iterator triele_list_iterator;
+typedef triele_list::const_iterator const_triele_list_iterator;
+
 
 class FGTriangle {
 
 private:
 
     // list of nodes
-    FGTriNodes trinodes;
+    FGTriNodes in_nodes;
+    FGTriNodes out_nodes;
 
     // list of segments
     FGTriSegments trisegs;
@@ -70,6 +76,9 @@ private:
     // polygon list
     tripoly_list polylist[FG_MAX_AREA_TYPES];
     
+    // triangle list
+    triele_list elelist;
+
 public:
 
     // Constructor and destructor
@@ -84,6 +93,8 @@ public:
 
     // front end triangulator for polygon list
     int run_triangulate();
+
+    inline FGTriNodes get_out_nodes() const { return out_nodes; }
 };
 
 
@@ -91,6 +102,9 @@ public:
 
 
 // $Log$
+// Revision 1.7  1999/03/22 23:49:03  curt
+// Modifications to facilitate conversion to output format.
+//
 // Revision 1.6  1999/03/20 20:32:56  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.
diff --git a/Triangulate/trinodes.cxx b/Triangulate/trinodes.cxx
index d29e907b1..3acc7775d 100644
--- a/Triangulate/trinodes.cxx
+++ b/Triangulate/trinodes.cxx
@@ -74,7 +74,18 @@ int FGTriNodes::unique_add( const Point3D& p ) {
 }
 
 
+// Add the point with no uniqueness checking
+int FGTriNodes::simple_add( const Point3D& p ) {
+    node_list.push_back( p );
+
+    return node_list.size() - 1;
+}
+
+
 // $Log$
+// Revision 1.4  1999/03/22 23:49:04  curt
+// Modifications to facilitate conversion to output format.
+//
 // Revision 1.3  1999/03/20 02:21:54  curt
 // Continue shaping the code towards triangulation bliss.  Added code to
 // calculate some point guaranteed to be inside a polygon.
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
index 3a3d31beb..cd14e1299 100644
--- a/Triangulate/trinodes.hxx
+++ b/Triangulate/trinodes.hxx
@@ -68,6 +68,9 @@ public:
     // Returns the index (starting at zero) of the point in the list.
     int unique_add( const Point3D& p );
 
+    // Add the point with no uniqueness checking
+    int simple_add( const Point3D& p );
+
     // return the master node list
     inline trinode_list get_node_list() const { return node_list; }
 
@@ -80,6 +83,9 @@ public:
 
 
 // $Log$
+// Revision 1.4  1999/03/22 23:49:05  curt
+// Modifications to facilitate conversion to output format.
+//
 // Revision 1.3  1999/03/20 02:21:55  curt
 // Continue shaping the code towards triangulation bliss.  Added code to
 // calculate some point guaranteed to be inside a polygon.

From 4525fcbd5584a5e1baa54a92c859b83a17c046e8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 22 Mar 1999 23:49:29 +0000
Subject: [PATCH 246/283] Moved AreaType get_shapefile_type(GDBFile *dbf, int
 rec) to where it belongs in ShapeFile/

---
 Polygon/names.cxx  | 45 ++++-----------------------------------------
 Polygon/names.hxx  | 18 ++++--------------
 ShapeFile/main.cxx | 45 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 55 deletions(-)

diff --git a/Polygon/names.cxx b/Polygon/names.cxx
index 7e6d2a320..eabd8697e 100644
--- a/Polygon/names.cxx
+++ b/Polygon/names.cxx
@@ -28,47 +28,6 @@
 #include "names.hxx"
 
 
-// return the type of the shapefile record
-AreaType get_shapefile_type(GDBFile *dbf, int rec) {
-    // GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
-    GDBFValue *fields;		//an array of field values
-    char* dbf_rec;		//a record containing all the fields
-
-    // grab the meta-information for all the fields
-    // this applies to all the records in the DBF file.
-    // for ( int i = 0; i < dbf->numFields(); i++ ) {
-    //   fdesc[i] = dbf->getFieldDesc(i);
-    //   cout << i << ") " << fdesc[i]->name << endl;
-    // }
-
-    // this is the whole name record
-    dbf_rec = dbf->getRecord( rec );
-
-    // parse it into individual fields
-    if ( dbf_rec ) {
-	fields = dbf->recordDeform( dbf_rec );
-    } else {
-	return UnknownArea;
-    }
-
-    string area = fields[4].str_v;
-    // strip leading spaces
-    while ( area[0] == ' ' ) {
-	area = area.substr(1, area.length() - 1);
-    }
-    // strip trailing spaces
-    while ( area[area.length() - 1] == ' ' ) {
-	area = area.substr(0, area.length() - 1);
-    }
-    // strip other junk encountered
-    while ( (int)area[area.length() - 1] == 9 ) {
-	area = area.substr(0, area.length() - 1);
-    }
-
-    return get_area_type( area );
-}
-
-
 // return area type from text name
 AreaType get_area_type( string area ) {
     if ( area == "AirportKeep" ) {
@@ -151,6 +110,10 @@ string get_area_name( AreaType area ) {
 
 
 // $Log$
+// Revision 1.5  1999/03/22 23:49:29  curt
+// Moved AreaType get_shapefile_type(GDBFile *dbf, int rec) to where it
+// belongs in ShapeFile/
+//
 // Revision 1.4  1999/03/13 18:47:04  curt
 // Removed an unused variable.
 //
diff --git a/Polygon/names.hxx b/Polygon/names.hxx
index 168df64d8..78c85d339 100644
--- a/Polygon/names.hxx
+++ b/Polygon/names.hxx
@@ -26,17 +26,6 @@
 #define _NAMES_HXX
 
 
-// libgfc.a includes need this bit o' strangeness
-#if defined ( linux )
-#  define _LINUX_
-#endif
-#include <gfc/gadt_polygon.h>
-#include <gfc/gdbf.h>
-#undef E
-#undef DEG_TO_RAD
-#undef RAD_TO_DEG
-
-
 // Posible shape file types.  Note the order of these is important and
 // defines the priority of these shapes if they should intersect.  The
 // smaller the number, the higher the priority.
@@ -59,9 +48,6 @@ enum AreaType {
 };
 
 
-// return the type of the shapefile record
-AreaType get_shapefile_type(GDBFile *dbf, int rec);
-
 // return area type from text name
 AreaType get_area_type( string area );
 
@@ -73,6 +59,10 @@ string get_area_name( AreaType area );
 
 
 // $Log$
+// Revision 1.4  1999/03/22 23:49:30  curt
+// Moved AreaType get_shapefile_type(GDBFile *dbf, int rec) to where it
+// belongs in ShapeFile/
+//
 // Revision 1.3  1999/03/01 15:35:53  curt
 // Generalized the routines a bit to make them more useful.
 //
diff --git a/ShapeFile/main.cxx b/ShapeFile/main.cxx
index f85ec18b4..b0e629575 100644
--- a/ShapeFile/main.cxx
+++ b/ShapeFile/main.cxx
@@ -53,6 +53,47 @@ extern "C" {
 #include "shape.hxx"
 
 
+// return the type of the shapefile record
+AreaType get_shapefile_type(GDBFile *dbf, int rec) {
+    // GDBFieldDesc *fdesc[128];	// 128 is an arbitrary number here
+    GDBFValue *fields;		//an array of field values
+    char* dbf_rec;		//a record containing all the fields
+
+    // grab the meta-information for all the fields
+    // this applies to all the records in the DBF file.
+    // for ( int i = 0; i < dbf->numFields(); i++ ) {
+    //   fdesc[i] = dbf->getFieldDesc(i);
+    //   cout << i << ") " << fdesc[i]->name << endl;
+    // }
+
+    // this is the whole name record
+    dbf_rec = dbf->getRecord( rec );
+
+    // parse it into individual fields
+    if ( dbf_rec ) {
+	fields = dbf->recordDeform( dbf_rec );
+    } else {
+	return UnknownArea;
+    }
+
+    string area = fields[4].str_v;
+    // strip leading spaces
+    while ( area[0] == ' ' ) {
+	area = area.substr(1, area.length() - 1);
+    }
+    // strip trailing spaces
+    while ( area[area.length() - 1] == ' ' ) {
+	area = area.substr(0, area.length() - 1);
+    }
+    // strip other junk encountered
+    while ( (int)area[area.length() - 1] == 9 ) {
+	area = area.substr(0, area.length() - 1);
+    }
+
+    return get_area_type( area );
+}
+
+
 int main( int argc, char **argv ) {
     gpc_polygon gpc_shape;
     int i, j;
@@ -265,6 +306,10 @@ int main( int argc, char **argv ) {
 
 
 // $Log$
+// Revision 1.8  1999/03/22 23:49:36  curt
+// Moved AreaType get_shapefile_type(GDBFile *dbf, int rec) to where it
+// belongs in ShapeFile/
+//
 // Revision 1.7  1999/03/17 23:51:29  curt
 // Changed polygon index counter file.
 //

From da6ff2100123b01a791620083e964976a630d815 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 22 Mar 1999 23:51:51 +0000
Subject: [PATCH 247/283] Initial revision.

---
 GenOutput/Makefile.am |  9 +++++
 GenOutput/genobj.cxx  | 85 +++++++++++++++++++++++++++++++++++++++++++
 GenOutput/genobj.hxx  | 48 ++++++++++++++++++++++++
 3 files changed, 142 insertions(+)
 create mode 100644 GenOutput/Makefile.am
 create mode 100644 GenOutput/genobj.cxx
 create mode 100644 GenOutput/genobj.hxx

diff --git a/GenOutput/Makefile.am b/GenOutput/Makefile.am
new file mode 100644
index 000000000..28ad535a2
--- /dev/null
+++ b/GenOutput/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libGenOutput.a
+
+libGenOutput_a_SOURCES = genobj.cxx genobj.hxx
+
+INCLUDES += \
+	-I$(top_builddir) \
+	-I$(top_builddir)/Lib \
+	-I$(top_builddir)/Tools/Lib \
+	-I$(top_builddir)/Tools/Construct
diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
new file mode 100644
index 000000000..634765d1d
--- /dev/null
+++ b/GenOutput/genobj.cxx
@@ -0,0 +1,85 @@
+// genobj.hxx -- Generate the flight gear "obj" file format from the
+//               triangle output
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include "genobj.hxx"
+
+
+// Calculate the global bounding sphere from all the input points.
+// Center is the average of the points.
+static void calc_gbs( const trinode_list& nodelist, Point3D *center, 
+		      double *radius )
+{
+    double x = 0;
+    double y = 0;
+    double z = 0;
+
+    double dist_squared;
+    double radius_squared = 0;
+    
+    const_trinode_list_iterator current = nodelist.begin();
+    const_trinode_list_iterator last = nodelist.end();
+
+    for ( ; current != last; ++current ) {
+	x += current->x();
+	y += current->y();
+	z += current->z();
+    }
+
+    x /= nodelist.size();
+    y /= nodelist.size();
+    z /= nodelist.size();
+
+    *center = Point3D(x, y, z);
+
+    current = nodelist.begin();
+    for ( ; current != last; ++current ) {
+        dist_squared = center->distance3Dsquared(*current);
+	if ( dist_squared > radius_squared ) {
+            radius_squared = dist_squared;
+        }
+    }
+
+    *radius = sqrt(radius_squared);
+}
+
+
+// generate the flight gear format from the triangulation
+int fgGenOutput( const FGTriangle& t ) {
+    Point3D gbs;
+    double gradius;
+
+    FGTriNodes trinodes = t.get_out_nodes();
+    trinode_list nodelist = trinodes.get_node_list();
+
+    calc_gbs( nodelist, &gbs, &gradius );
+    cout << "center = " << gbs << " radius = " << gradius << endl;
+    return 1;
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/22 23:51:51  curt
+// Initial revision.
+//
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
new file mode 100644
index 000000000..45f2b0082
--- /dev/null
+++ b/GenOutput/genobj.hxx
@@ -0,0 +1,48 @@
+// genobj.hxx -- Generate the flight gear "obj" file format from the
+//               triangle output
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _GENOBJ_HXX
+#define _GENOBJ_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Triangulate/triangle.hxx>
+
+
+// generate the flight gear format from the triangulation
+int fgGenOutput( const FGTriangle& t );
+
+
+#endif // _GENOBJ_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/22 23:51:51  curt
+// Initial revision.
+//

From bd31ce9a20b69500165f92f843e04a1d403b1d93 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 22 Mar 1999 23:58:57 +0000
Subject: [PATCH 248/283] Initial revision.

---
 Triangulate/trieles.cxx | 31 ++++++++++++++++++++
 Triangulate/trieles.hxx | 64 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)
 create mode 100644 Triangulate/trieles.cxx
 create mode 100644 Triangulate/trieles.hxx

diff --git a/Triangulate/trieles.cxx b/Triangulate/trieles.cxx
new file mode 100644
index 000000000..406a19a91
--- /dev/null
+++ b/Triangulate/trieles.cxx
@@ -0,0 +1,31 @@
+// trieles.cxx -- "Triangle" element management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include "trieles.hxx"
+
+
+// $Log$
+// Revision 1.1  1999/03/22 23:58:57  curt
+// Initial revision.
+//
diff --git a/Triangulate/trieles.hxx b/Triangulate/trieles.hxx
new file mode 100644
index 000000000..5c4440b72
--- /dev/null
+++ b/Triangulate/trieles.hxx
@@ -0,0 +1,64 @@
+// trieles.hxx -- "Triangle" element management class
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _TRIELES_HXX
+#define _TRIELES_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+
+// a segment is two integer pointers into the node list
+class FGTriEle {
+    int n1, n2, n3;
+
+public:
+
+    // Constructor and destructor
+    inline FGTriEle( void ) { };
+    inline FGTriEle( int i1, int i2, int i3 ) { n1 = i1; n2 = i2; n3 = i3; }
+
+    inline ~FGTriEle( void ) { };
+
+    inline int get_n1() const { return n1; }
+    inline void set_n1( int i ) { n1 = i; }
+    inline int get_n2() const { return n2; }
+    inline void set_n2( int i ) { n2 = i; }
+    inline int get_n3() const { return n3; }
+    inline void set_n3( int i ) { n3 = i; }
+};
+
+
+#endif // _TRIELES_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/22 23:58:57  curt
+// Initial revision.
+//

From 1dce89b1aae21ac1611e8c2cf9d539c30b197175 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 23 Mar 1999 17:44:49 +0000
Subject: [PATCH 249/283] Beginning work on generating output scenery.

---
 GenOutput/genobj.hxx | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index 45f2b0082..76ce3aee2 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -32,9 +32,30 @@
 #endif                                   
 
 
+#include <Math/point3d.hxx>
 #include <Triangulate/triangle.hxx>
 
 
+typedef vector < Point3D > wgs84_node_list;
+typedef wgs84_node_list::iterator wgs84_node_list_iterator;
+typedef wgs84_node_list::const_iterator const_wgs84_node_list_iterator;
+
+typedef vector < Point3D > normal_list;
+typedef normal_list::iterator normal_list_iterator;
+typedef normal_list::const_iterator const_normal_list_iterator;
+
+class FGGenOutput {
+
+private:
+
+    wgs84_node_list wgs84_nodes;
+    normal_list normals;
+
+public:
+    
+};
+
+
 // generate the flight gear format from the triangulation
 int fgGenOutput( const FGTriangle& t );
 
@@ -43,6 +64,9 @@ int fgGenOutput( const FGTriangle& t );
 
 
 // $Log$
+// Revision 1.2  1999/03/23 17:44:49  curt
+// Beginning work on generating output scenery.
+//
 // Revision 1.1  1999/03/22 23:51:51  curt
 // Initial revision.
 //

From 427762b074451a066d314e719ced0c6204e6f898 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 23 Mar 1999 22:02:03 +0000
Subject: [PATCH 250/283] Worked on creating data to output ... normals,
 bounding spheres, etc.

---
 GenOutput/genobj.cxx | 284 +++++++++++++++++++++++++++++++++++++++----
 GenOutput/genobj.hxx |  81 ++++++++++--
 Main/construct.cxx   |  13 +-
 3 files changed, 342 insertions(+), 36 deletions(-)

diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index 634765d1d..06c5a0799 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -23,14 +23,130 @@
 // (Log is kept at end of this file)
 
 
+#include <time.h>
+
+#include <Tools/scenery_version.hxx>
+#include <Math/mat3.h>
+
 #include "genobj.hxx"
 
 
-// Calculate the global bounding sphere from all the input points.
-// Center is the average of the points.
-static void calc_gbs( const trinode_list& nodelist, Point3D *center, 
-		      double *radius )
-{
+// build the wgs-84 point list
+void FGGenOutput::gen_wgs84_points() {
+    cout << "calculating wgs84 point" << endl;
+    Point3D geod, radians, cart;
+
+    const_point_list_iterator current = geod_nodes.begin();
+    const_point_list_iterator last = geod_nodes.end();
+
+    for ( ; current != last; ++current ) {
+	geod = *current;
+
+	// convert to radians
+	radians = Point3D( geod.x() * DEG_TO_RAD,
+			   geod.y() * DEG_TO_RAD,
+			   geod.z() );
+
+        cart = fgGeodToCart(radians);
+	// cout << cart << endl;
+        wgs84_nodes.push_back(cart);
+    }
+}
+
+
+// build the node -> element (triangle) reverse lookup table.  there
+// is an entry for each point containing a list of all the triangles
+// that share that point.
+void FGGenOutput::gen_node_ele_lookup_table() {
+    belongs_to ele_list;
+    ele_list.erase( ele_list.begin(), ele_list.end() );
+
+    // initialize reverse_ele_lookup structure by creating an empty
+    // list for each point
+    const_point_list_iterator w_current = wgs84_nodes.begin();
+    const_point_list_iterator w_last = wgs84_nodes.end();
+    for ( ; w_current != w_last; ++w_current ) {
+	reverse_ele_lookup.push_back( ele_list );
+    }
+
+    // traverse triangle structure building reverse lookup table
+    const_triele_list_iterator current = tri_elements.begin();
+    const_triele_list_iterator last = tri_elements.end();
+    int counter = 0;
+    for ( ; current != last; ++current ) {
+	reverse_ele_lookup[ current->get_n1() ].push_back( counter );
+	reverse_ele_lookup[ current->get_n2() ].push_back( counter );
+	reverse_ele_lookup[ current->get_n3() ].push_back( counter );
+	++counter;
+    }
+}
+
+
+// caclulate the normal for the specified triangle face
+Point3D FGGenOutput::calc_normal( int i ) {
+    double v1[3], v2[3], normal[3];
+    double temp;
+
+    Point3D p1 = wgs84_nodes[ tri_elements[i].get_n1() ];
+    Point3D p2 = wgs84_nodes[ tri_elements[i].get_n2() ];
+    Point3D p3 = wgs84_nodes[ tri_elements[i].get_n3() ];
+
+    v1[0] = p2.x() - p1.x(); v1[1] = p2.y() - p1.y(); v1[2] = p2.z() - p1.z();
+    v2[0] = p3.x() - p1.x(); v2[1] = p3.y() - p1.y(); v2[2] = p3.z() - p1.z();
+
+    MAT3cross_product(normal, v1, v2);
+    MAT3_NORMALIZE_VEC(normal,temp);
+
+    return Point3D( normal[0], normal[1], normal[2] );
+}
+
+
+// build the face normal list
+void FGGenOutput::gen_face_normals() {
+    // traverse triangle structure building the face normal table
+
+    cout << "calculating face normals" << endl;
+
+    for ( int i = 0; i < (int)tri_elements.size(); i++ ) {
+	// cout << calc_normal( i ) << endl;
+	face_normals.push_back( calc_normal( i ) );
+    }
+
+}
+
+
+// calculate the normals for each point in wgs84_nodes
+void FGGenOutput::gen_normals() {
+    Point3D normal;
+    cout << "caculating node normals" << endl;
+
+    // for each node
+    for ( int i = 0; i < (int)wgs84_nodes.size(); ++i ) {
+	belongs_to tri_list = reverse_ele_lookup[i];
+
+	belongs_to_iterator current = tri_list.begin();
+	belongs_to_iterator last = tri_list.end();
+
+	Point3D average( 0.0 );
+
+	// for each triangle that shares this node
+	for ( ; current != last; ++current ) {
+	    normal = face_normals[ *current ];
+	    average += normal;
+	    // cout << normal << endl;
+	}
+
+	average /= tri_list.size();
+	// cout << "average = " << average << endl;
+
+	point_normals.push_back( average );
+    }
+}
+
+
+// calculate the global bounding sphere.  Center is the average of the
+// points.
+void FGGenOutput::calc_gbs() {
     double x = 0;
     double y = 0;
     double z = 0;
@@ -38,8 +154,8 @@ static void calc_gbs( const trinode_list& nodelist, Point3D *center,
     double dist_squared;
     double radius_squared = 0;
     
-    const_trinode_list_iterator current = nodelist.begin();
-    const_trinode_list_iterator last = nodelist.end();
+    const_point_list_iterator current = wgs84_nodes.begin();
+    const_point_list_iterator last = wgs84_nodes.end();
 
     for ( ; current != last; ++current ) {
 	x += current->x();
@@ -47,39 +163,163 @@ static void calc_gbs( const trinode_list& nodelist, Point3D *center,
 	z += current->z();
     }
 
-    x /= nodelist.size();
-    y /= nodelist.size();
-    z /= nodelist.size();
+    x /= wgs84_nodes.size();
+    y /= wgs84_nodes.size();
+    z /= wgs84_nodes.size();
 
-    *center = Point3D(x, y, z);
+    gbs_center = Point3D(x, y, z);
 
-    current = nodelist.begin();
+    current =  wgs84_nodes.begin();
     for ( ; current != last; ++current ) {
-        dist_squared = center->distance3Dsquared(*current);
+        dist_squared = gbs_center.distance3Dsquared(*current);
 	if ( dist_squared > radius_squared ) {
             radius_squared = dist_squared;
         }
     }
 
-    *radius = sqrt(radius_squared);
+    gbs_radius = sqrt(radius_squared);
 }
 
 
-// generate the flight gear format from the triangulation
-int fgGenOutput( const FGTriangle& t ) {
-    Point3D gbs;
-    double gradius;
-
+// build the necessary output structures based on the triangulation
+// data
+int FGGenOutput::build( const FGTriangle& t ) {
     FGTriNodes trinodes = t.get_out_nodes();
-    trinode_list nodelist = trinodes.get_node_list();
 
-    calc_gbs( nodelist, &gbs, &gradius );
-    cout << "center = " << gbs << " radius = " << gradius << endl;
+    // copy the geodetic node list into this class
+    geod_nodes = trinodes.get_node_list();
+
+    // copy the triangle list into this class
+    tri_elements = t.get_elelist();
+
+    // generate the point list in wgs-84 coordinates
+    gen_wgs84_points();
+
+    // calculate the global bounding sphere
+    calc_gbs();
+    cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
+
+    // build the node -> element (triangle) reverse lookup table
+    gen_node_ele_lookup_table();
+
+    // build the face normal list
+    gen_face_normals();
+
+    // calculate the normals for each point in wgs84_nodes
+    gen_normals();
+
+    return 1;
+}
+
+
+// caclulate the bounding sphere for the specified triangle face
+void FGGenOutput::calc_bounding_sphere( int i, Point3D *center, 
+					double *radius ) {
+    Point3D c( 0.0 );
+
+    Point3D p1 = wgs84_nodes[ tri_elements[i].get_n1() ];
+    Point3D p2 = wgs84_nodes[ tri_elements[i].get_n2() ];
+    Point3D p3 = wgs84_nodes[ tri_elements[i].get_n3() ];
+
+    c = p1 + p2 + p3;
+    c /= 3;
+
+    double dist_squared;
+    double max_squared = 0;
+
+    dist_squared = c.distance3Dsquared(p1);
+    if ( dist_squared > max_squared ) {
+	max_squared = dist_squared;
+    }
+
+    dist_squared = c.distance3Dsquared(p2);
+    if ( dist_squared > max_squared ) {
+	max_squared = dist_squared;
+    }
+
+    dist_squared = c.distance3Dsquared(p3);
+    if ( dist_squared > max_squared ) {
+	max_squared = dist_squared;
+    }
+
+    *center = c;
+    *radius = sqrt(max_squared);
+}
+
+
+// write out the fgfs scenery file
+int FGGenOutput::write( const string& path ) {
+    Point3D p;
+
+    FILE *fp;
+    if ( (fp = fopen( path.c_str(), "w" )) == NULL ) {
+	cout << "ERROR: opening " << path << " for writing!" << endl;
+	exit(-1);
+    }
+
+    // write headers
+    fprintf(fp, "# FGFS Scenery Version %s\n", FG_SCENERY_FILE_FORMAT);
+
+    time_t calendar_time = time(NULL);
+    struct tm *local_tm;
+    local_tm = localtime( &calendar_time );
+    char time_str[256];
+    strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm);
+    fprintf(fp, "# Created %s\n", time_str );
+    fprintf(fp, "\n");
+
+    // write global bounding spher
+    fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n",
+	    gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
+    fprintf(fp, "\n");
+
+    // write nodes
+    fprintf(fp, "# vertex list\n");
+    const_point_list_iterator w_current = wgs84_nodes.begin();
+    const_point_list_iterator w_last = wgs84_nodes.end();
+    for ( ; w_current != w_last; ++w_current ) {
+	p = *w_current - gbs_center;
+	fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
+    }
+    fprintf(fp, "\n");
+    
+    // write vertex normals
+    fprintf(fp, "# vertex normal list\n");
+    const_point_list_iterator n_current = point_normals.begin();
+    const_point_list_iterator n_last = point_normals.end();
+    for ( ; n_current != n_last; ++n_current ) {
+	p = *n_current;
+	fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
+    }
+    fprintf(fp, "\n");
+
+    // write triangles
+    Point3D center;
+    double radius;
+    fprintf(fp, "# triangle list\n");
+    fprintf(fp, "\n");
+    const_triele_list_iterator t_current = tri_elements.begin();
+    const_triele_list_iterator t_last = tri_elements.end();
+    int counter = 0;
+    for ( ; t_current != t_last; ++t_current ) {
+	calc_bounding_sphere( counter, &center, &radius );
+	fprintf(fp, "# usemtl desert1\n");
+	fprintf(fp, "# bs %.2f %.2f %.2f %.2f\n", 
+		center.x(), center.y(), center.z(), radius);
+	fprintf(fp, "f %d %d %d\n", 
+		t_current->get_n1(), t_current->get_n2(), t_current->get_n3());
+	fprintf(fp, "\n");
+	++counter;
+    }
+
     return 1;
 }
 
 
 // $Log$
+// Revision 1.2  1999/03/23 22:02:03  curt
+// Worked on creating data to output ... normals, bounding spheres, etc.
+//
 // Revision 1.1  1999/03/22 23:51:51  curt
 // Initial revision.
 //
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index 76ce3aee2..7afb3076d 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -32,38 +32,93 @@
 #endif                                   
 
 
+#include <Math/fg_geodesy.hxx>
 #include <Math/point3d.hxx>
 #include <Triangulate/triangle.hxx>
 
 
-typedef vector < Point3D > wgs84_node_list;
-typedef wgs84_node_list::iterator wgs84_node_list_iterator;
-typedef wgs84_node_list::const_iterator const_wgs84_node_list_iterator;
+typedef vector < int > belongs_to;
+typedef belongs_to::iterator belongs_to_iterator;
+typedef belongs_to::const_iterator belongs_to_tripoly_iterator;
+
+typedef vector < belongs_to > belongs_to_list;
+typedef belongs_to_list::iterator belongs_to_list_iterator;
+typedef belongs_to_list::const_iterator belongs_to_list_tripoly_iterator;
 
-typedef vector < Point3D > normal_list;
-typedef normal_list::iterator normal_list_iterator;
-typedef normal_list::const_iterator const_normal_list_iterator;
 
 class FGGenOutput {
 
 private:
 
-    wgs84_node_list wgs84_nodes;
-    normal_list normals;
+    // node list in geodetic coordinats
+    point_list geod_nodes;
+
+    // node list in cartesian coords (wgs84 model)
+    point_list wgs84_nodes;
+
+    // face normal list (for flat shading)
+    point_list face_normals;
+
+    // normal list (for each point) in cart coords (for smooth
+    // shading)
+    point_list point_normals;
+
+    // triangles (by index into point list)
+    triele_list tri_elements;
+
+    // for each node, a list of triangle indices that contain this node
+    belongs_to_list reverse_ele_lookup;
+
+    // global bounding sphere
+    Point3D gbs_center;
+    double gbs_radius;
+
+    // build the wgs-84 point list
+    void gen_wgs84_points();
+
+    // build the node -> element (triangle) reverse lookup table.
+    // there is an entry for each point containing a list of all the
+    // triangles that share that point.
+    void gen_node_ele_lookup_table();
+
+    // calculate the normals for each point in wgs84_nodes
+    void gen_normals();
+
+    // build the face normal list
+    void gen_face_normals();
+
+    // caclulate the normal for the specified triangle face
+    Point3D calc_normal( int i );
+
+    // calculate the global bounding sphere.  Center is the average of
+    // the points.
+    void calc_gbs();
+
+    // caclulate the bounding sphere for the specified triangle face
+    void calc_bounding_sphere( int i, Point3D *center, double *radius );
 
 public:
-    
+
+    // Constructor && Destructor
+    inline FGGenOutput() { }
+    inline ~FGGenOutput() { }
+
+    // build the necessary output structures based on the
+    // triangulation data
+    int build( const FGTriangle& t );
+
+    // write out the fgfs scenery file
+    int write( const string& path );
 };
 
 
-// generate the flight gear format from the triangulation
-int fgGenOutput( const FGTriangle& t );
-
-
 #endif // _GENOBJ_HXX
 
 
 // $Log$
+// Revision 1.3  1999/03/23 22:02:04  curt
+// Worked on creating data to output ... normals, bounding spheres, etc.
+//
 // Revision 1.2  1999/03/23 17:44:49  curt
 // Beginning work on generating output scenery.
 //
diff --git a/Main/construct.cxx b/Main/construct.cxx
index 629df1918..23899f797 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -156,6 +156,13 @@ void do_triangulate( const FGArray& array, const FGClipper& clipper,
 }
 
 
+// generate the flight gear scenery file
+void do_output( const FGTriangle& t, FGGenOutput& output ) {
+    output.build( t );
+    output.write( "output" );
+}
+
+
 main(int argc, char **argv) {
     fitnode_list fit_list;
     double lon, lat;
@@ -188,11 +195,15 @@ main(int argc, char **argv) {
     do_triangulate( array, clipper, t );
 
     // generate the output
-    fgGenOutput( t );
+    FGGenOutput output;
+    do_output( t, output );
 }
 
 
 // $Log$
+// Revision 1.8  1999/03/23 22:02:17  curt
+// Worked on creating data to output ... normals, bounding spheres, etc.
+//
 // Revision 1.7  1999/03/22 23:48:29  curt
 // Added GenOutput/
 //

From e774a38dc7a6a79a788e30fccdd8e80f47f08203 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 23 Mar 1999 22:02:51 +0000
Subject: [PATCH 251/283] Refinements in naming and organization.

---
 Triangulate/triangle.cxx |  7 +++++--
 Triangulate/triangle.hxx | 17 ++++-------------
 Triangulate/trieles.hxx  | 12 ++++++++++++
 Triangulate/trinodes.cxx |  5 ++++-
 Triangulate/trinodes.hxx | 13 ++++++++-----
 Triangulate/tripoly.hxx  |  8 ++++++++
 Triangulate/trisegs.cxx  |  7 +++++--
 7 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 4e5265bb2..b1beaa79f 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -208,11 +208,11 @@ int FGTriangle::run_triangulate() {
     int counter;
 
     // point list
-    trinode_list node_list = in_nodes.get_node_list();
+    point_list node_list = in_nodes.get_node_list();
     in.numberofpoints = node_list.size();
     in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
 
-    trinode_list_iterator tn_current, tn_last;
+    point_list_iterator tn_current, tn_last;
     tn_current = node_list.begin();
     tn_last = node_list.end();
     counter = 0;
@@ -371,6 +371,9 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.11  1999/03/23 22:02:51  curt
+// Refinements in naming and organization.
+//
 // Revision 1.10  1999/03/22 23:49:02  curt
 // Modifications to facilitate conversion to output format.
 //
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index de26cd625..ba4fb4cbf 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -33,8 +33,6 @@
 
 #include <Include/compiler.h>
 
-#include <vector>
-
 #include <Array/array.hxx>
 #include <Clipper/clipper.hxx>
 #include <Math/point3d.hxx>
@@ -50,17 +48,6 @@ extern "C" {
 #include "tripoly.hxx"
 #include "trisegs.hxx"
 
-FG_USING_STD(vector);
-
-
-typedef vector < FGTriPoly > tripoly_list;
-typedef tripoly_list::iterator tripoly_list_iterator;
-typedef tripoly_list::const_iterator const_tripoly_list_iterator;
-
-typedef vector < FGTriEle > triele_list;
-typedef triele_list::iterator triele_list_iterator;
-typedef triele_list::const_iterator const_triele_list_iterator;
-
 
 class FGTriangle {
 
@@ -95,6 +82,7 @@ public:
     int run_triangulate();
 
     inline FGTriNodes get_out_nodes() const { return out_nodes; }
+    inline triele_list get_elelist() const { return elelist; }
 };
 
 
@@ -102,6 +90,9 @@ public:
 
 
 // $Log$
+// Revision 1.8  1999/03/23 22:02:52  curt
+// Refinements in naming and organization.
+//
 // Revision 1.7  1999/03/22 23:49:03  curt
 // Modifications to facilitate conversion to output format.
 //
diff --git a/Triangulate/trieles.hxx b/Triangulate/trieles.hxx
index 5c4440b72..8a867fc0e 100644
--- a/Triangulate/trieles.hxx
+++ b/Triangulate/trieles.hxx
@@ -33,6 +33,10 @@
 
 #include <Include/compiler.h>
 
+#include <vector>
+
+FG_USING_STD(vector);
+
 
 // a segment is two integer pointers into the node list
 class FGTriEle {
@@ -55,10 +59,18 @@ public:
 };
 
 
+typedef vector < FGTriEle > triele_list;
+typedef triele_list::iterator triele_list_iterator;
+typedef triele_list::const_iterator const_triele_list_iterator;
+
+
 #endif // _TRIELES_HXX
 
 
 // $Log$
+// Revision 1.2  1999/03/23 22:02:53  curt
+// Refinements in naming and organization.
+//
 // Revision 1.1  1999/03/22 23:58:57  curt
 // Initial revision.
 //
diff --git a/Triangulate/trinodes.cxx b/Triangulate/trinodes.cxx
index 3acc7775d..75b5b302d 100644
--- a/Triangulate/trinodes.cxx
+++ b/Triangulate/trinodes.cxx
@@ -50,7 +50,7 @@ inline bool FGTriNodes::close_enough( const Point3D& p1, const Point3D& p2 ) {
 // Add a point to the point list if it doesn't already exist.  Returns
 // the index (starting at zero) of the point in the list.
 int FGTriNodes::unique_add( const Point3D& p ) {
-    trinode_list_iterator current, last;
+    point_list_iterator current, last;
     int counter = 0;
 
     // cout << p.x() << "," << p.y() << endl;
@@ -83,6 +83,9 @@ int FGTriNodes::simple_add( const Point3D& p ) {
 
 
 // $Log$
+// Revision 1.5  1999/03/23 22:02:54  curt
+// Refinements in naming and organization.
+//
 // Revision 1.4  1999/03/22 23:49:04  curt
 // Modifications to facilitate conversion to output format.
 //
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
index cd14e1299..ab1b36504 100644
--- a/Triangulate/trinodes.hxx
+++ b/Triangulate/trinodes.hxx
@@ -43,16 +43,16 @@ FG_USING_STD(vector);
 #define FG_PROXIMITY_EPSILON 0.000001
 
 
-typedef vector < Point3D > trinode_list;
-typedef trinode_list::iterator trinode_list_iterator;
-typedef trinode_list::const_iterator const_trinode_list_iterator;
+typedef vector < Point3D > point_list;
+typedef point_list::iterator point_list_iterator;
+typedef point_list::const_iterator const_point_list_iterator;
 
 
 class FGTriNodes {
 
 private:
 
-    trinode_list node_list;
+    point_list node_list;
 
     // return true of the two points are "close enough" as defined by
     // FG_PROXIMITY_EPSILON
@@ -72,7 +72,7 @@ public:
     int simple_add( const Point3D& p );
 
     // return the master node list
-    inline trinode_list get_node_list() const { return node_list; }
+    inline point_list get_node_list() const { return node_list; }
 
     // return the ith point
     inline Point3D get_node( int i ) const { return node_list[i]; }
@@ -83,6 +83,9 @@ public:
 
 
 // $Log$
+// Revision 1.5  1999/03/23 22:02:55  curt
+// Refinements in naming and organization.
+//
 // Revision 1.4  1999/03/22 23:49:05  curt
 // Modifications to facilitate conversion to output format.
 //
diff --git a/Triangulate/tripoly.hxx b/Triangulate/tripoly.hxx
index 8115a8969..0cd87d00c 100644
--- a/Triangulate/tripoly.hxx
+++ b/Triangulate/tripoly.hxx
@@ -76,10 +76,18 @@ public:
 };
 
 
+typedef vector < FGTriPoly > tripoly_list;
+typedef tripoly_list::iterator tripoly_list_iterator;
+typedef tripoly_list::const_iterator const_tripoly_list_iterator;
+
+
 #endif // _TRIPOLY_HXX
 
 
 // $Log$
+// Revision 1.4  1999/03/23 22:02:56  curt
+// Refinements in naming and organization.
+//
 // Revision 1.3  1999/03/21 14:02:07  curt
 // Added a mechanism to dump out the triangle structures for viewing.
 // Fixed a couple bugs in first pass at triangulation.
diff --git a/Triangulate/trisegs.cxx b/Triangulate/trisegs.cxx
index d3ce0eec1..6d4ac1bb5 100644
--- a/Triangulate/trisegs.cxx
+++ b/Triangulate/trisegs.cxx
@@ -41,14 +41,14 @@ int FGTriSegments::unique_add( const FGTriSeg& s ) {
     triseg_list_iterator current, last;
     int counter = 0;
 
-    cout << s.get_n1() << "," << s.get_n2() << endl;
+    // cout << s.get_n1() << "," << s.get_n2() << endl;
 
     // see if point already exists
     current = seg_list.begin();
     last = seg_list.end();
     for ( ; current != last; ++current ) {
 	if ( s == *current ) {
-	    cout << "found an existing segment match" << endl;
+	    // cout << "found an existing segment match" << endl;
 	    return counter;
 	}
 	
@@ -63,6 +63,9 @@ int FGTriSegments::unique_add( const FGTriSeg& s ) {
 
 
 // $Log$
+// Revision 1.3  1999/03/23 22:02:57  curt
+// Refinements in naming and organization.
+//
 // Revision 1.2  1999/03/20 20:32:59  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.

From 48e3734e8fa480c3b7ec52901105939de2cd02be Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Mar 1999 19:03:50 +0000
Subject: [PATCH 252/283] Minor tweaks related to FGBucket usage.

---
 Array/array.cxx     | 14 +++++++-------
 Array/testarray.cxx |  6 +-----
 DEM/dem.cxx         |  9 ++++-----
 3 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/Array/array.cxx b/Array/array.cxx
index 90e04142d..76d4b7f27 100644
--- a/Array/array.cxx
+++ b/Array/array.cxx
@@ -443,14 +443,13 @@ void FGArray::outputmesh_output_nodes( const string& fg_root, FGBucket& p )
 {
     double exnodes[MAX_EX_NODES][3];
     struct stat stat_buf;
-    string dir;
-    char file[256], exfile[256];
+    string dir, file;
+    char exfile[256];
 #ifdef WIN32
     char tmp_path[256];
 #endif
     string command;
     FILE *fd;
-    long int index;
     int colmin, colmax, rowmin, rowmax;
     int i, j, count, excount, result;
 
@@ -481,13 +480,11 @@ void FGArray::outputmesh_output_nodes( const string& fg_root, FGBucket& p )
     }
 
     // get index and generate output file name
-    index = p.gen_index();
-    sprintf(file, "%s/%ld.node", dir.c_str(), index);
+    file = dir + "/" + p.gen_index_str() + ".node";
 
     // get (optional) extra node file name (in case there is matching
     // .poly file.
-    strcpy(exfile, file);
-    strcat(exfile, ".ex");
+    exfile = file + ".ex";
 
     // load extra nodes if they exist
     excount = 0;
@@ -560,6 +557,9 @@ FGArray::~FGArray( void ) {
 
 
 // $Log$
+// Revision 1.5  1999/03/25 19:03:50  curt
+// Minor tweaks related to FGBucket usage.
+//
 // Revision 1.4  1999/03/20 20:32:51  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.
diff --git a/Array/testarray.cxx b/Array/testarray.cxx
index 9d65c0bf7..74012eb93 100644
--- a/Array/testarray.cxx
+++ b/Array/testarray.cxx
@@ -3,7 +3,6 @@
 #include "array.hxx"
 
 main(int argc, char **argv) {
-    char tile_name[256];
     double lon, lat;
 
     if ( argc != 2 ) {
@@ -12,7 +11,6 @@ main(int argc, char **argv) {
     }
 
     string work_dir = argv[1];
-
    
     lon = -146.248360; lat = 61.133950;  // PAVD (Valdez, AK)
     lon = -110.664244; lat = 33.352890;  // P13
@@ -21,9 +19,7 @@ main(int argc, char **argv) {
     string base = b.gen_base_path();
     string path = work_dir + "/Scenery/" + base;
 
-    long int b_index = b.gen_index();
-    sprintf(tile_name, "%ld", b_index);
-    string arrayfile = path + "/" + tile_name + ".dem";
+    string arrayfile = path + "/" + b.gen_index_str() + ".dem";
     cout << "arrayfile = " << arrayfile << endl;
     
     FGArray a(arrayfile);
diff --git a/DEM/dem.cxx b/DEM/dem.cxx
index b7fdbfc74..e4661a3c7 100644
--- a/DEM/dem.cxx
+++ b/DEM/dem.cxx
@@ -371,8 +371,6 @@ FGDem::parse( ) {
 // corner.
 int
 FGDem::write_area( const string& root, FGBucket& b, bool compress ) {
-    char tile_name[256];
-
     // calculate some boundaries
     double min_x = ( b.get_center_lon() - 0.5 * b.get_width() ) * 3600.0;
     double max_x = ( b.get_center_lon() + 0.5 * b.get_width() ) * 3600.0;
@@ -412,9 +410,7 @@ FGDem::write_area( const string& root, FGBucket& b, bool compress ) {
     string command = "mkdir -p " + path;
     system( command.c_str() );
 
-    long int b_index = b.gen_index();
-    sprintf(tile_name, "%ld", b_index);
-    string demfile = path + "/" + tile_name + ".dem";
+    string demfile = path + "/" + b.gen_index_str() + ".dem";
     cout << "demfile = " << demfile << endl;
 
     // write the file
@@ -869,6 +865,9 @@ FGDem::~FGDem( void ) {
 
 
 // $Log$
+// Revision 1.27  1999/03/25 19:04:36  curt
+// Minor tweaks related to FGBucket usage.
+//
 // Revision 1.26  1999/03/13 17:40:37  curt
 // Moved point interpolation and least squares fitting to contruction program
 // area.

From f33915fd134f33d13b068bb99b07ccc38f25018d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Mar 1999 19:04:21 +0000
Subject: [PATCH 253/283] Preparations for outputing scenery file to correct
 location.

---
 GenOutput/genobj.cxx | 7 +++++--
 GenOutput/genobj.hxx | 6 +++++-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index 06c5a0799..72110fa72 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -248,7 +248,7 @@ void FGGenOutput::calc_bounding_sphere( int i, Point3D *center,
 
 
 // write out the fgfs scenery file
-int FGGenOutput::write( const string& path ) {
+int FGGenOutput::write( const FGBucket& b, const string& path ) {
     Point3D p;
 
     FILE *fp;
@@ -268,7 +268,7 @@ int FGGenOutput::write( const string& path ) {
     fprintf(fp, "# Created %s\n", time_str );
     fprintf(fp, "\n");
 
-    // write global bounding spher
+    // write global bounding sphere
     fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n",
 	    gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
     fprintf(fp, "\n");
@@ -317,6 +317,9 @@ int FGGenOutput::write( const string& path ) {
 
 
 // $Log$
+// Revision 1.3  1999/03/25 19:04:21  curt
+// Preparations for outputing scenery file to correct location.
+//
 // Revision 1.2  1999/03/23 22:02:03  curt
 // Worked on creating data to output ... normals, bounding spheres, etc.
 //
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index 7afb3076d..ed90deef9 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -32,6 +32,7 @@
 #endif                                   
 
 
+#include <Bucket/newbucket.hxx>
 #include <Math/fg_geodesy.hxx>
 #include <Math/point3d.hxx>
 #include <Triangulate/triangle.hxx>
@@ -108,7 +109,7 @@ public:
     int build( const FGTriangle& t );
 
     // write out the fgfs scenery file
-    int write( const string& path );
+    int write( const FGBucket& b, const string& path );
 };
 
 
@@ -116,6 +117,9 @@ public:
 
 
 // $Log$
+// Revision 1.4  1999/03/25 19:04:22  curt
+// Preparations for outputing scenery file to correct location.
+//
 // Revision 1.3  1999/03/23 22:02:04  curt
 // Worked on creating data to output ... normals, bounding spheres, etc.
 //

From 8709db31ae54faf4a4c677ce5a7eaab8dd1cc167 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Mar 1999 19:04:31 +0000
Subject: [PATCH 254/283] Preparations for outputing scenery file to correct
 location. Minor tweaks related to FGBucket usage.

---
 Main/construct.cxx | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index 23899f797..7b7935fca 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -37,13 +37,10 @@
 // fitted nodes
 int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
     fitnode_list result;
-    char tile_name[256];
     string base = b.gen_base_path();
-    long int b_index = b.gen_index();
-    sprintf(tile_name, "%ld", b_index);
 
     string dem_path = work_base + ".dem" + "/Scenery/" + base 
-	+ "/" + tile_name + ".dem";
+	+ "/" + b.gen_index_str() + ".dem";
     cout << "dem_path = " << dem_path << endl;
 
     if ( ! array.open(dem_path) ) {
@@ -61,11 +58,8 @@ int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
 // do actual scan of directory and loading of files
 int actual_load_polys( const string& dir, FGBucket& b, FGClipper& clipper ) {
     int counter = 0;
-    char tile_char[256];
     string base = b.gen_base_path();
-    long int b_index = b.gen_index();
-    sprintf(tile_char, "%ld", b_index);
-    string tile_str = tile_char;
+    string tile_str = b.gen_index_str();
     string ext;
 
     DIR *d;
@@ -157,9 +151,9 @@ void do_triangulate( const FGArray& array, const FGClipper& clipper,
 
 
 // generate the flight gear scenery file
-void do_output( const FGTriangle& t, FGGenOutput& output ) {
+void do_output( const FGBucket &b, const FGTriangle& t, FGGenOutput& output ) {
     output.build( t );
-    output.write( "output" );
+    output.write( b, "output" );
 }
 
 
@@ -196,11 +190,15 @@ main(int argc, char **argv) {
 
     // generate the output
     FGGenOutput output;
-    do_output( t, output );
+    do_output( b, t, output );
 }
 
 
 // $Log$
+// Revision 1.9  1999/03/25 19:04:31  curt
+// Preparations for outputing scenery file to correct location.
+// Minor tweaks related to FGBucket usage.
+//
 // Revision 1.8  1999/03/23 22:02:17  curt
 // Worked on creating data to output ... normals, bounding spheres, etc.
 //

From 68e5a695e8f6dcc1c83114c496747a0ec2766c9a Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 25 Mar 1999 19:13:35 +0000
Subject: [PATCH 255/283] Initial revision.

---
 Tools/scenery_version.hxx | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Tools/scenery_version.hxx

diff --git a/Tools/scenery_version.hxx b/Tools/scenery_version.hxx
new file mode 100644
index 000000000..c5616a646
--- /dev/null
+++ b/Tools/scenery_version.hxx
@@ -0,0 +1,31 @@
+// scenery_version.hxx -- Scenery file format version
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#define FG_SCENERY_FILE_FORMAT "0.2"
+
+
+// $Log$
+// Revision 1.1  1999/03/25 19:13:35  curt
+// Initial revision.
+//

From e887aef7e719d21596cea3bd737d9b4dc363149d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 05:20:13 +0000
Subject: [PATCH 256/283] Handle corner nodes separately from the rest of the
 fitted nodes. Fixed some "const" related warnings.

---
 Array/array.cxx | 56 +++++++++++++++++++------------------------------
 Array/array.hxx | 27 ++++++++++--------------
 2 files changed, 32 insertions(+), 51 deletions(-)

diff --git a/Array/array.cxx b/Array/array.cxx
index 76d4b7f27..d7b38c22e 100644
--- a/Array/array.cxx
+++ b/Array/array.cxx
@@ -130,42 +130,24 @@ FGArray::parse() {
 }
 
 
-// add a node to the output (fitted) node list
+// add a node to the output corner node list
+void FGArray::add_corner_node( int i, int j, double val ) {
+    double x = (originx + i * col_step) / 3600.0;
+    double y = (originy + j * row_step) / 3600.0;
+    // cout << Point3D(x, y, val) << endl;
+    corner_list.push_back( Point3D(x, y, val) );
+}
+
+
+// add a node to the output fitted node list
 void FGArray::add_fit_node( int i, int j, double val ) {
     double x = (originx + i * col_step) / 3600.0;
     double y = (originy + j * row_step) / 3600.0;
-    cout << Point3D(x, y, val) << endl;
+    // cout << Point3D(x, y, val) << endl;
     node_list.push_back( Point3D(x, y, val) );
 }
 
 
-#if 0
-// Initialize output mesh structure
-void FGArray::outputmesh_init( void ) {
-    int i, j;
-    
-    for ( j = 0; j < ARRAY_SIZE_1; j++ ) {
-	for ( i = 0; i < ARRAY_SIZE_1; i++ ) {
-	    out_data[i][j] = -9999.0;
-	}
-    }
-}
-
-
-// Get the value of a mesh node
-double FGArray::outputmesh_get_pt( int i, int j ) {
-    return ( out_data[i][j] );
-}
-
-
-// Set the value of a mesh node
-void FGArray::outputmesh_set_pt( int i, int j, double value ) {
-    // cout << "Setting data[" << i << "][" << j << "] = " << value << endl;
-   out_data[i][j] = value;
-}
-#endif
-
-
 // Use least squares to fit a simpler data set to dem data
 void FGArray::fit( double error ) {
     double x[ARRAY_SIZE_1], y[ARRAY_SIZE_1];
@@ -191,11 +173,11 @@ void FGArray::fit( double error ) {
     cout << "  Fitting region = " << colmin << "," << rowmin << " to " 
 	 << colmax << "," << rowmax << endl;;
     
-    // include the corners explicitly
-    add_fit_node( colmin, rowmin, in_data[colmin][rowmin] );
-    add_fit_node( colmin, rowmax-1, in_data[colmin][rowmax] );
-    add_fit_node( colmax-1, rowmin, in_data[colmax][rowmin] );
-    add_fit_node( colmax-1, rowmax-1, in_data[colmax][rowmax] );
+    // generate corners list
+    add_corner_node( colmin, rowmin, in_data[colmin][rowmin] );
+    add_corner_node( colmin, rowmax-1, in_data[colmin][rowmax] );
+    add_corner_node( colmax-1, rowmin, in_data[colmax][rowmin] );
+    add_corner_node( colmax-1, rowmax-1, in_data[colmax][rowmax] );
 
     cout << "  Beginning best fit procedure" << endl;
     lasty = 0;
@@ -320,7 +302,7 @@ void FGArray::fit( double error ) {
 
 // return the current altitude based on grid data.  We should rewrite
 // this to interpolate exact values, but for now this is good enough
-double FGArray::interpolate_altitude( double lon, double lat ) {
+double FGArray::interpolate_altitude( double lon, double lat ) const {
     // we expect incoming (lon,lat) to be in arcsec for now
 
     double xlocal, ylocal, dx, dy, zA, zB, elev;
@@ -557,6 +539,10 @@ FGArray::~FGArray( void ) {
 
 
 // $Log$
+// Revision 1.6  1999/03/27 05:20:13  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Fixed some "const" related warnings.
+//
 // Revision 1.5  1999/03/25 19:03:50  curt
 // Minor tweaks related to FGBucket usage.
 //
diff --git a/Array/array.hxx b/Array/array.hxx
index f90b88b92..ee3c8a37b 100644
--- a/Array/array.hxx
+++ b/Array/array.hxx
@@ -73,22 +73,9 @@ private:
     // float (*out_data)[ARRAY_SIZE_1];
 
     // output nodes
+    fitnode_list corner_list;
     fitnode_list node_list;
 
-    // Initialize output mesh structure
-    // void outputmesh_init( void );
-
-    // Get the value of a mesh node
-    // double outputmesh_get_pt( int i, int j );
-
-    // Set the value of a mesh node
-    // void outputmesh_set_pt( int i, int j, double value );
-
-#if 0
-    // Write out a node file that can be used by the "triangle" program
-    // void outputmesh_output_nodes( const string& fg_root, FGBucket& p );
-#endif
-
 public:
 
     // Constructor
@@ -110,13 +97,16 @@ public:
     // Use least squares to fit a simpler data set to dem data
     void fit( double error );
 
-    // add a node to the output (fitted) node list
+    // add a node to the output corner node list
+    void add_corner_node( int i, int j, double val );
+
+    // add a node to the output fitted node list
     void add_fit_node( int i, int j, double val );
 
     // return the current altitude based on grid data.  We should
     // rewrite this to interpolate exact values, but for now this is
     // good enough
-    double interpolate_altitude( double lon, double lat );
+    double interpolate_altitude( double lon, double lat ) const;
 
     // Informational methods
     inline double get_originx() const { return originx; }
@@ -126,6 +116,7 @@ public:
     inline double get_col_step() const { return col_step; }
     inline double get_row_step() const { return row_step; }
 
+    inline fitnode_list get_corner_node_list() const { return corner_list; }
     inline fitnode_list get_fit_node_list() const { return node_list; }
 };
 
@@ -134,6 +125,10 @@ public:
 
 
 // $Log$
+// Revision 1.4  1999/03/27 05:20:14  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Fixed some "const" related warnings.
+//
 // Revision 1.3  1999/03/20 20:32:52  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.

From b77bfe20ac745e99333412458a74246d72921d7e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 05:20:53 +0000
Subject: [PATCH 257/283] Pass along default area explicitely to triangulator.

---
 Clipper/clipper.cxx | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index 2f9e4e3ca..a6d78fd3a 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -144,7 +144,7 @@ bool FGClipper::load_polys(const string& path) {
 // Do actually clipping work
 bool FGClipper::clip_all(const point2d& min, const point2d& max) {
     gpc_polygon accum, result_union, tmp;
-    gpc_polygon *result_diff;
+    gpc_polygon *result_diff, *remains;
     gpcpoly_iterator current, last;
 
     FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
@@ -234,22 +234,31 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
     // finally, what ever is left over goes to base terrain
 
     // clip to accum against original base tile
+    remains = new gpc_polygon;
+    remains->num_contours = 0;
+    remains->contour = NULL;
     gpc_polygon_clip(GPC_DIFF, &polys_in.safety_base, &accum, 
-		     &polys_clipped.safety_base);
+		     remains);
+    if ( remains->num_contours > 0 ) {
+	polys_clipped.polys[0].push_back(remains);
+    }
 
     // tmp output accum
     FILE *ofp= fopen("accum", "w");
     gpc_write_polygon(ofp, &accum);
 
     // tmp output safety_base
-    ofp= fopen("safety_base", "w");
-    gpc_write_polygon(ofp, &polys_clipped.safety_base);
+    ofp= fopen("remains", "w");
+    gpc_write_polygon(ofp, remains);
 
     return true;
 }
 
 
 // $Log$
+// Revision 1.6  1999/03/27 05:20:53  curt
+// Pass along default area explicitely to triangulator.
+//
 // Revision 1.5  1999/03/19 22:28:46  curt
 // Only add non-null polygons to output list.
 //

From 903ac38cfff0cc948c077c6cc2aa3b1202de825e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 05:23:22 +0000
Subject: [PATCH 258/283] Interpolate real z value of all nodes from dem data.
 Write scenery file to correct location. Pass along correct triangle
 attributes and write to output file.

---
 GenOutput/genobj.cxx | 45 +++++++++++++++++++++++++++++++++++---------
 GenOutput/genobj.hxx | 18 +++++++++++++++---
 2 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index 72110fa72..b708f0ce5 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -25,27 +25,33 @@
 
 #include <time.h>
 
-#include <Tools/scenery_version.hxx>
 #include <Math/mat3.h>
+#include <Polygon/names.hxx>
+#include <Tools/scenery_version.hxx>
 
 #include "genobj.hxx"
 
 
 // build the wgs-84 point list
-void FGGenOutput::gen_wgs84_points() {
+void FGGenOutput::gen_wgs84_points( const FGArray& array ) {
     cout << "calculating wgs84 point" << endl;
     Point3D geod, radians, cart;
 
     const_point_list_iterator current = geod_nodes.begin();
     const_point_list_iterator last = geod_nodes.end();
 
+    double real_z;
+
     for ( ; current != last; ++current ) {
 	geod = *current;
 
+	real_z = array.interpolate_altitude( geod.x() * 3600.0, 
+					      geod.y() * 3600.0 );
+
 	// convert to radians
 	radians = Point3D( geod.x() * DEG_TO_RAD,
 			   geod.y() * DEG_TO_RAD,
-			   geod.z() );
+			   real_z );
 
         cart = fgGeodToCart(radians);
 	// cout << cart << endl;
@@ -183,7 +189,7 @@ void FGGenOutput::calc_gbs() {
 
 // build the necessary output structures based on the triangulation
 // data
-int FGGenOutput::build( const FGTriangle& t ) {
+int FGGenOutput::build( const FGArray& array, const FGTriangle& t ) {
     FGTriNodes trinodes = t.get_out_nodes();
 
     // copy the geodetic node list into this class
@@ -193,7 +199,7 @@ int FGGenOutput::build( const FGTriangle& t ) {
     tri_elements = t.get_elelist();
 
     // generate the point list in wgs-84 coordinates
-    gen_wgs84_points();
+    gen_wgs84_points( array );
 
     // calculate the global bounding sphere
     calc_gbs();
@@ -248,12 +254,19 @@ void FGGenOutput::calc_bounding_sphere( int i, Point3D *center,
 
 
 // write out the fgfs scenery file
-int FGGenOutput::write( const FGBucket& b, const string& path ) {
+int FGGenOutput::write( const string& base, const FGBucket& b ) {
     Point3D p;
 
+    string dir = base + "/Scenery/" + b.gen_base_path();
+    string command = "mkdir -p " + dir;
+    system(command.c_str());
+
+    string file = dir + "/" + b.gen_index_str();
+    cout << "Output file = " << file << endl;
+
     FILE *fp;
-    if ( (fp = fopen( path.c_str(), "w" )) == NULL ) {
-	cout << "ERROR: opening " << path << " for writing!" << endl;
+    if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
+	cout << "ERROR: opening " << file << " for writing!" << endl;
 	exit(-1);
     }
 
@@ -301,9 +314,13 @@ int FGGenOutput::write( const FGBucket& b, const string& path ) {
     const_triele_list_iterator t_current = tri_elements.begin();
     const_triele_list_iterator t_last = tri_elements.end();
     int counter = 0;
+    int attribute;
+    string attr_name;
     for ( ; t_current != t_last; ++t_current ) {
+	attribute = (int)t_current->get_attribute();
 	calc_bounding_sphere( counter, &center, &radius );
-	fprintf(fp, "# usemtl desert1\n");
+	attr_name = get_area_name( (AreaType)attribute );
+	fprintf(fp, "# usemtl %s\n", attr_name.c_str() );
 	fprintf(fp, "# bs %.2f %.2f %.2f %.2f\n", 
 		center.x(), center.y(), center.z(), radius);
 	fprintf(fp, "f %d %d %d\n", 
@@ -312,11 +329,21 @@ int FGGenOutput::write( const FGBucket& b, const string& path ) {
 	++counter;
     }
 
+    fclose(fp);
+
+    command = "gzip --force --best " + file;
+    system(command.c_str());
+
     return 1;
 }
 
 
 // $Log$
+// Revision 1.4  1999/03/27 05:23:22  curt
+// Interpolate real z value of all nodes from dem data.
+// Write scenery file to correct location.
+// Pass along correct triangle attributes and write to output file.
+//
 // Revision 1.3  1999/03/25 19:04:21  curt
 // Preparations for outputing scenery file to correct location.
 //
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index ed90deef9..5a5b12b68 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -32,11 +32,18 @@
 #endif                                   
 
 
+#include <Include/compiler.h>
+
+#include STL_STRING
+
 #include <Bucket/newbucket.hxx>
 #include <Math/fg_geodesy.hxx>
 #include <Math/point3d.hxx>
 #include <Triangulate/triangle.hxx>
 
+FG_USING_STD(string);
+FG_USING_STD(vector);
+
 
 typedef vector < int > belongs_to;
 typedef belongs_to::iterator belongs_to_iterator;
@@ -75,7 +82,7 @@ private:
     double gbs_radius;
 
     // build the wgs-84 point list
-    void gen_wgs84_points();
+    void gen_wgs84_points( const FGArray& array );
 
     // build the node -> element (triangle) reverse lookup table.
     // there is an entry for each point containing a list of all the
@@ -106,10 +113,10 @@ public:
 
     // build the necessary output structures based on the
     // triangulation data
-    int build( const FGTriangle& t );
+    int build( const FGArray& array, const FGTriangle& t );
 
     // write out the fgfs scenery file
-    int write( const FGBucket& b, const string& path );
+    int write( const string& base, const FGBucket& b );
 };
 
 
@@ -117,6 +124,11 @@ public:
 
 
 // $Log$
+// Revision 1.5  1999/03/27 05:23:23  curt
+// Interpolate real z value of all nodes from dem data.
+// Write scenery file to correct location.
+// Pass along correct triangle attributes and write to output file.
+//
 // Revision 1.4  1999/03/25 19:04:22  curt
 // Preparations for outputing scenery file to correct location.
 //

From 444abe17bec36c808e01d049d176eb7fbfe240df Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 05:25:02 +0000
Subject: [PATCH 259/283] Fit with a value of 200 rather than 100. Handle
 corner nodes separately from the rest of the fitted nodes. Write scenery file
 to correct location. First hack at generating scenery for multiple tiles in
 one invocation.

---
 Main/construct.cxx | 96 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 72 insertions(+), 24 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index 7b7935fca..fb0d76f0f 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -27,6 +27,7 @@
 
 #include <Bucket/newbucket.hxx>
 
+#include <Debug/logstream.hxx>
 #include <Array/array.hxx>
 #include <Clipper/clipper.hxx>
 #include <GenOutput/genobj.hxx>
@@ -49,7 +50,7 @@ int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
     }
 
     array.parse();
-    array.fit( 100 );
+    array.fit( 200 );
 
     return 1;
 }
@@ -137,11 +138,12 @@ void do_triangulate( const FGArray& array, const FGClipper& clipper,
     // first we need to consolidate the points of the DEM fit list and
     // all the polygons into a more "Triangle" friendly format
 
+    fitnode_list corner_list = array.get_corner_node_list();
     fitnode_list fit_list = array.get_fit_node_list();
     FGgpcPolyList gpc_polys = clipper.get_polys_clipped();
 
     cout << "ready to build node list and polygons" << endl;
-    t.build( fit_list, gpc_polys );
+    t.build( corner_list, fit_list, gpc_polys );
     cout << "done building node list and polygons" << endl;
 
     cout << "ready to do triangulation" << endl;
@@ -151,30 +153,17 @@ void do_triangulate( const FGArray& array, const FGClipper& clipper,
 
 
 // generate the flight gear scenery file
-void do_output( const FGBucket &b, const FGTriangle& t, FGGenOutput& output ) {
-    output.build( t );
-    output.write( b, "output" );
+void do_output( const string& base, const FGBucket &b, const FGTriangle& t, 
+		const FGArray& array, FGGenOutput& output ) {
+    output.build( array, t );
+    output.write( base, b );
 }
 
 
-main(int argc, char **argv) {
-    fitnode_list fit_list;
-    double lon, lat;
-
-    if ( argc != 2 ) {
-	cout << "Usage: " << argv[0] << " work_base" << endl;
-	exit(-1);
-    }
-
-    string work_base = argv[1];
-   
-    // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
-    // lon = -110.664244; lat = 33.352890;     // P13
-    // lon = -93.211389; lat = 45.145000;      // KANE
-    // lon = -92.486188; lat = 44.590190;      // KRGK
-    lon = -89.744682312011719; lat= 29.314495086669922;
-
-    FGBucket b( lon, lat );
+void construct_tile( const string& work_base, const string& output_base,
+		     FGBucket& b )
+{
+    cout << "Construct tile, bucket = " << b << endl;
 
     // load and fit grid of elevation data
     FGArray array;
@@ -190,11 +179,70 @@ main(int argc, char **argv) {
 
     // generate the output
     FGGenOutput output;
-    do_output( b, t, output );
+    do_output( output_base, b, t, array, output );
+}
+
+
+main(int argc, char **argv) {
+    fitnode_list fit_list;
+    double lon, lat;
+
+    fglog().setLogLevels( FG_ALL, FG_DEBUG );
+
+    if ( argc != 3 ) {
+	cout << "Usage: " << argv[0] << " <work_base> <output_base>" << endl;
+	exit(-1);
+    }
+
+    string work_base = argv[1];
+    string output_base = argv[2];
+   
+    // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
+    // lon = -110.664244; lat = 33.352890;     // P13
+    // lon = -93.211389; lat = 45.145000;      // KANE
+    // lon = -92.486188; lat = 44.590190;      // KRGK
+    // lon = -89.744682312011719; lat= 29.314495086669922;
+    // lon = -122.488090; lat = 42.743183;     // 64S
+    // lon = -114.861097; lat = 35.947480;     // 61B
+    lon = -112.012175; lat = 41.195944;      // KOGD
+
+    double min_x = lon - 1;
+    double min_y = lat - 1;
+    FGBucket b_min( min_x, min_y );
+    FGBucket b_max( lon + 1, lat + 1 );
+
+    // FGBucket b(550363L);
+    // construct_tile( work_base, output_base, b );
+    // exit(0);
+
+    if ( b_min == b_max ) {
+	construct_tile( work_base, output_base, b_min );
+    } else {
+	FGBucket b_cur;
+	int dx, dy, i, j;
+	    
+	fgBucketDiff(b_min, b_max, &dx, &dy);
+	cout << "  construction area spans tile boundaries" << endl;
+	cout << "  dx = " << dx << "  dy = " << dy << endl;
+
+	for ( j = 0; j <= dy; j++ ) {
+	    for ( i = 0; i <= dx; i++ ) {
+		b_cur = fgBucketOffset(min_x, min_y, i, j);
+		construct_tile( work_base, output_base, b_cur );
+	    }
+	}
+	// string answer; cin >> answer;
+    }
 }
 
 
 // $Log$
+// Revision 1.10  1999/03/27 05:25:02  curt
+// Fit with a value of 200 rather than 100.
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Write scenery file to correct location.
+// First hack at generating scenery for multiple tiles in one invocation.
+//
 // Revision 1.9  1999/03/25 19:04:31  curt
 // Preparations for outputing scenery file to correct location.
 // Minor tweaks related to FGBucket usage.

From 09aa6ba330e44a81a00462a4a1ff9cad69e82bb8 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 05:30:12 +0000
Subject: [PATCH 260/283] Handle corner nodes separately from the rest of the
 fitted nodes. Add fitted nodes in after corners and polygon nodes since the
 fitted nodes   are less important.  Subsequent nodes will "snap" to previous
 nodes if   they are "close enough." Need to manually divide segments to
 prevent "T" intersetions which can   confound the triangulator.  Hey, I got
 to use a recursive method! Pass along correct triangle attributes to output
 file generator. Do fine grained node snapping for corners and polygons, but
 course grain   node snapping for fitted terrain nodes.

---
 Triangulate/triangle.cxx |  64 ++++++++++++++++----
 Triangulate/triangle.hxx |  15 ++++-
 Triangulate/trieles.hxx  |  20 ++++++-
 Triangulate/trinodes.cxx |  51 ++++++++++++----
 Triangulate/trinodes.hxx |  47 +++++++++++++++
 Triangulate/trisegs.cxx  | 126 +++++++++++++++++++++++++++++++++++++--
 Triangulate/trisegs.hxx  |  33 +++++++++-
 7 files changed, 322 insertions(+), 34 deletions(-)

diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index b1beaa79f..5aa396721 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -37,7 +37,8 @@ FGTriangle::~FGTriangle( void ) {
 
 // populate this class based on the specified gpc_polys list
 int 
-FGTriangle::build( const fitnode_list& fit_list, 
+FGTriangle::build( const fitnode_list& corner_list,
+		   const fitnode_list& fit_list, 
 		   const FGgpcPolyList& gpc_polys )
 {
     FGTriPoly poly;
@@ -48,18 +49,20 @@ FGTriangle::build( const fitnode_list& fit_list,
     // char junkn[256];
     // FILE *junkfp;
 
-    // traverse the dem fit list and gpc_polys building a unified node
-    // list and converting the polygons so that they reference the
-    // node list by index (starting at zero) rather than listing the
-    // points explicitely
+    // traverse the dem corner and fit lists and gpc_polys building a
+    // unified node list and converting the polygons so that they
+    // reference the node list by index (starting at zero) rather than
+    // listing the points explicitely
 
+    // first the corners since these are important
     const_fitnode_list_iterator f_current, f_last;
-    f_current = fit_list.begin();
-    f_last = fit_list.end();
+    f_current = corner_list.begin();
+    f_last = corner_list.end();
     for ( ; f_current != f_last; ++f_current ) {
 	index = in_nodes.unique_add( *f_current );
     }
 
+    // next process the polygons
     gpc_polygon *gpc_poly;
     const_gpcpoly_iterator current, last;
 
@@ -87,6 +90,8 @@ FGTriangle::build( const fitnode_list& fit_list,
 	    }
 
 	    for ( int j = 0; j < gpc_poly->num_contours; j++ ) {
+		cout << " processing contour, nodes = " 
+		     << gpc_poly->contour[j].num_vertices << endl;
 
 		poly.erase();
 
@@ -115,6 +120,13 @@ FGTriangle::build( const fitnode_list& fit_list,
 	}
     }
 
+    // last, do the rest of the height nodes
+    f_current = fit_list.begin();
+    f_last = fit_list.end();
+    for ( ; f_current != f_last; ++f_current ) {
+	index = in_nodes.course_add( *f_current );
+    }
+
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
 	if ( polylist[i].size() ) {
 	    cout << get_area_name((AreaType)i) << " = " 
@@ -126,6 +138,7 @@ FGTriangle::build( const fitnode_list& fit_list,
     // that is used by the "Triangle" lib.
 
     int i1, i2;
+    point_list node_list = in_nodes.get_node_list();
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
 	cout << "area type = " << i << endl;
 	tripoly_list_iterator tp_current, tp_last;
@@ -139,11 +152,13 @@ FGTriangle::build( const fitnode_list& fit_list,
 	    for ( int j = 0; j < (int)(poly.size()) - 1; ++j ) {
 		i1 = poly.get_pt_index( j );
 		i2 = poly.get_pt_index( j + 1 );
-		trisegs.unique_add( FGTriSeg(i1, i2) );
+		// calc_line_params(i1, i2, &m, &b);
+		trisegs.unique_divide_and_add( node_list, FGTriSeg(i1, i2) );
 	    }
 	    i1 = poly.get_pt_index( 0 );
 	    i2 = poly.get_pt_index( poly.size() - 1 );
-	    trisegs.unique_add( FGTriSeg(i1, i2) );
+	    // calc_line_params(i1, i2, &m, &b);
+	    trisegs.unique_divide_and_add( node_list, FGTriSeg(i1, i2) );
 	}
     }
 
@@ -197,6 +212,7 @@ static void write_out_data(struct triangulateio *out) {
 		i, out->regionlist[4*i], out->regionlist[4*i + 1],
 		out->regionlist[4*i + 2]);
     }
+    fclose(fp);
 }
 
 
@@ -312,17 +328,22 @@ int FGTriangle::run_triangulate() {
     vorout.normlist = (REAL *) NULL;      // Needed only if -v switch used.
     
     // TEMPORARY
-    // write_out_data(&in);
+    write_out_data(&in);
 
     // 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), and a triangle neighbor list (n).
 
-    triangulate("pczq15Aen", &in, &out, &vorout);
+    string tri_options = "pczq10Aen";
+    // string tri_options = "pzAen";
+    // string tri_options = "pczq15S400Aen";
+    cout << "Triangulation with options = " << tri_options << endl;
+
+    triangulate(tri_options.c_str(), &in, &out, &vorout);
 
     // TEMPORARY
-    write_out_data(&out);
+    // write_out_data(&out);
 
     // now copy the results back into the corresponding FGTriangle
     // structures
@@ -336,13 +357,19 @@ int FGTriangle::run_triangulate() {
 
     // triangles
     int n1, n2, n3;
+    double attribute;
     for ( int i = 0; i < out.numberoftriangles; i++ ) {
 	n1 = out.trianglelist[i * 3];
 	n2 = out.trianglelist[i * 3 + 1];
 	n3 = out.trianglelist[i * 3 + 2];
+	if ( out.numberoftriangleattributes > 0 ) {
+	    attribute = out.triangleattributelist[i];
+	} else {
+	    attribute = 0.0;
+	}
 	// cout << "triangle = " << n1 << " " << n2 << " " << n3 << endl;
 
-	elelist.push_back( FGTriEle( n1, n2, n3 ) );
+	elelist.push_back( FGTriEle( n1, n2, n3, attribute ) );
     }
 
     // free mem allocated to the "Triangle" structures
@@ -371,6 +398,17 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.12  1999/03/27 05:30:12  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.11  1999/03/23 22:02:51  curt
 // Refinements in naming and organization.
 //
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index ba4fb4cbf..8106c3ab3 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -76,7 +76,9 @@ public:
     int add_nodes();
 
     // populate this class based on the specified gpc_polys list
-    int build( const fitnode_list& fit_list, const FGgpcPolyList& gpc_polys );
+    int build( const fitnode_list& corner_list, 
+	       const fitnode_list& fit_list,
+	       const FGgpcPolyList& gpc_polys );
 
     // front end triangulator for polygon list
     int run_triangulate();
@@ -90,6 +92,17 @@ public:
 
 
 // $Log$
+// Revision 1.9  1999/03/27 05:30:13  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.8  1999/03/23 22:02:52  curt
 // Refinements in naming and organization.
 //
diff --git a/Triangulate/trieles.hxx b/Triangulate/trieles.hxx
index 8a867fc0e..2d22c7db5 100644
--- a/Triangulate/trieles.hxx
+++ b/Triangulate/trieles.hxx
@@ -42,11 +42,15 @@ FG_USING_STD(vector);
 class FGTriEle {
     int n1, n2, n3;
 
+    double attribute;
+
 public:
 
     // Constructor and destructor
     inline FGTriEle( void ) { };
-    inline FGTriEle( int i1, int i2, int i3 ) { n1 = i1; n2 = i2; n3 = i3; }
+    inline FGTriEle( int i1, int i2, int i3, double a ) {
+	n1 = i1; n2 = i2; n3 = i3; attribute = a;
+    }
 
     inline ~FGTriEle( void ) { };
 
@@ -56,6 +60,9 @@ public:
     inline void set_n2( int i ) { n2 = i; }
     inline int get_n3() const { return n3; }
     inline void set_n3( int i ) { n3 = i; }
+
+    inline double get_attribute() const { return attribute; }
+    inline void set_attribute( double a ) { attribute = a; }
 };
 
 
@@ -68,6 +75,17 @@ typedef triele_list::const_iterator const_triele_list_iterator;
 
 
 // $Log$
+// Revision 1.3  1999/03/27 05:30:14  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.2  1999/03/23 22:02:53  curt
 // Refinements in naming and organization.
 //
diff --git a/Triangulate/trinodes.cxx b/Triangulate/trinodes.cxx
index 75b5b302d..50e7df7ee 100644
--- a/Triangulate/trinodes.cxx
+++ b/Triangulate/trinodes.cxx
@@ -35,18 +35,6 @@ FGTriNodes::~FGTriNodes( void ) {
 }
 
 
-// return true of the two points are "close enough" as defined by
-// FG_PROXIMITY_EPSILON
-inline bool FGTriNodes::close_enough( const Point3D& p1, const Point3D& p2 ) {
-    if ( ( fabs(p1.x() - p2.x()) < FG_PROXIMITY_EPSILON ) &&
-	 ( fabs(p1.y() - p2.y()) < FG_PROXIMITY_EPSILON ) ) {
-	return true;
-    } else {
-	return false;
-    }
-}
-
-
 // Add a point to the point list if it doesn't already exist.  Returns
 // the index (starting at zero) of the point in the list.
 int FGTriNodes::unique_add( const Point3D& p ) {
@@ -82,7 +70,46 @@ int FGTriNodes::simple_add( const Point3D& p ) {
 }
 
 
+// Add a point to the point list if it doesn't already exist.  Returns
+// the index (starting at zero) of the point in the list.  Use a
+// course proximity check
+int FGTriNodes::course_add( const Point3D& p ) {
+    point_list_iterator current, last;
+    int counter = 0;
+
+    // cout << p.x() << "," << p.y() << endl;
+
+    // see if point already exists
+    current = node_list.begin();
+    last = node_list.end();
+    for ( ; current != last; ++current ) {
+	if ( course_close_enough(p, *current) ) {
+	    // cout << "found an existing match!" << endl;
+	    return counter;
+	}
+	
+	++counter;
+    }
+
+    // add to list
+    node_list.push_back( p );
+
+    return counter;
+}
+
+
 // $Log$
+// Revision 1.6  1999/03/27 05:30:15  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.5  1999/03/23 22:02:54  curt
 // Refinements in naming and organization.
 //
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
index ab1b36504..860b63034 100644
--- a/Triangulate/trinodes.hxx
+++ b/Triangulate/trinodes.hxx
@@ -41,6 +41,7 @@ FG_USING_STD(vector);
 
 
 #define FG_PROXIMITY_EPSILON 0.000001
+#define FG_COURSE_EPSILON 0.0003
 
 
 typedef vector < Point3D > point_list;
@@ -58,6 +59,10 @@ private:
     // FG_PROXIMITY_EPSILON
     bool close_enough( const Point3D& p, const Point3D& p );
 
+    // return true of the two points are "close enough" as defined by
+    // FG_COURSE_EPSILON
+    bool course_close_enough( const Point3D& p1, const Point3D& p2 );
+
 public:
 
     // Constructor and destructor
@@ -71,6 +76,11 @@ public:
     // Add the point with no uniqueness checking
     int simple_add( const Point3D& p );
 
+    // Add a point to the point list if it doesn't already exist.
+    // Returns the index (starting at zero) of the point in the list.
+    // Use a course proximity check
+    int course_add( const Point3D& p );
+
     // return the master node list
     inline point_list get_node_list() const { return node_list; }
 
@@ -79,10 +89,47 @@ public:
 };
 
 
+// return true of the two points are "close enough" as defined by
+// FG_PROXIMITY_EPSILON
+inline bool FGTriNodes::close_enough( const Point3D& p1, const Point3D& p2 ) {
+    if ( ( fabs(p1.x() - p2.x()) < FG_PROXIMITY_EPSILON ) &&
+	 ( fabs(p1.y() - p2.y()) < FG_PROXIMITY_EPSILON ) ) {
+	return true;
+    } else {
+	return false;
+    }
+}
+
+
+// return true of the two points are "close enough" as defined by
+// FG_COURSE_EPSILON
+inline bool FGTriNodes::course_close_enough( const Point3D& p1, 
+					     const Point3D& p2 )
+{
+    if ( ( fabs(p1.x() - p2.x()) < FG_COURSE_EPSILON ) &&
+	 ( fabs(p1.y() - p2.y()) < FG_COURSE_EPSILON ) ) {
+	return true;
+    } else {
+	return false;
+    }
+}
+
+
 #endif // _TRINODES_HXX
 
 
 // $Log$
+// Revision 1.6  1999/03/27 05:30:16  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.5  1999/03/23 22:02:55  curt
 // Refinements in naming and organization.
 //
diff --git a/Triangulate/trisegs.cxx b/Triangulate/trisegs.cxx
index 6d4ac1bb5..62cf4d03a 100644
--- a/Triangulate/trisegs.cxx
+++ b/Triangulate/trisegs.cxx
@@ -22,6 +22,10 @@
 // (Log is kept at end of this file)
 
 
+#include <Include/fg_constants.h>
+#include <Math/point3d.hxx>
+
+#include "trinodes.hxx"
 #include "trisegs.hxx"
 
 
@@ -35,15 +39,16 @@ FGTriSegments::~FGTriSegments( void ) {
 }
 
 
-// Add a point to the point list if it doesn't already exist.
-// Returns the index (starting at zero) of the point in the list.
-int FGTriSegments::unique_add( const FGTriSeg& s ) {
+// Add a segment to the segment list if it doesn't already exist.
+// Returns the index (starting at zero) of the segment in the list.
+int FGTriSegments::unique_add( const FGTriSeg& s )
+{
     triseg_list_iterator current, last;
     int counter = 0;
 
     // cout << s.get_n1() << "," << s.get_n2() << endl;
 
-    // see if point already exists
+    // check if segment already exists
     current = seg_list.begin();
     last = seg_list.end();
     for ( ; current != last; ++current ) {
@@ -62,7 +67,120 @@ int FGTriSegments::unique_add( const FGTriSeg& s ) {
 }
 
 
+// Divide segment if there are other points on it, return the divided
+// list of segments
+void FGTriSegments::unique_divide_and_add( const point_list& nodes, 
+					   const FGTriSeg& s )
+{
+    Point3D p0 = nodes[ s.get_n1() ];
+    Point3D p1 = nodes[ s.get_n2() ];
+
+    bool found_extra = false;
+    int extra_index;
+    int counter;
+    double m, b, y_err, x_err;
+    const_point_list_iterator current, last;
+
+    // bool temp = false;
+    // if ( s == FGTriSeg( 170, 206 ) ) {
+    //   cout << "this is it!" << endl;
+    //   temp = true;
+    // }
+
+    if ( fabs(p0.x() - p1.x()) > FG_EPSILON ) {
+	// use y = mx + b
+
+	// sort these in a sensable order
+	if ( p0.x() > p1.x() ) {
+	    Point3D tmp = p0;
+	    p0 = p1;
+	    p1 = tmp;
+	}
+
+	m = (p0.y() - p1.y()) / (p0.x() - p1.x());
+	b = p1.y() - m * p1.x();
+
+	// if ( temp ) {
+	//   cout << "m = " << m << " b = " << b << endl;
+	// }
+
+	current = nodes.begin();
+	last = nodes.end();
+	counter = 0;
+	for ( ; current != last; ++current ) {
+	    if ( (current->x() > (p0.x() + FG_EPSILON)) 
+		 && (current->x() < (p1.x() - FG_EPSILON)) ) {
+
+		// if ( temp ) {
+		//   cout << counter << endl;
+		// }
+
+		y_err = fabs(current->y() - (m * current->x() + b));
+
+		if ( y_err < 10 * FG_EPSILON ) {
+		    cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
+		    cout << p0 << " < " << *current << " < "
+			 << p1 << endl;
+		    found_extra = true;
+		    extra_index = counter;
+		    break;
+		}
+	    }
+	    ++counter;
+	}
+    } else {
+	// use x = constant
+
+	// sort these in a sensable order
+	if ( p0.y() > p1.y() ) {
+	    Point3D tmp = p0;
+	    p0 = p1;
+	    p1 = tmp;
+	}
+
+	current = nodes.begin();
+	last = nodes.end();
+	counter = 0;
+	for ( ; current != last; ++current ) {
+	    // cout << counter << endl;
+	    if ( (current->y() > p0.y()) && (current->y() < p1.y()) ) {
+		x_err = fabs(current->x() - p0.x());
+		if ( x_err < 10*FG_EPSILON ) {
+		    cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
+		    found_extra = true;
+		    extra_index = counter;
+		    break;
+		}
+	    }
+	    ++counter;
+	}
+    }
+
+    if ( found_extra ) {
+	// recurse with two sub segments
+	cout << "dividing " << s.get_n1() << " " << extra_index 
+	     << " " << s.get_n2() << endl;
+	unique_divide_and_add( nodes, FGTriSeg( s.get_n1(), extra_index ) );
+	unique_divide_and_add( nodes, FGTriSeg( extra_index, s.get_n2() ) );
+    } else {
+	// this segment does not need to be divided, lets add it
+	unique_add( s );
+    }
+}
+
+
 // $Log$
+// Revision 1.4  1999/03/27 05:30:17  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.3  1999/03/23 22:02:57  curt
 // Refinements in naming and organization.
 //
diff --git a/Triangulate/trisegs.hxx b/Triangulate/trisegs.hxx
index 31189d591..09fd5b921 100644
--- a/Triangulate/trisegs.hxx
+++ b/Triangulate/trisegs.hxx
@@ -35,6 +35,8 @@
 
 #include <vector>
 
+#include "trinodes.hxx"
+
 FG_USING_STD(vector);
 
 
@@ -46,7 +48,10 @@ public:
 
     // Constructor and destructor
     inline FGTriSeg( void ) { };
-    inline FGTriSeg( int i1, int i2 ) { n1 = i1; n2 = i2; }
+    inline FGTriSeg( int i1, int i2 ) { 
+	n1 = i1;
+	n2 = i2;
+    }
 
     inline ~FGTriSeg( void ) { };
 
@@ -77,16 +82,27 @@ private:
 
     triseg_list seg_list;
 
+    // Divide segment if there are other points on it, return the
+    // divided list of segments
+    triseg_list divide_segment( const point_list& nodes, 
+				const FGTriSeg& s );
+
 public:
 
     // Constructor and destructor
     FGTriSegments( void );
     ~FGTriSegments( void );
 
-    // Add a point to the point list if it doesn't already exist.
-    // Returns the index (starting at zero) of the point in the list.
+    // Add a segment to the segment list if it doesn't already exist.
+    // Returns the index (starting at zero) of the segment in the
+    // list.
     int unique_add( const FGTriSeg& s );
 
+    // Add a segment to the segment list if it doesn't already exist.
+    // Returns the index (starting at zero) of the segment in the list.
+    void unique_divide_and_add( const point_list& node_list, 
+				const FGTriSeg& s );
+
     // return the master node list
     inline triseg_list get_seg_list() const { return seg_list; }
 
@@ -99,6 +115,17 @@ public:
 
 
 // $Log$
+// Revision 1.3  1999/03/27 05:30:18  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.2  1999/03/20 20:33:00  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.

From 0f6ec612cfe3cc787576f913690f239b0cb88f8d Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 05:31:24 +0000
Subject: [PATCH 261/283] Make 0 the default area type since this corresponds
 well with the conventions   used by the triangulator.

---
 Polygon/names.cxx | 15 ++++++++++++---
 Polygon/names.hxx | 36 ++++++++++++++++++++++++------------
 2 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/Polygon/names.cxx b/Polygon/names.cxx
index eabd8697e..d3d190612 100644
--- a/Polygon/names.cxx
+++ b/Polygon/names.cxx
@@ -30,7 +30,9 @@
 
 // return area type from text name
 AreaType get_area_type( string area ) {
-    if ( area == "AirportKeep" ) {
+    if ( area == "Default" ) {
+	return DefaultArea;
+    } else if ( area == "AirportKeep" ) {
 	return AirportKeepArea;
     } else if ( area == "AirportIgnore" ) {
 	return AirportIgnoreArea;
@@ -42,7 +44,8 @@ AreaType get_area_type( string area ) {
 	return OceanArea;
     } else if ( area == "Lake" ) {
 	return LakeArea;
-    } else if ( area == "Lake   Dry" ) {
+    } else if ( (area == "Lake   Dry")
+		|| (area == "DryLake") ) {
 	return DryLakeArea;
     } else if ( (area == "Lake   Intermittent")
 		|| (area == "IntermittentLake") ) {
@@ -74,7 +77,9 @@ AreaType get_area_type( string area ) {
 
 // return text from of area name
 string get_area_name( AreaType area ) {
-    if ( area == AirportKeepArea ) {
+    if ( area == DefaultArea ) {
+	return "Default";
+    } else if ( area == AirportKeepArea ) {
 	return "AirportKeep";
     } else if ( area == AirportIgnoreArea ) {
 	return "AirportIgnore";
@@ -110,6 +115,10 @@ string get_area_name( AreaType area ) {
 
 
 // $Log$
+// Revision 1.6  1999/03/27 05:31:24  curt
+// Make 0 the default area type since this corresponds well with the conventions
+//   used by the triangulator.
+//
 // Revision 1.5  1999/03/22 23:49:29  curt
 // Moved AreaType get_shapefile_type(GDBFile *dbf, int rec) to where it
 // belongs in ShapeFile/
diff --git a/Polygon/names.hxx b/Polygon/names.hxx
index 78c85d339..0a919a5ed 100644
--- a/Polygon/names.hxx
+++ b/Polygon/names.hxx
@@ -26,22 +26,30 @@
 #define _NAMES_HXX
 
 
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+FG_USING_STD(string);
+
+
 // Posible shape file types.  Note the order of these is important and
 // defines the priority of these shapes if they should intersect.  The
 // smaller the number, the higher the priority.
 enum AreaType {
-    AirportKeepArea   = 0,
-    AirportIgnoreArea = 1,
-    OceanArea         = 2,
-    LakeArea          = 3,
-    DryLakeArea       = 4,
-    IntLakeArea       = 5,
-    ReservoirArea     = 6,
-    IntReservoirArea  = 7,
-    StreamArea        = 8,
-    CanalArea         = 9,
-    GlacierArea       = 10,
-    MarshArea         = 11,
+    DefaultArea       = 0,
+    AirportKeepArea   = 1,
+    AirportIgnoreArea = 2,
+    OceanArea         = 3,
+    LakeArea          = 4,
+    DryLakeArea       = 5,
+    IntLakeArea       = 6,
+    ReservoirArea     = 7,
+    IntReservoirArea  = 8,
+    StreamArea        = 9,
+    CanalArea         = 10,
+    GlacierArea       = 11,
+    MarshArea         = 12,
     VoidArea          = 9997,
     NullArea          = 9998,
     UnknownArea       = 9999
@@ -59,6 +67,10 @@ string get_area_name( AreaType area );
 
 
 // $Log$
+// Revision 1.5  1999/03/27 05:31:25  curt
+// Make 0 the default area type since this corresponds well with the conventions
+//   used by the triangulator.
+//
 // Revision 1.4  1999/03/22 23:49:30  curt
 // Moved AreaType get_shapefile_type(GDBFile *dbf, int rec) to where it
 // belongs in ShapeFile/

From 0530d520f06e784c6f0bc99ebc3ae4f9c8ee336e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 05:33:02 +0000
Subject: [PATCH 262/283] Increased precision in showme when clicking with the
 middle mouse button   to display coordinates. Build showme. Removed -DREDUCED
 from compile flags

---
 Triangle/Makefile.am | 7 ++++---
 Triangle/showme.c    | 2 +-
 Triangle/triangle.c  | 9 +++++++++
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/Triangle/Makefile.am b/Triangle/Makefile.am
index f07cb8e4e..17f6825cd 100644
--- a/Triangle/Makefile.am
+++ b/Triangle/Makefile.am
@@ -9,11 +9,12 @@
 #
 #   DEFS = -DTRILIBRARY -DREDUCED -DCDT_ONLY
 
-DEFS += -DTRILIBRARY -DREDUCED
+DEFS += -DTRILIBRARY
 
 noinst_LIBRARIES = libTriangle.a
 
 libTriangle_a_SOURCES = triangle.c triangle.h
 
-# bin_PROGRAMS = showme
-# showme_SOURCES = showme.c
+bin_PROGRAMS = showme
+showme_SOURCES = showme.c
+showme_LDADD = -lX11
diff --git a/Triangle/showme.c b/Triangle/showme.c
index 6c4f0a95d..722cba8ac 100644
--- a/Triangle/showme.c
+++ b/Triangle/showme.c
@@ -3355,7 +3355,7 @@ char **argv;
             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);
+            printf("x = %.9f, y = %.9f\n", xptr, yptr);
           }
         }
         break;
diff --git a/Triangle/triangle.c b/Triangle/triangle.c
index 67bd00ddb..9af47a493 100644
--- a/Triangle/triangle.c
+++ b/Triangle/triangle.c
@@ -5513,6 +5513,15 @@ struct triedge *testtri;
   if (vararea || fixedarea) {
     /* Check whether the area is larger than permitted. */
     area = 0.5 * (dxod * dyda - dyod * dxda);
+
+#if 0
+    if ( area < 1.0 / (2.0 * 3600.0 * 3600.0) ) {
+      /* FGFS ADDITION!!! */
+      /* small enough, don't add to list of bad triangles */
+      printf("REJECTING TRIANGLE OF AREA %.6g\n", area);
+    }
+#endif
+
     if (fixedarea && (area > maxarea)) {
       /* Add this triangle to the list of bad triangles. */
       enqueuebadtri(testtri, angle, tapex, torg, tdest);

From c6f97e5413c373a32302463e90f19327e094c586 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 14:05:10 +0000
Subject: [PATCH 263/283] More sensible handling of the case where no dem file
 for this tile exists (or has been generated).

---
 Array/array.cxx | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Array/array.cxx b/Array/array.cxx
index d7b38c22e..af1e32f7d 100644
--- a/Array/array.cxx
+++ b/Array/array.cxx
@@ -85,7 +85,7 @@ FGArray::open( const string& file ) {
 	return 0;
     } else {
 	in = new fg_gzifstream( file );
-	if ( !(*in) ) {
+	if ( ! in->is_open() ) {
 	    cout << "  Cannot open " << file << endl;
 	    return 0;
 	}
@@ -341,7 +341,7 @@ double FGArray::interpolate_altitude( double lon, double lat ) const {
 	 (yindex < 0) || (yindex + 1 >= rows) ) {
 	cout << "WARNING: Attempt to interpolate value outside of array!!!" 
 	     << endl;
-	return(-9999);
+	return 0;
     }
 
     dx = xlocal - xindex;
@@ -539,6 +539,10 @@ FGArray::~FGArray( void ) {
 
 
 // $Log$
+// Revision 1.7  1999/03/27 14:05:10  curt
+// More sensible handling of the case where no dem file for this tile exists
+// (or has been generated).
+//
 // Revision 1.6  1999/03/27 05:20:13  curt
 // Handle corner nodes separately from the rest of the fitted nodes.
 // Fixed some "const" related warnings.

From 7307279d5b8530e62a7006f5b2c64c1a1ead68da Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 27 Mar 1999 14:06:42 +0000
Subject: [PATCH 264/283] Tweaks to bounding sphere calculation routines. Group
 like triangles together for output to be in a single display list, even
 though they are individual, non-fanified, triangles.

---
 GenOutput/genobj.cxx | 134 ++++++++++++++++++++++++++++++++-----------
 GenOutput/genobj.hxx |  12 +++-
 2 files changed, 111 insertions(+), 35 deletions(-)

diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index b708f0ce5..d45a649ba 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -153,27 +153,19 @@ void FGGenOutput::gen_normals() {
 // calculate the global bounding sphere.  Center is the average of the
 // points.
 void FGGenOutput::calc_gbs() {
-    double x = 0;
-    double y = 0;
-    double z = 0;
-
     double dist_squared;
     double radius_squared = 0;
     
+    gbs_center = Point3D( 0.0 );
+
     const_point_list_iterator current = wgs84_nodes.begin();
     const_point_list_iterator last = wgs84_nodes.end();
 
     for ( ; current != last; ++current ) {
-	x += current->x();
-	y += current->y();
-	z += current->z();
+	gbs_center += *current;
     }
 
-    x /= wgs84_nodes.size();
-    y /= wgs84_nodes.size();
-    z /= wgs84_nodes.size();
-
-    gbs_center = Point3D(x, y, z);
+    gbs_center /= wgs84_nodes.size();
 
     current =  wgs84_nodes.begin();
     for ( ; current != last; ++current ) {
@@ -218,14 +210,66 @@ int FGGenOutput::build( const FGArray& array, const FGTriangle& t ) {
 }
 
 
+// caclulate the bounding sphere for a list of triangle faces
+void FGGenOutput::calc_group_bounding_sphere( const triele_list& tris, 
+					      Point3D *center, double *radius )
+{
+    cout << "calculate group bounding sphere for " << tris.size() << " tris." 
+	 << endl;
+
+    // generate a list of unique points from the triangle list
+    FGTriNodes nodes;
+
+    const_triele_list_iterator t_current = tris.begin();
+    const_triele_list_iterator t_last = tris.end();
+    for ( ; t_current != t_last; ++t_current ) {
+	Point3D p1 = wgs84_nodes[ t_current->get_n1() ];
+	Point3D p2 = wgs84_nodes[ t_current->get_n2() ];
+	Point3D p3 = wgs84_nodes[ t_current->get_n3() ];
+
+	nodes.unique_add(p1);
+	nodes.unique_add(p2);
+	nodes.unique_add(p3);
+    }
+
+    // find average of point list
+    Point3D c( 0.0 );
+    point_list points = nodes.get_node_list();
+    cout << "found " << points.size() << " unique nodes" << endl;
+    point_list_iterator p_current = points.begin();
+    point_list_iterator p_last = points.end();
+    for ( ; p_current != p_last; ++p_current ) {
+	c += *p_current;
+    }
+    c /= points.size();
+
+    // find max radius
+    double dist_squared;
+    double max_squared = 0;
+
+    p_current = points.begin();
+    p_last = points.end();
+    for ( ; p_current != p_last; ++p_current ) {
+	dist_squared = c.distance3Dsquared(*p_current);
+	if ( dist_squared > max_squared ) {
+	    max_squared = dist_squared;
+	}
+    }
+
+    *center = c;
+    *radius = sqrt(max_squared);
+}
+
+
 // caclulate the bounding sphere for the specified triangle face
-void FGGenOutput::calc_bounding_sphere( int i, Point3D *center, 
-					double *radius ) {
+void FGGenOutput::calc_bounding_sphere( const FGTriEle& t, 
+					Point3D *center, double *radius )
+{
     Point3D c( 0.0 );
 
-    Point3D p1 = wgs84_nodes[ tri_elements[i].get_n1() ];
-    Point3D p2 = wgs84_nodes[ tri_elements[i].get_n2() ];
-    Point3D p3 = wgs84_nodes[ tri_elements[i].get_n3() ];
+    Point3D p1 = wgs84_nodes[ t.get_n1() ];
+    Point3D p2 = wgs84_nodes[ t.get_n2() ];
+    Point3D p3 = wgs84_nodes[ t.get_n3() ];
 
     c = p1 + p2 + p3;
     c /= 3;
@@ -306,27 +350,44 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
     }
     fprintf(fp, "\n");
 
-    // write triangles
+    // write triangles (grouped by type for now)
     Point3D center;
     double radius;
     fprintf(fp, "# triangle list\n");
     fprintf(fp, "\n");
-    const_triele_list_iterator t_current = tri_elements.begin();
-    const_triele_list_iterator t_last = tri_elements.end();
-    int counter = 0;
-    int attribute;
-    string attr_name;
-    for ( ; t_current != t_last; ++t_current ) {
-	attribute = (int)t_current->get_attribute();
-	calc_bounding_sphere( counter, &center, &radius );
-	attr_name = get_area_name( (AreaType)attribute );
-	fprintf(fp, "# usemtl %s\n", attr_name.c_str() );
-	fprintf(fp, "# bs %.2f %.2f %.2f %.2f\n", 
-		center.x(), center.y(), center.z(), radius);
-	fprintf(fp, "f %d %d %d\n", 
-		t_current->get_n1(), t_current->get_n2(), t_current->get_n3());
-	fprintf(fp, "\n");
-	++counter;
+
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	triele_list area_tris;
+	area_tris.erase( area_tris.begin(), area_tris.end() );
+
+	const_triele_list_iterator t_current = tri_elements.begin();
+	const_triele_list_iterator t_last = tri_elements.end();
+	for ( ; t_current != t_last; ++t_current ) {
+	    if ( (int)t_current->get_attribute() == i ) {
+		area_tris.push_back( *t_current );
+	    }
+	}
+
+	if ( (int)area_tris.size() > 0 ) {
+	    string attr_name = get_area_name( (AreaType)i );
+	    calc_group_bounding_sphere( area_tris, &center, &radius );
+	    cout << "writing " << (int)area_tris.size() << " faces for " 
+		 << attr_name << endl;
+
+	    fprintf(fp, "# usemtl %s\n", attr_name.c_str() );
+	    fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n", 
+		    center.x(), center.y(), center.z(), radius);
+
+	    triele_list_iterator a_current = area_tris.begin();
+	    triele_list_iterator a_last = area_tris.end();
+	    for ( ; a_current != a_last; ++a_current ) {
+		fprintf( fp, "f %d %d %d\n", 
+			 a_current->get_n1(), 
+			 a_current->get_n2(),
+			 a_current->get_n3() );
+	    }
+	    fprintf( fp, "\n" );
+	}
     }
 
     fclose(fp);
@@ -339,6 +400,11 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 
 
 // $Log$
+// Revision 1.5  1999/03/27 14:06:42  curt
+// Tweaks to bounding sphere calculation routines.
+// Group like triangles together for output to be in a single display list,
+// even though they are individual, non-fanified, triangles.
+//
 // Revision 1.4  1999/03/27 05:23:22  curt
 // Interpolate real z value of all nodes from dem data.
 // Write scenery file to correct location.
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index 5a5b12b68..2d89fbe66 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -102,8 +102,13 @@ private:
     // the points.
     void calc_gbs();
 
+    // caclulate the bounding sphere for a list of triangle faces
+    void calc_group_bounding_sphere( const triele_list& tris, 
+				     Point3D *center, double *radius );
+
     // caclulate the bounding sphere for the specified triangle face
-    void calc_bounding_sphere( int i, Point3D *center, double *radius );
+    void calc_bounding_sphere( const FGTriEle& t, 
+			       Point3D *center, double *radius );
 
 public:
 
@@ -124,6 +129,11 @@ public:
 
 
 // $Log$
+// Revision 1.6  1999/03/27 14:06:43  curt
+// Tweaks to bounding sphere calculation routines.
+// Group like triangles together for output to be in a single display list,
+// even though they are individual, non-fanified, triangles.
+//
 // Revision 1.5  1999/03/27 05:23:23  curt
 // Interpolate real z value of all nodes from dem data.
 // Write scenery file to correct location.

From d3b0d463d0282f8f0c67b994fc26dc40fa2371a6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 29 Mar 1999 13:08:35 +0000
Subject: [PATCH 265/283] Initial revision.

---
 Combine/Makefile.am |   9 ++
 Combine/genfans.cxx | 217 ++++++++++++++++++++++++++++++++++++++++++++
 Combine/genfans.hxx |  85 +++++++++++++++++
 3 files changed, 311 insertions(+)
 create mode 100644 Combine/Makefile.am
 create mode 100644 Combine/genfans.cxx
 create mode 100644 Combine/genfans.hxx

diff --git a/Combine/Makefile.am b/Combine/Makefile.am
new file mode 100644
index 000000000..ea8702955
--- /dev/null
+++ b/Combine/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libGenFans.a
+
+libGenFans_a_SOURCES = genfans.cxx genfans.hxx
+
+INCLUDES += \
+	-I$(top_builddir) \
+	-I$(top_builddir)/Lib \
+	-I$(top_builddir)/Tools/Lib \
+	-I$(top_builddir)/Tools/Construct
diff --git a/Combine/genfans.cxx b/Combine/genfans.cxx
new file mode 100644
index 000000000..fba5dfa68
--- /dev/null
+++ b/Combine/genfans.cxx
@@ -0,0 +1,217 @@
+// genfans.cxx -- Combine individual triangles into more optimal fans.
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#include "genfans.hxx"
+
+
+// make sure the list is expanded at least to hold "n" and then push
+// "i" onto the back of the "n" list.
+void FGGenFans::add_and_expand( reverse_list& by_node, int n, int i ) {
+    int_list empty;
+
+    int size = (int)by_node.size();
+    if ( size > n ) {
+	// ok
+    } else {
+	// cout << "capacity = " << by_node.capacity() << endl;
+	// cout << "size = " << size << "  n = " << n
+	//      << " need to push = " << n - size + 1 << endl;
+	for ( int i = 0; i < n - size + 1; ++i ) {
+	    by_node.push_back(empty);
+	}
+    }
+
+    by_node[n].push_back(i);
+}
+
+
+// given an input triangle, shuffle nodes so that "center" is the
+// first node, but maintain winding order.
+static FGTriEle canonify( const FGTriEle& t, int center ) {
+    if ( t.get_n1() == center ) {
+	// already ok
+	return t;
+    } else if ( t.get_n2() == center ) {
+	return FGTriEle( t.get_n2(), t.get_n3(), t.get_n1(), 0.0 );
+    } else if ( t.get_n3() == center ) {
+	return FGTriEle( t.get_n3(), t.get_n1(), t.get_n2(), 0.0 );
+    } else {
+	cout << "ERROR, index doesn't refer to this triangle!!!" << endl;
+	exit(-1);
+    }
+}
+
+static int_list make_best_fan( const triele_list& master_tris, 
+			       const int center, const int_list& local_tris )
+{
+    int_list best_result;
+
+    // try starting with local triangle to find the best fan arrangement
+    for ( int start = 0; start < (int)local_tris.size(); ++start ) {
+	cout << "trying with first triangle = " << local_tris[start] << endl;
+
+	int_list tmp_result;
+	tmp_result.clear();
+
+	FGTriEle current_tri;
+	FGTriEle test;
+	current_tri = canonify( master_tris[local_tris[start]], center );
+	tmp_result.push_back( local_tris[start] );
+
+	// follow the ring
+	int next = -1;
+	bool matches = true;
+	while ( (next != start) && matches ) {
+	    // find next triangle in ring
+	    matches = false;
+	    for ( int i = 0; i < (int)local_tris.size(); ++i ) {
+		test = canonify( master_tris[local_tris[i]], center );
+		if ( current_tri.get_n3() == test.get_n2() ) {
+		    if ( i != start ) {
+			cout << "  next triangle = " << local_tris[i] << endl;
+			current_tri = test;
+			tmp_result.push_back( local_tris[i] );
+			matches = true;
+			next = i;
+			break;
+		    }
+		}
+	    }
+	}
+
+	if ( tmp_result.size() == local_tris.size() ) {
+	    // we found a complete usage, no need to go on
+	    cout << "we found a complete usage, no need to go on" << endl;
+	    best_result = tmp_result;
+	    break;
+	} else if ( tmp_result.size() > best_result.size() ) {
+	    // we found a better way to fan
+	    cout << "we found a better fan arrangement" << endl;
+	    best_result = tmp_result;
+	}
+    }
+
+    return best_result;
+}
+
+
+static bool in_fan(int index, const int_list& fan ) {
+    const_int_list_iterator current = fan.begin();
+    const_int_list_iterator last = fan.end();
+
+    for ( ; current != last; ++current ) {
+	if ( index == *current ) {
+	    return true;
+	}
+    }
+
+    return false;
+}
+
+
+// recursive build fans from triangle list
+fan_list FGGenFans::greedy_build( triele_list tris ) {
+    cout << "starting greedy build of fans" << endl;
+
+    while ( ! tris.empty() ) {
+	reverse_list by_node;
+	by_node.clear();
+
+	// traverse the triangle list and for each node, build a list of
+	// triangles that attach to it.
+
+	for ( int i = 0; i < (int)tris.size(); ++i ) {
+	    int n1 = tris[i].get_n1();
+	    int n2 = tris[i].get_n2();
+	    int n3 = tris[i].get_n3();
+
+	    add_and_expand( by_node, n1, i );
+	    add_and_expand( by_node, n2, i );
+	    add_and_expand( by_node, n3, i );
+	}
+
+	// find the node in the tris list that attaches to the most
+	// triangles
+
+	int_list biggest_group;
+	reverse_list_iterator r_current = by_node.begin();
+	reverse_list_iterator r_last = by_node.end();
+	int index = 0;
+	int counter = 0;
+	for ( ; r_current != r_last; ++r_current ) {
+	    if ( r_current->size() > biggest_group.size() ) {
+		biggest_group = *r_current;
+		index = counter;
+	    }
+	    ++counter;
+	}
+	cout << "master triangle pool = " << tris.size() << endl;
+	cout << "biggest_group = " << biggest_group.size() << endl;
+	cout << "center node = " << index << endl;
+
+	// make the best fan we can out of this group
+	int_list best_fan = make_best_fan( tris, index, biggest_group );
+
+	// add this fan to the fan list
+	fans.push_back( best_fan );
+
+	// delete the triangles in best_fan out of tris and repeat
+	triele_list_iterator t_current = tris.begin();
+	triele_list_iterator t_last = tris.end();
+	counter = 0;
+	for ( ; t_current != t_last; ++t_current ) {
+	    if ( in_fan(counter, best_fan) ) {
+		// cout << "erasing " << counter << " from master tri pool" 
+		//      << endl;
+		tris.erase( t_current );
+	    }
+	    ++counter;
+	}
+    }
+
+    cout << "end of greedy build of fans" << endl;
+    cout << "average fan size = " << ave_size() << endl;
+
+    return fans;
+}
+
+
+// report average fan size
+double FGGenFans::ave_size() {
+    double sum;
+
+    fan_list_iterator current = fans.begin();
+    fan_list_iterator last = fans.end();
+    for ( ; current != last; ++current ) {
+	sum += current->size();
+    }
+
+    return sum / (double)fans.size();
+}
+
+
+// $Log$
+// Revision 1.1  1999/03/29 13:08:35  curt
+// Initial revision.
+//
diff --git a/Combine/genfans.hxx b/Combine/genfans.hxx
new file mode 100644
index 000000000..55af05d70
--- /dev/null
+++ b/Combine/genfans.hxx
@@ -0,0 +1,85 @@
+// genfans.hxx -- Combine individual triangles into more optimal fans.
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _GENFANS_HXX
+#define _GENFANS_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+#include <vector>
+
+#include <Main/construct_types.hxx>
+#include <Triangulate/trieles.hxx>
+
+FG_USING_STD(vector);
+
+
+typedef vector < int_list > fan_list;
+typedef fan_list::iterator fan_list_iterator;
+typedef fan_list::const_iterator const_fan_list_iterator;
+
+typedef vector < int_list > reverse_list;
+typedef reverse_list::iterator reverse_list_iterator;
+typedef reverse_list::const_iterator const_reverse_list_iterator;
+
+
+
+class FGGenFans {
+
+private:
+
+    fan_list fans;
+
+    // make sure the list is expanded at least to hold "n" and then
+    // push "i" onto the back of the "n" list.
+    void add_and_expand( reverse_list& by_node, int n, int i );
+
+public:
+
+    // Constructor && Destructor
+    inline FGGenFans() { }
+    inline ~FGGenFans() { }
+
+    // recursive build fans from triangle list
+    // fan_list greedy_build( triele_list tris );
+    fan_list greedy_build( triele_list tris );
+
+    // report average fan size
+    double ave_size();
+};
+
+
+#endif // _GENFANS_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/29 13:08:35  curt
+// Initial revision.
+//

From fc6eee819bb8d05c4958ff2c104ee6bf71457761 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 29 Mar 1999 13:11:00 +0000
Subject: [PATCH 266/283] Shuffled stl type names a bit. Began adding support
 for tri-fanning (or maybe other arrangments too.)

---
 Array/Makefile.am        |  5 ++++-
 Array/array.hxx          | 19 ++++++++++---------
 Construct/Makefile.am    |  1 +
 GenOutput/genobj.cxx     | 16 ++++++++++++----
 GenOutput/genobj.hxx     | 16 +++++++++++-----
 Main/Makefile.am         |  3 ++-
 Main/construct.cxx       | 21 +++++++++++++--------
 Triangulate/triangle.cxx | 14 +++++++++-----
 Triangulate/triangle.hxx |  8 ++++++--
 Triangulate/trinodes.hxx | 13 +++++--------
 Triangulate/tripoly.cxx  |  6 +++++-
 Triangulate/tripoly.hxx  | 13 +++++++------
 Triangulate/trisegs.cxx  |  6 +++++-
 13 files changed, 90 insertions(+), 51 deletions(-)

diff --git a/Array/Makefile.am b/Array/Makefile.am
index 8f9897423..a62648005 100644
--- a/Array/Makefile.am
+++ b/Array/Makefile.am
@@ -13,7 +13,10 @@ testarray_LDADD = \
 	$(top_builddir)/Lib/Misc/libMisc.a \
 	$(top_builddir)/Lib/zlib/libz.a
 
-INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
+INCLUDES += \
+	-I$(top_builddir) \
+	-I$(top_builddir)/Lib \
+	-I$(top_builddir)/Tools/Construct
 
 # We can't build this with "-O2" (optimization) since this causes a seg fault
 # I haven't found a way to strip this out of the CXXFLAGS, so I'm just
diff --git a/Array/array.hxx b/Array/array.hxx
index ee3c8a37b..601d0fb56 100644
--- a/Array/array.hxx
+++ b/Array/array.hxx
@@ -39,6 +39,8 @@
 #include <Math/point3d.hxx>
 #include <Misc/fgstream.hxx>
 
+#include <Main/construct_types.hxx>
+
 FG_USING_STD(vector);
 
 
@@ -46,11 +48,6 @@ FG_USING_STD(vector);
 #define ARRAY_SIZE_1 1201
 
 
-typedef vector < Point3D > fitnode_list;
-typedef fitnode_list::iterator fitnode_list_iterator;
-typedef fitnode_list::const_iterator const_fitnode_list_iterator;
-
-
 class FGArray {
 
 private:
@@ -73,8 +70,8 @@ private:
     // float (*out_data)[ARRAY_SIZE_1];
 
     // output nodes
-    fitnode_list corner_list;
-    fitnode_list node_list;
+    point_list corner_list;
+    point_list node_list;
 
 public:
 
@@ -116,8 +113,8 @@ public:
     inline double get_col_step() const { return col_step; }
     inline double get_row_step() const { return row_step; }
 
-    inline fitnode_list get_corner_node_list() const { return corner_list; }
-    inline fitnode_list get_fit_node_list() const { return node_list; }
+    inline point_list get_corner_node_list() const { return corner_list; }
+    inline point_list get_fit_node_list() const { return node_list; }
 };
 
 
@@ -125,6 +122,10 @@ public:
 
 
 // $Log$
+// Revision 1.5  1999/03/29 13:11:02  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.4  1999/03/27 05:20:14  curt
 // Handle corner nodes separately from the rest of the fitted nodes.
 // Fixed some "const" related warnings.
diff --git a/Construct/Makefile.am b/Construct/Makefile.am
index d3901496a..7761fd464 100644
--- a/Construct/Makefile.am
+++ b/Construct/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = \
 	Array \
 	Clipper \
+	GenFans \
 	GenOutput \
 	Triangulate \
 	Main
diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index d45a649ba..ad2446d07 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -64,7 +64,7 @@ void FGGenOutput::gen_wgs84_points( const FGArray& array ) {
 // is an entry for each point containing a list of all the triangles
 // that share that point.
 void FGGenOutput::gen_node_ele_lookup_table() {
-    belongs_to ele_list;
+    int_list ele_list;
     ele_list.erase( ele_list.begin(), ele_list.end() );
 
     // initialize reverse_ele_lookup structure by creating an empty
@@ -128,10 +128,10 @@ void FGGenOutput::gen_normals() {
 
     // for each node
     for ( int i = 0; i < (int)wgs84_nodes.size(); ++i ) {
-	belongs_to tri_list = reverse_ele_lookup[i];
+	int_list tri_list = reverse_ele_lookup[i];
 
-	belongs_to_iterator current = tri_list.begin();
-	belongs_to_iterator last = tri_list.end();
+	int_list_iterator current = tri_list.begin();
+	int_list_iterator last = tri_list.end();
 
 	Point3D average( 0.0 );
 
@@ -190,6 +190,10 @@ int FGGenOutput::build( const FGArray& array, const FGTriangle& t ) {
     // copy the triangle list into this class
     tri_elements = t.get_elelist();
 
+    // build the trifan list
+    FGGenFans f;
+    fans = f.greedy_build( tri_elements );
+
     // generate the point list in wgs-84 coordinates
     gen_wgs84_points( array );
 
@@ -400,6 +404,10 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 
 
 // $Log$
+// Revision 1.6  1999/03/29 13:11:03  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.5  1999/03/27 14:06:42  curt
 // Tweaks to bounding sphere calculation routines.
 // Group like triangles together for output to be in a single display list,
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index 2d89fbe66..7d2d84374 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -39,17 +39,16 @@
 #include <Bucket/newbucket.hxx>
 #include <Math/fg_geodesy.hxx>
 #include <Math/point3d.hxx>
+
+#include <GenFans/genfans.hxx>
+#include <Main/construct_types.hxx>
 #include <Triangulate/triangle.hxx>
 
 FG_USING_STD(string);
 FG_USING_STD(vector);
 
 
-typedef vector < int > belongs_to;
-typedef belongs_to::iterator belongs_to_iterator;
-typedef belongs_to::const_iterator belongs_to_tripoly_iterator;
-
-typedef vector < belongs_to > belongs_to_list;
+typedef vector < int_list > belongs_to_list;
 typedef belongs_to_list::iterator belongs_to_list_iterator;
 typedef belongs_to_list::const_iterator belongs_to_list_tripoly_iterator;
 
@@ -74,6 +73,9 @@ private:
     // triangles (by index into point list)
     triele_list tri_elements;
 
+    // fan list
+    fan_list fans;
+
     // for each node, a list of triangle indices that contain this node
     belongs_to_list reverse_ele_lookup;
 
@@ -129,6 +131,10 @@ public:
 
 
 // $Log$
+// Revision 1.7  1999/03/29 13:11:04  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.6  1999/03/27 14:06:43  curt
 // Tweaks to bounding sphere calculation routines.
 // Group like triangles together for output to be in a single display list,
diff --git a/Main/Makefile.am b/Main/Makefile.am
index 06acce5b2..ffc387243 100644
--- a/Main/Makefile.am
+++ b/Main/Makefile.am
@@ -1,11 +1,12 @@
 bin_PROGRAMS = construct
 
-construct_SOURCES = construct.cxx
+construct_SOURCES = construct.cxx construct_types.hxx
 
 construct_LDADD = \
 	$(top_builddir)/Tools/Construct/Array/libArray.a \
 	$(top_builddir)/Tools/Construct/Clipper/libClipper.a \
 	$(top_builddir)/Tools/Construct/GenOutput/libGenOutput.a \
+	$(top_builddir)/Tools/Construct/GenFans/libGenFans.a \
 	$(top_builddir)/Tools/Construct/Triangulate/libTriangulate.a \
 	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Tools/Lib/Triangle/libTriangle.a \
diff --git a/Main/construct.cxx b/Main/construct.cxx
index fb0d76f0f..92b853b45 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -37,7 +37,7 @@
 // load regular grid of elevation data (dem based), return list of
 // fitted nodes
 int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
-    fitnode_list result;
+    point_list result;
     string base = b.gen_base_path();
 
     string dem_path = work_base + ".dem" + "/Scenery/" + base 
@@ -138,8 +138,8 @@ void do_triangulate( const FGArray& array, const FGClipper& clipper,
     // first we need to consolidate the points of the DEM fit list and
     // all the polygons into a more "Triangle" friendly format
 
-    fitnode_list corner_list = array.get_corner_node_list();
-    fitnode_list fit_list = array.get_fit_node_list();
+    point_list corner_list = array.get_corner_node_list();
+    point_list fit_list = array.get_fit_node_list();
     FGgpcPolyList gpc_polys = clipper.get_polys_clipped();
 
     cout << "ready to build node list and polygons" << endl;
@@ -184,7 +184,6 @@ void construct_tile( const string& work_base, const string& output_base,
 
 
 main(int argc, char **argv) {
-    fitnode_list fit_list;
     double lon, lat;
 
     fglog().setLogLevels( FG_ALL, FG_DEBUG );
@@ -204,16 +203,18 @@ main(int argc, char **argv) {
     // lon = -89.744682312011719; lat= 29.314495086669922;
     // lon = -122.488090; lat = 42.743183;     // 64S
     // lon = -114.861097; lat = 35.947480;     // 61B
-    lon = -112.012175; lat = 41.195944;      // KOGD
+    // lon = -112.012175; lat = 41.195944;     // KOGD
+    lon = -90.757128; lat = 46.790212;       // WI32
 
     double min_x = lon - 1;
     double min_y = lat - 1;
     FGBucket b_min( min_x, min_y );
     FGBucket b_max( lon + 1, lat + 1 );
 
-    // FGBucket b(550363L);
-    // construct_tile( work_base, output_base, b );
-    // exit(0);
+    // FGBucket b(533955L);
+    FGBucket b(-146.248360, 61.133950);
+    construct_tile( work_base, output_base, b );
+    exit(0);
 
     if ( b_min == b_max ) {
 	construct_tile( work_base, output_base, b_min );
@@ -237,6 +238,10 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.11  1999/03/29 13:11:06  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.10  1999/03/27 05:25:02  curt
 // Fit with a value of 200 rather than 100.
 // Handle corner nodes separately from the rest of the fitted nodes.
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 5aa396721..dba74d102 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -37,8 +37,8 @@ FGTriangle::~FGTriangle( void ) {
 
 // populate this class based on the specified gpc_polys list
 int 
-FGTriangle::build( const fitnode_list& corner_list,
-		   const fitnode_list& fit_list, 
+FGTriangle::build( const point_list& corner_list,
+		   const point_list& fit_list, 
 		   const FGgpcPolyList& gpc_polys )
 {
     FGTriPoly poly;
@@ -55,7 +55,7 @@ FGTriangle::build( const fitnode_list& corner_list,
     // listing the points explicitely
 
     // first the corners since these are important
-    const_fitnode_list_iterator f_current, f_last;
+    const_point_list_iterator f_current, f_last;
     f_current = corner_list.begin();
     f_last = corner_list.end();
     for ( ; f_current != f_last; ++f_current ) {
@@ -328,7 +328,7 @@ int FGTriangle::run_triangulate() {
     vorout.normlist = (REAL *) NULL;      // Needed only if -v switch used.
     
     // TEMPORARY
-    write_out_data(&in);
+    // write_out_data(&in);
 
     // Triangulate the points.  Switches are chosen to read and write
     // a PSLG (p), preserve the convex hull (c), number everything
@@ -343,7 +343,7 @@ int FGTriangle::run_triangulate() {
     triangulate(tri_options.c_str(), &in, &out, &vorout);
 
     // TEMPORARY
-    // write_out_data(&out);
+    write_out_data(&out);
 
     // now copy the results back into the corresponding FGTriangle
     // structures
@@ -398,6 +398,10 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.13  1999/03/29 13:11:07  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.12  1999/03/27 05:30:12  curt
 // Handle corner nodes separately from the rest of the fitted nodes.
 // Add fitted nodes in after corners and polygon nodes since the fitted nodes
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index 8106c3ab3..b561bd2c1 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -76,8 +76,8 @@ public:
     int add_nodes();
 
     // populate this class based on the specified gpc_polys list
-    int build( const fitnode_list& corner_list, 
-	       const fitnode_list& fit_list,
+    int build( const point_list& corner_list, 
+	       const point_list& fit_list,
 	       const FGgpcPolyList& gpc_polys );
 
     // front end triangulator for polygon list
@@ -92,6 +92,10 @@ public:
 
 
 // $Log$
+// Revision 1.10  1999/03/29 13:11:08  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.9  1999/03/27 05:30:13  curt
 // Handle corner nodes separately from the rest of the fitted nodes.
 // Add fitted nodes in after corners and polygon nodes since the fitted nodes
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
index 860b63034..6b05a42df 100644
--- a/Triangulate/trinodes.hxx
+++ b/Triangulate/trinodes.hxx
@@ -33,22 +33,15 @@
 
 #include <Include/compiler.h>
 
-#include <vector>
-
 #include <Math/point3d.hxx>
 
-FG_USING_STD(vector);
+#include <Main/construct_types.hxx>
 
 
 #define FG_PROXIMITY_EPSILON 0.000001
 #define FG_COURSE_EPSILON 0.0003
 
 
-typedef vector < Point3D > point_list;
-typedef point_list::iterator point_list_iterator;
-typedef point_list::const_iterator const_point_list_iterator;
-
-
 class FGTriNodes {
 
 private:
@@ -119,6 +112,10 @@ inline bool FGTriNodes::course_close_enough( const Point3D& p1,
 
 
 // $Log$
+// Revision 1.7  1999/03/29 13:11:10  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.6  1999/03/27 05:30:16  curt
 // Handle corner nodes separately from the rest of the fitted nodes.
 // Add fitted nodes in after corners and polygon nodes since the fitted nodes
diff --git a/Triangulate/tripoly.cxx b/Triangulate/tripoly.cxx
index 763e369e4..d01bb8b40 100644
--- a/Triangulate/tripoly.cxx
+++ b/Triangulate/tripoly.cxx
@@ -95,7 +95,7 @@ void FGTriPoly::calc_point_inside( const FGTriNodes& trinodes ) {
     // int min_index;
     int min_node_index = 0;
 
-    tripoly_iterator current, last;
+    int_list_iterator current, last;
     current = poly.begin();
     last = poly.end();
 
@@ -180,6 +180,10 @@ void FGTriPoly::calc_point_inside( const FGTriNodes& trinodes ) {
 
 
 // $Log$
+// Revision 1.2  1999/03/29 13:11:11  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.1  1999/03/20 13:21:36  curt
 // Initial revision.
 //
diff --git a/Triangulate/tripoly.hxx b/Triangulate/tripoly.hxx
index 0cd87d00c..0e156dbae 100644
--- a/Triangulate/tripoly.hxx
+++ b/Triangulate/tripoly.hxx
@@ -35,21 +35,18 @@
 
 #include <vector>
 
+#include <Main/construct_types.hxx>
+
 #include "trinodes.hxx"
 
 FG_USING_STD(vector);
 
 
-typedef vector < int > tripoly;
-typedef tripoly::iterator tripoly_iterator;
-typedef tripoly::const_iterator const_tripoly_iterator;
-
-
 class FGTriPoly {
 
 private:
 
-    tripoly poly;
+    int_list poly;
     Point3D inside;
 
 public:
@@ -85,6 +82,10 @@ typedef tripoly_list::const_iterator const_tripoly_list_iterator;
 
 
 // $Log$
+// Revision 1.5  1999/03/29 13:11:12  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.4  1999/03/23 22:02:56  curt
 // Refinements in naming and organization.
 //
diff --git a/Triangulate/trisegs.cxx b/Triangulate/trisegs.cxx
index 62cf4d03a..1c1c386bf 100644
--- a/Triangulate/trisegs.cxx
+++ b/Triangulate/trisegs.cxx
@@ -76,7 +76,7 @@ void FGTriSegments::unique_divide_and_add( const point_list& nodes,
     Point3D p1 = nodes[ s.get_n2() ];
 
     bool found_extra = false;
-    int extra_index;
+    int extra_index = 0;
     int counter;
     double m, b, y_err, x_err;
     const_point_list_iterator current, last;
@@ -170,6 +170,10 @@ void FGTriSegments::unique_divide_and_add( const point_list& nodes,
 
 
 // $Log$
+// Revision 1.5  1999/03/29 13:11:13  curt
+// Shuffled stl type names a bit.
+// Began adding support for tri-fanning (or maybe other arrangments too.)
+//
 // Revision 1.4  1999/03/27 05:30:17  curt
 // Handle corner nodes separately from the rest of the fitted nodes.
 // Add fitted nodes in after corners and polygon nodes since the fitted nodes

From ad2835f3e31886cc4a4764af48bed5c191459d20 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 29 Mar 1999 13:19:44 +0000
Subject: [PATCH 267/283] Initial revision.

---
 Main/construct_types.hxx | 58 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 Main/construct_types.hxx

diff --git a/Main/construct_types.hxx b/Main/construct_types.hxx
new file mode 100644
index 000000000..095e48c56
--- /dev/null
+++ b/Main/construct_types.hxx
@@ -0,0 +1,58 @@
+// construct_types.hxx -- commonly used types in the construction business.
+//
+// Written by Curtis Olson, started March 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+
+#ifndef _CONSTRUCT_TYPES_HXX
+#define _CONSTRUCT_TYPES_HXX
+
+
+#ifndef __cplusplus                                                          
+# error This library requires C++
+#endif                                   
+
+
+#include <Include/compiler.h>
+
+#include <vector>
+
+#include <Math/point3d.hxx>
+
+FG_USING_STD(vector);
+
+
+typedef vector < int > int_list;
+typedef int_list::iterator int_list_iterator;
+typedef int_list::const_iterator const_int_list_iterator;
+
+typedef vector < Point3D > point_list;
+typedef point_list::iterator point_list_iterator;
+typedef point_list::const_iterator const_point_list_iterator;
+
+
+#endif // _CONSTRUCT_TYPES_HXX
+
+
+// $Log$
+// Revision 1.1  1999/03/29 13:19:44  curt
+// Initial revision.
+//

From 3f3afe16142709313f83f4b33b4440144062d532 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 30 Mar 1999 13:41:38 +0000
Subject: [PATCH 268/283] Working towards better handling of multi-contoured
 polygons.

---
 Clipper/clipper.cxx | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index a6d78fd3a..9817cf6de 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -55,7 +55,7 @@ bool FGClipper::init() {
 // Load a polygon definition file
 bool FGClipper::load_polys(const string& path) {
     string poly_name;
-    AreaType poly_type;
+    AreaType poly_type = DefaultArea;
     int contours, count, i, j;
     double startx, starty, x, y, lastx, lasty;
 
@@ -68,6 +68,10 @@ bool FGClipper::load_polys(const string& path) {
 	exit(-1);
     }
 
+    gpc_polygon *poly = new gpc_polygon;
+    poly->num_contours = 0;
+    poly->contour = NULL;
+
     in >> skipcomment;
     while ( !in.eof() ) {
 	in >> poly_name;
@@ -116,24 +120,22 @@ bool FGClipper::load_polys(const string& path) {
 			<< lastx << ", " << lasty );
 	    }
 
-	    gpc_polygon *poly = new gpc_polygon;
-	    poly->num_contours = 0;
-	    poly->contour = NULL;
 	    gpc_add_contour( poly, &v_list );
 
-	    int area = (int)poly_type;
-	    if ( area < FG_MAX_AREA_TYPES ) {
-		polys_in.polys[area].push_back(poly);
-	    } else {
-		FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = " 
-			<< (int)poly_type);
-		exit(-1);
-	    }
 	}
 
 	in >> skipcomment;
     }
 
+    int area = (int)poly_type;
+    if ( area < FG_MAX_AREA_TYPES ) {
+	polys_in.polys[area].push_back(poly);
+    } else {
+	FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = " 
+		<< (int)poly_type);
+	exit(-1);
+    }
+
     // FILE *ofp= fopen("outfile", "w");
     // gpc_write_polygon(ofp, &polys.landuse);
 
@@ -175,7 +177,7 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
     // process polygons in priority order
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-
+	cout << "num polys of this type = " << polys_in.polys[i].size() << endl;
 	current = polys_in.polys[i].begin();
 	last = polys_in.polys[i].end();
 	for ( ; current != last; ++current ) {
@@ -256,6 +258,9 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
 
 // $Log$
+// Revision 1.7  1999/03/30 13:41:38  curt
+// Working towards better handling of multi-contoured polygons.
+//
 // Revision 1.6  1999/03/27 05:20:53  curt
 // Pass along default area explicitely to triangulator.
 //

From bec6a05d33799b8c867c380d6d3fcac28b50a362 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 30 Mar 1999 23:49:22 +0000
Subject: [PATCH 269/283] Added some debugging output.

---
 Clipper/clipper.cxx | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index 9817cf6de..78f3dc21c 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -201,6 +201,18 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 		*result_diff = tmp;
 		result_union = tmp;
 	    } else {
+   		cout << "DIFF: tmp.num_contours = " << tmp.num_contours
+			<< " accum.num_contours = " << accum.num_contours
+			<< endl;
+		// tmp output accum
+		FILE *ofp= fopen("tmp-debug", "w");
+		gpc_write_polygon(ofp, &tmp);
+		fclose(ofp);
+
+		ofp= fopen("accum-debug", "w");
+		gpc_write_polygon(ofp, &accum);
+		fclose(ofp);
+
 		gpc_polygon_clip(GPC_DIFF, &tmp, &accum, result_diff);
 		gpc_polygon_clip(GPC_UNION, &tmp, &accum, &result_union);
 	    }
@@ -248,16 +260,21 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
     // tmp output accum
     FILE *ofp= fopen("accum", "w");
     gpc_write_polygon(ofp, &accum);
+    fclose(ofp);
 
     // tmp output safety_base
     ofp= fopen("remains", "w");
     gpc_write_polygon(ofp, remains);
+    fclose(ofp);
 
     return true;
 }
 
 
 // $Log$
+// Revision 1.8  1999/03/30 23:49:22  curt
+// Added some debugging output.
+//
 // Revision 1.7  1999/03/30 13:41:38  curt
 // Working towards better handling of multi-contoured polygons.
 //

From 0b74b1bbf275ba79a66400c9de7487a17756c35e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 30 Mar 1999 23:50:15 +0000
Subject: [PATCH 270/283] Fannifier is clearly bugging ... working on debugging
 it.  I suspect there is a problem related to deleting triangles from the
 triangle pool as they are combined into fans.

---
 Combine/genfans.cxx | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/Combine/genfans.cxx b/Combine/genfans.cxx
index fba5dfa68..05a16ea3d 100644
--- a/Combine/genfans.cxx
+++ b/Combine/genfans.cxx
@@ -62,6 +62,7 @@ static FGTriEle canonify( const FGTriEle& t, int center ) {
     }
 }
 
+// returns a list of triangle indices
 static int_list make_best_fan( const triele_list& master_tris, 
 			       const int center, const int_list& local_tris )
 {
@@ -134,6 +135,8 @@ static bool in_fan(int index, const int_list& fan ) {
 fan_list FGGenFans::greedy_build( triele_list tris ) {
     cout << "starting greedy build of fans" << endl;
 
+    fans.clear();
+
     while ( ! tris.empty() ) {
 	reverse_list by_node;
 	by_node.clear();
@@ -166,15 +169,32 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	    }
 	    ++counter;
 	}
-	cout << "master triangle pool = " << tris.size() << endl;
+	cout << "triangle pool = " << tris.size() << endl;
 	cout << "biggest_group = " << biggest_group.size() << endl;
 	cout << "center node = " << index << endl;
 
 	// make the best fan we can out of this group
 	int_list best_fan = make_best_fan( tris, index, biggest_group );
 
+	// generate point form of best_fan
+	int_list node_list;
+	node_list.clear();
+
+	int_list_iterator i_start = best_fan.begin();
+	int_list_iterator i_current = i_start;
+	int_list_iterator i_last = best_fan.end();
+	for ( ; i_current != i_last; ++i_current ) {
+	    FGTriEle t = canonify( tris[*i_current], index );
+	    if ( i_start == i_current ) {
+		node_list.push_back( t.get_n1() );
+		node_list.push_back( t.get_n2() );
+	    }
+	    node_list.push_back( t.get_n3() );
+	}
+	cout << "best list size = " << node_list.size() << endl;
+
 	// add this fan to the fan list
-	fans.push_back( best_fan );
+	fans.push_back( node_list );
 
 	// delete the triangles in best_fan out of tris and repeat
 	triele_list_iterator t_current = tris.begin();
@@ -182,8 +202,8 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	counter = 0;
 	for ( ; t_current != t_last; ++t_current ) {
 	    if ( in_fan(counter, best_fan) ) {
-		// cout << "erasing " << counter << " from master tri pool" 
-		//      << endl;
+		cout << "erasing " << counter << " from master tri pool" 
+		     << endl;
 		tris.erase( t_current );
 	    }
 	    ++counter;
@@ -212,6 +232,11 @@ double FGGenFans::ave_size() {
 
 
 // $Log$
+// Revision 1.2  1999/03/30 23:50:15  curt
+// Fannifier is clearly bugging ... working on debugging it.  I suspect there
+// is a problem related to deleting triangles from the triangle pool as they
+// are combined into fans.
+//
 // Revision 1.1  1999/03/29 13:08:35  curt
 // Initial revision.
 //

From 21b1516131f58fe7deee415ca7943b7d90a65ab5 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 30 Mar 1999 23:50:43 +0000
Subject: [PATCH 271/283] Modifications to fanify by attribute.

---
 GenOutput/genobj.cxx | 100 ++++++++++++++++++++++++++++---------------
 GenOutput/genobj.hxx |   7 ++-
 2 files changed, 70 insertions(+), 37 deletions(-)

diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index ad2446d07..0cbfdcdfe 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -191,8 +191,26 @@ int FGGenOutput::build( const FGArray& array, const FGTriangle& t ) {
     tri_elements = t.get_elelist();
 
     // build the trifan list
+    cout << "total triangles = " << tri_elements.size() << endl;
     FGGenFans f;
-    fans = f.greedy_build( tri_elements );
+    for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	cout << "generating fans for area = " << i << endl;
+
+	triele_list area_tris;
+	area_tris.erase( area_tris.begin(), area_tris.end() );
+
+	const_triele_list_iterator t_current = tri_elements.begin();
+	const_triele_list_iterator t_last = tri_elements.end();
+	for ( ; t_current != t_last; ++t_current ) {
+	    if ( (int)t_current->get_attribute() == i ) {
+		area_tris.push_back( *t_current );
+	    }
+	}
+
+	if ( (int)area_tris.size() > 0 ) {
+	    fans[i] = f.greedy_build( area_tris );
+	}
+    }
 
     // generate the point list in wgs-84 coordinates
     gen_wgs84_points( array );
@@ -215,25 +233,24 @@ int FGGenOutput::build( const FGArray& array, const FGTriangle& t ) {
 
 
 // caclulate the bounding sphere for a list of triangle faces
-void FGGenOutput::calc_group_bounding_sphere( const triele_list& tris, 
+void FGGenOutput::calc_group_bounding_sphere( const fan_list& fans, 
 					      Point3D *center, double *radius )
 {
-    cout << "calculate group bounding sphere for " << tris.size() << " tris." 
+    cout << "calculate group bounding sphere for " << fans.size() << " fans." 
 	 << endl;
 
     // generate a list of unique points from the triangle list
     FGTriNodes nodes;
 
-    const_triele_list_iterator t_current = tris.begin();
-    const_triele_list_iterator t_last = tris.end();
-    for ( ; t_current != t_last; ++t_current ) {
-	Point3D p1 = wgs84_nodes[ t_current->get_n1() ];
-	Point3D p2 = wgs84_nodes[ t_current->get_n2() ];
-	Point3D p3 = wgs84_nodes[ t_current->get_n3() ];
-
-	nodes.unique_add(p1);
-	nodes.unique_add(p2);
-	nodes.unique_add(p3);
+    const_fan_list_iterator f_current = fans.begin();
+    const_fan_list_iterator f_last = fans.end();
+    for ( ; f_current != f_last; ++f_current ) {
+	const_int_list_iterator i_current = f_current->begin();
+	const_int_list_iterator i_last = f_current->end();
+	for ( ; i_current != i_last; ++i_current ) {
+	    Point3D p1 = wgs84_nodes[ *i_current ];
+	    nodes.unique_add(p1);
+	}
     }
 
     // find average of point list
@@ -357,42 +374,52 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
     // write triangles (grouped by type for now)
     Point3D center;
     double radius;
-    fprintf(fp, "# triangle list\n");
+    fprintf(fp, "# triangle groups\n");
     fprintf(fp, "\n");
 
+    int total_tris = 0;
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	triele_list area_tris;
-	area_tris.erase( area_tris.begin(), area_tris.end() );
-
-	const_triele_list_iterator t_current = tri_elements.begin();
-	const_triele_list_iterator t_last = tri_elements.end();
-	for ( ; t_current != t_last; ++t_current ) {
-	    if ( (int)t_current->get_attribute() == i ) {
-		area_tris.push_back( *t_current );
-	    }
-	}
-
-	if ( (int)area_tris.size() > 0 ) {
+	if ( (int)fans[i].size() > 0 ) {
 	    string attr_name = get_area_name( (AreaType)i );
-	    calc_group_bounding_sphere( area_tris, &center, &radius );
-	    cout << "writing " << (int)area_tris.size() << " faces for " 
+	    calc_group_bounding_sphere( fans[i], &center, &radius );
+	    cout << "writing " << (int)fans[i].size() << " fans for " 
 		 << attr_name << endl;
 
 	    fprintf(fp, "# usemtl %s\n", attr_name.c_str() );
 	    fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n", 
 		    center.x(), center.y(), center.z(), radius);
 
-	    triele_list_iterator a_current = area_tris.begin();
-	    triele_list_iterator a_last = area_tris.end();
-	    for ( ; a_current != a_last; ++a_current ) {
-		fprintf( fp, "f %d %d %d\n", 
-			 a_current->get_n1(), 
-			 a_current->get_n2(),
-			 a_current->get_n3() );
+	    fan_list_iterator f_current = fans[i].begin();
+	    fan_list_iterator f_last = fans[i].end();
+	    for ( ; f_current != f_last; ++f_current ) {
+		fprintf( fp, "tf" );
+		int_list_iterator i_current = f_current->begin();
+		int_list_iterator i_last = f_current->end();
+		for ( ; i_current != i_last; ++i_current ) {
+		    fprintf( fp, " %d", *i_current );
+		}
+		fprintf( fp, "\n" );
+
+		{
+		int_list_iterator i_current = f_current->begin();
+		int_list_iterator i_last = f_current->end();
+		int center = *i_current;
+		++i_current;
+		int n2 = *i_current;
+		++i_current;
+		for ( ; i_current != i_last; ++i_current ) {
+		    int n3 = *i_current;
+		    fprintf( fp, "f %d %d %d\n", center, n2, n3 );
+		    ++total_tris;
+		    n2 = n3;
+		}
+		}
 	    }
+
 	    fprintf( fp, "\n" );
 	}
     }
+    cout << "wrote " << total_tris << " tris to output file" << endl;
 
     fclose(fp);
 
@@ -404,6 +431,9 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 
 
 // $Log$
+// Revision 1.7  1999/03/30 23:50:43  curt
+// Modifications to fanify by attribute.
+//
 // Revision 1.6  1999/03/29 13:11:03  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index 7d2d84374..e6ffd1dae 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -74,7 +74,7 @@ private:
     triele_list tri_elements;
 
     // fan list
-    fan_list fans;
+    fan_list fans[FG_MAX_AREA_TYPES];
 
     // for each node, a list of triangle indices that contain this node
     belongs_to_list reverse_ele_lookup;
@@ -105,7 +105,7 @@ private:
     void calc_gbs();
 
     // caclulate the bounding sphere for a list of triangle faces
-    void calc_group_bounding_sphere( const triele_list& tris, 
+    void calc_group_bounding_sphere( const fan_list& fans, 
 				     Point3D *center, double *radius );
 
     // caclulate the bounding sphere for the specified triangle face
@@ -131,6 +131,9 @@ public:
 
 
 // $Log$
+// Revision 1.8  1999/03/30 23:50:44  curt
+// Modifications to fanify by attribute.
+//
 // Revision 1.7  1999/03/29 13:11:04  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)

From 6a7b127577e6e4429da8199b0571bcce3aa1dbea Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 30 Mar 1999 23:51:14 +0000
Subject: [PATCH 272/283] fiddling ...

---
 Main/construct.cxx | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index 92b853b45..4f6be6006 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -196,7 +196,7 @@ main(int argc, char **argv) {
     string work_base = argv[1];
     string output_base = argv[2];
    
-    // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
+    lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
     // lon = -110.664244; lat = 33.352890;     // P13
     // lon = -93.211389; lat = 45.145000;      // KANE
     // lon = -92.486188; lat = 44.590190;      // KRGK
@@ -204,14 +204,14 @@ main(int argc, char **argv) {
     // lon = -122.488090; lat = 42.743183;     // 64S
     // lon = -114.861097; lat = 35.947480;     // 61B
     // lon = -112.012175; lat = 41.195944;     // KOGD
-    lon = -90.757128; lat = 46.790212;       // WI32
+    // lon = -90.757128; lat = 46.790212;      // WI32
 
     double min_x = lon - 1;
     double min_y = lat - 1;
     FGBucket b_min( min_x, min_y );
     FGBucket b_max( lon + 1, lat + 1 );
 
-    // FGBucket b(533955L);
+    // FGBucket b(566664L);
     FGBucket b(-146.248360, 61.133950);
     construct_tile( work_base, output_base, b );
     exit(0);
@@ -229,7 +229,10 @@ main(int argc, char **argv) {
 	for ( j = 0; j <= dy; j++ ) {
 	    for ( i = 0; i <= dx; i++ ) {
 		b_cur = fgBucketOffset(min_x, min_y, i, j);
-		construct_tile( work_base, output_base, b_cur );
+
+		if ( b_cur != b ) {
+		    construct_tile( work_base, output_base, b_cur );
+		}
 	    }
 	}
 	// string answer; cin >> answer;
@@ -238,6 +241,9 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.12  1999/03/30 23:51:14  curt
+// fiddling ...
+//
 // Revision 1.11  1999/03/29 13:11:06  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)

From 8a691a975f5b0f5fdc4f7ed472461f77fd444d23 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 31 Mar 1999 05:35:04 +0000
Subject: [PATCH 273/283] Fixed bug in genfans (deleting the wrong triangles
 from the available pool.)

---
 Combine/genfans.cxx  | 21 +++++++++++++++------
 GenOutput/genobj.cxx | 29 +++++++++++++++++------------
 Main/construct.cxx   | 19 +++++++++++--------
 3 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/Combine/genfans.cxx b/Combine/genfans.cxx
index 05a16ea3d..2dcab97fc 100644
--- a/Combine/genfans.cxx
+++ b/Combine/genfans.cxx
@@ -70,7 +70,7 @@ static int_list make_best_fan( const triele_list& master_tris,
 
     // try starting with local triangle to find the best fan arrangement
     for ( int start = 0; start < (int)local_tris.size(); ++start ) {
-	cout << "trying with first triangle = " << local_tris[start] << endl;
+	// cout << "trying with first triangle = " << local_tris[start] << endl;
 
 	int_list tmp_result;
 	tmp_result.clear();
@@ -90,7 +90,7 @@ static int_list make_best_fan( const triele_list& master_tris,
 		test = canonify( master_tris[local_tris[i]], center );
 		if ( current_tri.get_n3() == test.get_n2() ) {
 		    if ( i != start ) {
-			cout << "  next triangle = " << local_tris[i] << endl;
+			// cout << " next triangle = " << local_tris[i] << endl;
 			current_tri = test;
 			tmp_result.push_back( local_tris[i] );
 			matches = true;
@@ -103,12 +103,12 @@ static int_list make_best_fan( const triele_list& master_tris,
 
 	if ( tmp_result.size() == local_tris.size() ) {
 	    // we found a complete usage, no need to go on
-	    cout << "we found a complete usage, no need to go on" << endl;
+	    // cout << "we found a complete usage, no need to go on" << endl;
 	    best_result = tmp_result;
 	    break;
 	} else if ( tmp_result.size() > best_result.size() ) {
 	    // we found a better way to fan
-	    cout << "we found a better fan arrangement" << endl;
+	    // cout << "we found a better fan arrangement" << endl;
 	    best_result = tmp_result;
 	}
     }
@@ -200,11 +200,17 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	triele_list_iterator t_current = tris.begin();
 	triele_list_iterator t_last = tris.end();
 	counter = 0;
-	for ( ; t_current != t_last; ++t_current ) {
+	while ( t_current != t_last ) {
 	    if ( in_fan(counter, best_fan) ) {
-		cout << "erasing " << counter << " from master tri pool" 
+		cout << "erasing " 
+		     << t_current->get_n1() << ","
+		     << t_current->get_n2() << ","
+		     << t_current->get_n3()
+		     << " from master tri pool"
 		     << endl;
 		tris.erase( t_current );
+	    } else {
+		++t_current;
 	    }
 	    ++counter;
 	}
@@ -232,6 +238,9 @@ double FGGenFans::ave_size() {
 
 
 // $Log$
+// Revision 1.3  1999/03/31 05:35:04  curt
+// Fixed bug in genfans (deleting the wrong triangles from the available pool.)
+//
 // Revision 1.2  1999/03/30 23:50:15  curt
 // Fannifier is clearly bugging ... working on debugging it.  I suspect there
 // is a problem related to deleting triangles from the triangle pool as they
diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index 0cbfdcdfe..9716cd617 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -400,20 +400,22 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 		}
 		fprintf( fp, "\n" );
 
+#if 0
 		{
-		int_list_iterator i_current = f_current->begin();
-		int_list_iterator i_last = f_current->end();
-		int center = *i_current;
-		++i_current;
-		int n2 = *i_current;
-		++i_current;
-		for ( ; i_current != i_last; ++i_current ) {
-		    int n3 = *i_current;
-		    fprintf( fp, "f %d %d %d\n", center, n2, n3 );
-		    ++total_tris;
-		    n2 = n3;
-		}
+		    int_list_iterator i_current = f_current->begin();
+		    int_list_iterator i_last = f_current->end();
+		    int center = *i_current;
+		    ++i_current;
+		    int n2 = *i_current;
+		    ++i_current;
+		    for ( ; i_current != i_last; ++i_current ) {
+			int n3 = *i_current;
+			fprintf( fp, "f %d %d %d\n", center, n2, n3 );
+			++total_tris;
+			n2 = n3;
+		    }
 		}
+#endif
 	    }
 
 	    fprintf( fp, "\n" );
@@ -431,6 +433,9 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 
 
 // $Log$
+// Revision 1.8  1999/03/31 05:35:05  curt
+// Fixed bug in genfans (deleting the wrong triangles from the available pool.)
+//
 // Revision 1.7  1999/03/30 23:50:43  curt
 // Modifications to fanify by attribute.
 //
diff --git a/Main/construct.cxx b/Main/construct.cxx
index 4f6be6006..224fa1bd3 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -196,13 +196,13 @@ main(int argc, char **argv) {
     string work_base = argv[1];
     string output_base = argv[2];
    
-    lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
+    // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
     // lon = -110.664244; lat = 33.352890;     // P13
     // lon = -93.211389; lat = 45.145000;      // KANE
     // lon = -92.486188; lat = 44.590190;      // KRGK
     // lon = -89.744682312011719; lat= 29.314495086669922;
     // lon = -122.488090; lat = 42.743183;     // 64S
-    // lon = -114.861097; lat = 35.947480;     // 61B
+    lon = -114.861097; lat = 35.947480;     // 61B
     // lon = -112.012175; lat = 41.195944;     // KOGD
     // lon = -90.757128; lat = 46.790212;      // WI32
 
@@ -212,9 +212,9 @@ main(int argc, char **argv) {
     FGBucket b_max( lon + 1, lat + 1 );
 
     // FGBucket b(566664L);
-    FGBucket b(-146.248360, 61.133950);
-    construct_tile( work_base, output_base, b );
-    exit(0);
+    // FGBucket b(-146.248360, 61.133950);
+    // construct_tile( work_base, output_base, b );
+    // exit(0);
 
     if ( b_min == b_max ) {
 	construct_tile( work_base, output_base, b_min );
@@ -230,9 +230,9 @@ main(int argc, char **argv) {
 	    for ( i = 0; i <= dx; i++ ) {
 		b_cur = fgBucketOffset(min_x, min_y, i, j);
 
-		if ( b_cur != b ) {
-		    construct_tile( work_base, output_base, b_cur );
-		}
+		// if ( b_cur != b ) {
+		construct_tile( work_base, output_base, b_cur );
+		// }
 	    }
 	}
 	// string answer; cin >> answer;
@@ -241,6 +241,9 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.13  1999/03/31 05:35:06  curt
+// Fixed bug in genfans (deleting the wrong triangles from the available pool.)
+//
 // Revision 1.12  1999/03/30 23:51:14  curt
 // fiddling ...
 //

From 14273c1760b84fa91906a993ddb170a14e57a845 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 31 Mar 1999 13:26:39 +0000
Subject: [PATCH 274/283] Debugging output tweeaks.

---
 Combine/genfans.cxx  | 15 +++++++++------
 GenOutput/genobj.cxx |  7 +++++--
 Main/construct.cxx   |  7 +++++--
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/Combine/genfans.cxx b/Combine/genfans.cxx
index 2dcab97fc..be2ba6822 100644
--- a/Combine/genfans.cxx
+++ b/Combine/genfans.cxx
@@ -202,12 +202,12 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	counter = 0;
 	while ( t_current != t_last ) {
 	    if ( in_fan(counter, best_fan) ) {
-		cout << "erasing " 
-		     << t_current->get_n1() << ","
-		     << t_current->get_n2() << ","
-		     << t_current->get_n3()
-		     << " from master tri pool"
-		     << endl;
+		// cout << "erasing " 
+		//      << t_current->get_n1() << ","
+		//      << t_current->get_n2() << ","
+		//      << t_current->get_n3()
+		//      << " from master tri pool"
+		//      << endl;
 		tris.erase( t_current );
 	    } else {
 		++t_current;
@@ -238,6 +238,9 @@ double FGGenFans::ave_size() {
 
 
 // $Log$
+// Revision 1.4  1999/03/31 13:26:39  curt
+// Debugging output tweeaks.
+//
 // Revision 1.3  1999/03/31 05:35:04  curt
 // Fixed bug in genfans (deleting the wrong triangles from the available pool.)
 //
diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index 9716cd617..4b12bfe29 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -256,7 +256,7 @@ void FGGenOutput::calc_group_bounding_sphere( const fan_list& fans,
     // find average of point list
     Point3D c( 0.0 );
     point_list points = nodes.get_node_list();
-    cout << "found " << points.size() << " unique nodes" << endl;
+    // cout << "found " << points.size() << " unique nodes" << endl;
     point_list_iterator p_current = points.begin();
     point_list_iterator p_last = points.end();
     for ( ; p_current != p_last; ++p_current ) {
@@ -393,6 +393,7 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 	    fan_list_iterator f_last = fans[i].end();
 	    for ( ; f_current != f_last; ++f_current ) {
 		fprintf( fp, "tf" );
+		total_tris += f_current->size() - 2;
 		int_list_iterator i_current = f_current->begin();
 		int_list_iterator i_last = f_current->end();
 		for ( ; i_current != i_last; ++i_current ) {
@@ -411,7 +412,6 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 		    for ( ; i_current != i_last; ++i_current ) {
 			int n3 = *i_current;
 			fprintf( fp, "f %d %d %d\n", center, n2, n3 );
-			++total_tris;
 			n2 = n3;
 		    }
 		}
@@ -433,6 +433,9 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 
 
 // $Log$
+// Revision 1.9  1999/03/31 13:26:40  curt
+// Debugging output tweeaks.
+//
 // Revision 1.8  1999/03/31 05:35:05  curt
 // Fixed bug in genfans (deleting the wrong triangles from the available pool.)
 //
diff --git a/Main/construct.cxx b/Main/construct.cxx
index 224fa1bd3..ad578622c 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -199,10 +199,10 @@ main(int argc, char **argv) {
     // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
     // lon = -110.664244; lat = 33.352890;     // P13
     // lon = -93.211389; lat = 45.145000;      // KANE
-    // lon = -92.486188; lat = 44.590190;      // KRGK
+    lon = -92.486188; lat = 44.590190;      // KRGK
     // lon = -89.744682312011719; lat= 29.314495086669922;
     // lon = -122.488090; lat = 42.743183;     // 64S
-    lon = -114.861097; lat = 35.947480;     // 61B
+    // lon = -114.861097; lat = 35.947480;     // 61B
     // lon = -112.012175; lat = 41.195944;     // KOGD
     // lon = -90.757128; lat = 46.790212;      // WI32
 
@@ -241,6 +241,9 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.14  1999/03/31 13:26:41  curt
+// Debugging output tweeaks.
+//
 // Revision 1.13  1999/03/31 05:35:06  curt
 // Fixed bug in genfans (deleting the wrong triangles from the available pool.)
 //

From d3e3985f4be37efbc865a654754b2e1d6225f2af Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 31 Mar 1999 23:46:20 +0000
Subject: [PATCH 275/283] Added scenery_version.hxx to source distribution.

---
 Construct/Makefile.am | 2 +-
 Tools/Makefile.am     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Construct/Makefile.am b/Construct/Makefile.am
index 7761fd464..f19226325 100644
--- a/Construct/Makefile.am
+++ b/Construct/Makefile.am
@@ -1,7 +1,7 @@
 SUBDIRS = \
 	Array \
 	Clipper \
-	GenFans \
+	Combine \
 	GenOutput \
 	Triangulate \
 	Main
diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index a448801a7..f51cf02c9 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -1,4 +1,4 @@
-EXTRA_DIST = process-dem.pl
+EXTRA_DIST = process-dem.pl scenery_version.hxx
 
 SUBDIRS = \
 	Lib \

From af55795d499ba83b2cfa7e28d403d0b944d45af0 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 31 Mar 1999 23:46:38 +0000
Subject: [PATCH 276/283] Debuggin output tweaks.

---
 Clipper/clipper.cxx | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/Clipper/clipper.cxx b/Clipper/clipper.cxx
index 78f3dc21c..a088f0ffb 100644
--- a/Clipper/clipper.cxx
+++ b/Clipper/clipper.cxx
@@ -177,7 +177,8 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
     // process polygons in priority order
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	cout << "num polys of this type = " << polys_in.polys[i].size() << endl;
+	// cout << "num polys of this type = " 
+	//       << polys_in.polys[i].size() << endl;
 	current = polys_in.polys[i].begin();
 	last = polys_in.polys[i].end();
 	for ( ; current != last; ++current ) {
@@ -201,9 +202,9 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 		*result_diff = tmp;
 		result_union = tmp;
 	    } else {
-   		cout << "DIFF: tmp.num_contours = " << tmp.num_contours
-			<< " accum.num_contours = " << accum.num_contours
-			<< endl;
+   		// cout << "DIFF: tmp.num_contours = " << tmp.num_contours
+		//      << " accum.num_contours = " << accum.num_contours
+		//      << endl;
 		// tmp output accum
 		FILE *ofp= fopen("tmp-debug", "w");
 		gpc_write_polygon(ofp, &tmp);
@@ -272,6 +273,9 @@ bool FGClipper::clip_all(const point2d& min, const point2d& max) {
 
 
 // $Log$
+// Revision 1.9  1999/03/31 23:46:38  curt
+// Debuggin output tweaks.
+//
 // Revision 1.8  1999/03/30 23:49:22  curt
 // Added some debugging output.
 //

From f8f6dbcfdee75c2e72a6c4cf14964d18571643e4 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 31 Mar 1999 23:46:48 +0000
Subject: [PATCH 277/283] Debugging output tweaks.

---
 Combine/Makefile.am      |  4 ++--
 Combine/genfans.cxx      | 11 +++++++----
 GenOutput/genobj.cxx     |  6 ++++--
 GenOutput/genobj.hxx     |  5 ++++-
 Main/Makefile.am         |  2 +-
 Main/construct.cxx       | 16 ++++++++++------
 Triangulate/triangle.cxx |  7 +++++--
 7 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/Combine/Makefile.am b/Combine/Makefile.am
index ea8702955..c8c640202 100644
--- a/Combine/Makefile.am
+++ b/Combine/Makefile.am
@@ -1,6 +1,6 @@
-noinst_LIBRARIES = libGenFans.a
+noinst_LIBRARIES = libCombine.a
 
-libGenFans_a_SOURCES = genfans.cxx genfans.hxx
+libCombine_a_SOURCES = genfans.cxx genfans.hxx
 
 INCLUDES += \
 	-I$(top_builddir) \
diff --git a/Combine/genfans.cxx b/Combine/genfans.cxx
index be2ba6822..57aa05f46 100644
--- a/Combine/genfans.cxx
+++ b/Combine/genfans.cxx
@@ -169,9 +169,9 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	    }
 	    ++counter;
 	}
-	cout << "triangle pool = " << tris.size() << endl;
-	cout << "biggest_group = " << biggest_group.size() << endl;
-	cout << "center node = " << index << endl;
+	// cout << "triangle pool = " << tris.size() << endl;
+	// cout << "biggest_group = " << biggest_group.size() << endl;
+	// cout << "center node = " << index << endl;
 
 	// make the best fan we can out of this group
 	int_list best_fan = make_best_fan( tris, index, biggest_group );
@@ -191,7 +191,7 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	    }
 	    node_list.push_back( t.get_n3() );
 	}
-	cout << "best list size = " << node_list.size() << endl;
+	// cout << "best list size = " << node_list.size() << endl;
 
 	// add this fan to the fan list
 	fans.push_back( node_list );
@@ -238,6 +238,9 @@ double FGGenFans::ave_size() {
 
 
 // $Log$
+// Revision 1.5  1999/03/31 23:46:49  curt
+// Debugging output tweaks.
+//
 // Revision 1.4  1999/03/31 13:26:39  curt
 // Debugging output tweeaks.
 //
diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx
index 4b12bfe29..fc3cc3b68 100644
--- a/GenOutput/genobj.cxx
+++ b/GenOutput/genobj.cxx
@@ -194,8 +194,6 @@ int FGGenOutput::build( const FGArray& array, const FGTriangle& t ) {
     cout << "total triangles = " << tri_elements.size() << endl;
     FGGenFans f;
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	cout << "generating fans for area = " << i << endl;
-
 	triele_list area_tris;
 	area_tris.erase( area_tris.begin(), area_tris.end() );
 
@@ -208,6 +206,7 @@ int FGGenOutput::build( const FGArray& array, const FGTriangle& t ) {
 	}
 
 	if ( (int)area_tris.size() > 0 ) {
+	    cout << "generating fans for area = " << i << endl;
 	    fans[i] = f.greedy_build( area_tris );
 	}
     }
@@ -433,6 +432,9 @@ int FGGenOutput::write( const string& base, const FGBucket& b ) {
 
 
 // $Log$
+// Revision 1.10  1999/03/31 23:46:57  curt
+// Debugging output tweaks.
+//
 // Revision 1.9  1999/03/31 13:26:40  curt
 // Debugging output tweeaks.
 //
diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx
index e6ffd1dae..55f984452 100644
--- a/GenOutput/genobj.hxx
+++ b/GenOutput/genobj.hxx
@@ -40,7 +40,7 @@
 #include <Math/fg_geodesy.hxx>
 #include <Math/point3d.hxx>
 
-#include <GenFans/genfans.hxx>
+#include <Combine/genfans.hxx>
 #include <Main/construct_types.hxx>
 #include <Triangulate/triangle.hxx>
 
@@ -131,6 +131,9 @@ public:
 
 
 // $Log$
+// Revision 1.9  1999/03/31 23:46:58  curt
+// Debugging output tweaks.
+//
 // Revision 1.8  1999/03/30 23:50:44  curt
 // Modifications to fanify by attribute.
 //
diff --git a/Main/Makefile.am b/Main/Makefile.am
index ffc387243..95e1e4f14 100644
--- a/Main/Makefile.am
+++ b/Main/Makefile.am
@@ -6,7 +6,7 @@ construct_LDADD = \
 	$(top_builddir)/Tools/Construct/Array/libArray.a \
 	$(top_builddir)/Tools/Construct/Clipper/libClipper.a \
 	$(top_builddir)/Tools/Construct/GenOutput/libGenOutput.a \
-	$(top_builddir)/Tools/Construct/GenFans/libGenFans.a \
+	$(top_builddir)/Tools/Construct/Combine/libCombine.a \
 	$(top_builddir)/Tools/Construct/Triangulate/libTriangulate.a \
 	$(top_builddir)/Tools/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/Tools/Lib/Triangle/libTriangle.a \
diff --git a/Main/construct.cxx b/Main/construct.cxx
index ad578622c..d5b93c5e8 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -197,21 +197,22 @@ main(int argc, char **argv) {
     string output_base = argv[2];
    
     // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
-    // lon = -110.664244; lat = 33.352890;     // P13
+    lon = -110.664244; lat = 33.352890;     // P13
     // lon = -93.211389; lat = 45.145000;      // KANE
-    lon = -92.486188; lat = 44.590190;      // KRGK
+    // lon = -92.486188; lat = 44.590190;      // KRGK
     // lon = -89.744682312011719; lat= 29.314495086669922;
     // lon = -122.488090; lat = 42.743183;     // 64S
     // lon = -114.861097; lat = 35.947480;     // 61B
     // lon = -112.012175; lat = 41.195944;     // KOGD
     // lon = -90.757128; lat = 46.790212;      // WI32
+    // lon = -122.220717; lat = 37.721291;      // KOAK
 
     double min_x = lon - 1;
     double min_y = lat - 1;
     FGBucket b_min( min_x, min_y );
     FGBucket b_max( lon + 1, lat + 1 );
 
-    // FGBucket b(566664L);
+    FGBucket b_omit(550314L);
     // FGBucket b(-146.248360, 61.133950);
     // construct_tile( work_base, output_base, b );
     // exit(0);
@@ -230,9 +231,9 @@ main(int argc, char **argv) {
 	    for ( i = 0; i <= dx; i++ ) {
 		b_cur = fgBucketOffset(min_x, min_y, i, j);
 
-		// if ( b_cur != b ) {
-		construct_tile( work_base, output_base, b_cur );
-		// }
+		if ( b_cur != b_omit ) {
+		    construct_tile( work_base, output_base, b_cur );
+		}
 	    }
 	}
 	// string answer; cin >> answer;
@@ -241,6 +242,9 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.15  1999/03/31 23:47:02  curt
+// Debugging output tweaks.
+//
 // Revision 1.14  1999/03/31 13:26:41  curt
 // Debugging output tweeaks.
 //
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index dba74d102..6265237b0 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -70,7 +70,7 @@ FGTriangle::build( const point_list& corner_list,
     cout << "prepairing node list and polygons" << endl;
 
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	cout << "area type = " << i << endl;
+	// cout << "area type = " << i << endl;
 	current = gpc_polys.polys[i].begin();
 	last = gpc_polys.polys[i].end();
 	for ( ; current != last; ++current ) {
@@ -140,7 +140,7 @@ FGTriangle::build( const point_list& corner_list,
     int i1, i2;
     point_list node_list = in_nodes.get_node_list();
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
-	cout << "area type = " << i << endl;
+	// cout << "area type = " << i << endl;
 	tripoly_list_iterator tp_current, tp_last;
 	tp_current = polylist[i].begin();
 	tp_last = polylist[i].end();
@@ -398,6 +398,9 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.14  1999/03/31 23:47:09  curt
+// Debugging output tweaks.
+//
 // Revision 1.13  1999/03/29 13:11:07  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)

From a1f70c00a8d4399b798f89cc9c917f567bbfeab1 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Thu, 1 Apr 1999 13:52:11 +0000
Subject: [PATCH 278/283] Version 0.6.0 Shape name tweak. Removing tool:
 FixNode

---
 Main/construct.cxx | 10 ++++++++--
 Polygon/names.cxx  |  8 +++++++-
 Tools/Makefile.am  |  1 -
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index d5b93c5e8..12099f928 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -197,7 +197,7 @@ main(int argc, char **argv) {
     string output_base = argv[2];
    
     // lon = -146.248360; lat = 61.133950;     // PAVD (Valdez, AK)
-    lon = -110.664244; lat = 33.352890;     // P13
+    // lon = -110.664244; lat = 33.352890;     // P13
     // lon = -93.211389; lat = 45.145000;      // KANE
     // lon = -92.486188; lat = 44.590190;      // KRGK
     // lon = -89.744682312011719; lat= 29.314495086669922;
@@ -205,7 +205,8 @@ main(int argc, char **argv) {
     // lon = -114.861097; lat = 35.947480;     // 61B
     // lon = -112.012175; lat = 41.195944;     // KOGD
     // lon = -90.757128; lat = 46.790212;      // WI32
-    // lon = -122.220717; lat = 37.721291;      // KOAK
+    // lon = -122.220717; lat = 37.721291;     // KOAK
+    lon = -111.721477; lat = 40.215641;     // KPVU
 
     double min_x = lon - 1;
     double min_y = lat - 1;
@@ -242,6 +243,11 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.16  1999/04/01 13:52:12  curt
+// Version 0.6.0
+// Shape name tweak.
+// Removing tool: FixNode
+//
 // Revision 1.15  1999/03/31 23:47:02  curt
 // Debugging output tweaks.
 //
diff --git a/Polygon/names.cxx b/Polygon/names.cxx
index d3d190612..2633d19a6 100644
--- a/Polygon/names.cxx
+++ b/Polygon/names.cxx
@@ -52,7 +52,8 @@ AreaType get_area_type( string area ) {
 	return IntLakeArea;
     } else if ( area == "Reservoir" ) {
 	return ReservoirArea;
-    } else if ( area == "Reservoir   Intermittent" ) {
+    } else if ( (area == "Reservoir   Intermittent")
+		|| (area == "IntermittentReservoir") ) {
 	return IntReservoirArea;
     } else if ( area == "Stream" ) {
 	return StreamArea;
@@ -115,6 +116,11 @@ string get_area_name( AreaType area ) {
 
 
 // $Log$
+// Revision 1.7  1999/04/01 13:52:13  curt
+// Version 0.6.0
+// Shape name tweak.
+// Removing tool: FixNode
+//
 // Revision 1.6  1999/03/27 05:31:24  curt
 // Make 0 the default area type since this corresponds well with the conventions
 //   used by the triangulator.
diff --git a/Tools/Makefile.am b/Tools/Makefile.am
index f51cf02c9..034024ed4 100644
--- a/Tools/Makefile.am
+++ b/Tools/Makefile.am
@@ -7,7 +7,6 @@ SUBDIRS = \
 	Utils \
 	Areas \
 	AssemTris \
-	FixNode \
 	FixObj \
 	SplitTris \
 	Stripe_w \

From bcb6638535a77ccf7532f9266798e02301116152 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Sat, 3 Apr 1999 05:22:57 +0000
Subject: [PATCH 279/283] Found a bug in dividing and adding unique verticle
 segments which could cause the triangulator to end up in an infinite loop. 
 Basically the code was correct, but the verticle line test was a bit to
 selective.

---
 Main/construct.cxx       |  9 ++++++++-
 Triangulate/triangle.cxx |  9 +++++++--
 Triangulate/trisegs.cxx  | 18 ++++++++++++++++--
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index 12099f928..85227747b 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -206,7 +206,8 @@ main(int argc, char **argv) {
     // lon = -112.012175; lat = 41.195944;     // KOGD
     // lon = -90.757128; lat = 46.790212;      // WI32
     // lon = -122.220717; lat = 37.721291;     // KOAK
-    lon = -111.721477; lat = 40.215641;     // KPVU
+    // lon = -111.721477; lat = 40.215641;     // KPVU
+    lon = -122.309313; lat = 47.448982;     // KSEA
 
     double min_x = lon - 1;
     double min_y = lat - 1;
@@ -214,6 +215,7 @@ main(int argc, char **argv) {
     FGBucket b_max( lon + 1, lat + 1 );
 
     FGBucket b_omit(550314L);
+    // FGBucket b(942698L);
     // FGBucket b(-146.248360, 61.133950);
     // construct_tile( work_base, output_base, b );
     // exit(0);
@@ -243,6 +245,11 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.17  1999/04/03 05:22:57  curt
+// Found a bug in dividing and adding unique verticle segments which could
+// cause the triangulator to end up in an infinite loop.  Basically the code
+// was correct, but the verticle line test was a bit to selective.
+//
 // Revision 1.16  1999/04/01 13:52:12  curt
 // Version 0.6.0
 // Shape name tweak.
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 6265237b0..6ce08c492 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -328,7 +328,7 @@ int FGTriangle::run_triangulate() {
     vorout.normlist = (REAL *) NULL;      // Needed only if -v switch used.
     
     // TEMPORARY
-    // write_out_data(&in);
+    write_out_data(&in);
 
     // Triangulate the points.  Switches are chosen to read and write
     // a PSLG (p), preserve the convex hull (c), number everything
@@ -343,7 +343,7 @@ int FGTriangle::run_triangulate() {
     triangulate(tri_options.c_str(), &in, &out, &vorout);
 
     // TEMPORARY
-    write_out_data(&out);
+    // write_out_data(&out);
 
     // now copy the results back into the corresponding FGTriangle
     // structures
@@ -398,6 +398,11 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.15  1999/04/03 05:22:58  curt
+// Found a bug in dividing and adding unique verticle segments which could
+// cause the triangulator to end up in an infinite loop.  Basically the code
+// was correct, but the verticle line test was a bit to selective.
+//
 // Revision 1.14  1999/03/31 23:47:09  curt
 // Debugging output tweaks.
 //
diff --git a/Triangulate/trisegs.cxx b/Triangulate/trisegs.cxx
index 1c1c386bf..d05c6ccf1 100644
--- a/Triangulate/trisegs.cxx
+++ b/Triangulate/trisegs.cxx
@@ -87,7 +87,7 @@ void FGTriSegments::unique_divide_and_add( const point_list& nodes,
     //   temp = true;
     // }
 
-    if ( fabs(p0.x() - p1.x()) > FG_EPSILON ) {
+    if ( fabs(p0.x() - p1.x()) > 3 * FG_EPSILON ) {
 	// use y = mx + b
 
 	// sort these in a sensable order
@@ -131,6 +131,8 @@ void FGTriSegments::unique_divide_and_add( const point_list& nodes,
     } else {
 	// use x = constant
 
+	// cout << "FOUND VERTICLE SEGMENT" << endl;
+
 	// sort these in a sensable order
 	if ( p0.y() > p1.y() ) {
 	    Point3D tmp = p0;
@@ -138,15 +140,22 @@ void FGTriSegments::unique_divide_and_add( const point_list& nodes,
 	    p1 = tmp;
 	}
 
+	// cout << " p0 = " << p0 << " p1 = " << p1 << endl;
+
 	current = nodes.begin();
 	last = nodes.end();
 	counter = 0;
 	for ( ; current != last; ++current ) {
 	    // cout << counter << endl;
-	    if ( (current->y() > p0.y()) && (current->y() < p1.y()) ) {
+	    if ( (current->y() > (p0.y() + FG_EPSILON))
+		 && (current->y() < (p1.y() - FG_EPSILON)) ) {
 		x_err = fabs(current->x() - p0.x());
+		// cout << "  found a potential point, x err = " 
+		//      << x_err << endl;
 		if ( x_err < 10*FG_EPSILON ) {
 		    cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
+		    cout << p0 << " < " << *current << " < "
+			 << p1 << endl;
 		    found_extra = true;
 		    extra_index = counter;
 		    break;
@@ -170,6 +179,11 @@ void FGTriSegments::unique_divide_and_add( const point_list& nodes,
 
 
 // $Log$
+// Revision 1.6  1999/04/03 05:22:59  curt
+// Found a bug in dividing and adding unique verticle segments which could
+// cause the triangulator to end up in an infinite loop.  Basically the code
+// was correct, but the verticle line test was a bit to selective.
+//
 // Revision 1.5  1999/03/29 13:11:13  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)

From 007bac3720e694fddde672b5ecbe2645ab2d1f2b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 5 Apr 1999 02:15:23 +0000
Subject: [PATCH 280/283] Make dem fitting more robust in cases when no dem
 file available.

---
 Array/array.cxx     | 77 ++++++++++++++++++++++++++++++++++-----------
 Array/array.hxx     | 10 ++++--
 Array/testarray.cxx |  2 +-
 3 files changed, 67 insertions(+), 22 deletions(-)

diff --git a/Array/array.cxx b/Array/array.cxx
index af1e32f7d..2b7d2a625 100644
--- a/Array/array.cxx
+++ b/Array/array.cxx
@@ -107,24 +107,55 @@ FGArray::close() {
 }
 
 
-// parse Array file
+// parse Array file, pass in the bucket so we can make up values when
+// the file wasn't found.
 int
-FGArray::parse() {
-    *in >> originx >> originy;
-    *in >> cols >> col_step;
-    *in >> rows >> row_step;
+FGArray::parse( FGBucket& b ) {
+    if ( in->is_open() ) {
+	// file open, parse
+	*in >> originx >> originy;
+	*in >> cols >> col_step;
+	*in >> rows >> row_step;
 
-    cout << "    origin  = " << originx << "  " << originy << endl;
-    cout << "    cols = " << cols << "  rows = " << rows << endl;
-    cout << "    col_step = " << col_step << "  row_step = " << row_step <<endl;
+	cout << "    origin  = " << originx << "  " << originy << endl;
+	cout << "    cols = " << cols << "  rows = " << rows << endl;
+	cout << "    col_step = " << col_step 
+	     << "  row_step = " << row_step <<endl;
 
-    for ( int i = 0; i < cols; i++ ) {
-	for ( int j = 0; j < rows; j++ ) {
-	    *in >> in_data[i][j];
+	for ( int i = 0; i < cols; i++ ) {
+	    for ( int j = 0; j < rows; j++ ) {
+		*in >> in_data[i][j];
+	    }
 	}
-    }
 
-    cout << "    Done parsing\n";
+	cout << "    Done parsing\n";
+    } else {
+	// file not open (not found?), fill with zero'd data
+
+	originx = ( b.get_center_lon() - 0.5 * b.get_width() ) * 3600.0;
+	originy = ( b.get_center_lat() - 0.5 * b.get_height() ) * 3600.0;
+
+	double max_x = ( b.get_center_lon() + 0.5 * b.get_width() ) * 3600.0;
+	double max_y = ( b.get_center_lat() + 0.5 * b.get_height() ) * 3600.0;
+
+	cols = 3;
+	col_step = (max_x - originx) / (cols - 1);
+	rows = 3;
+	row_step = (max_y - originy) / (rows - 1);
+
+	cout << "    origin  = " << originx << "  " << originy << endl;
+	cout << "    cols = " << cols << "  rows = " << rows << endl;
+	cout << "    col_step = " << col_step 
+	     << "  row_step = " << row_step <<endl;
+
+	for ( int i = 0; i < cols; i++ ) {
+	    for ( int j = 0; j < rows; j++ ) {
+		in_data[i][j] = 0.0;
+	    }
+	}
+
+	cout << "    File not open, so using zero'd data" << endl;
+    }
 
     return 1;
 }
@@ -132,9 +163,11 @@ FGArray::parse() {
 
 // add a node to the output corner node list
 void FGArray::add_corner_node( int i, int j, double val ) {
+    
     double x = (originx + i * col_step) / 3600.0;
     double y = (originy + j * row_step) / 3600.0;
-    // cout << Point3D(x, y, val) << endl;
+    // cout << "originx = " << originx << "  originy = " << originy << endl;
+    // cout << "corner = " << Point3D(x, y, val) << endl;
     corner_list.push_back( Point3D(x, y, val) );
 }
 
@@ -148,8 +181,9 @@ void FGArray::add_fit_node( int i, int j, double val ) {
 }
 
 
-// Use least squares to fit a simpler data set to dem data
-void FGArray::fit( double error ) {
+// Use least squares to fit a simpler data set to dem data.  Return
+// the number of fitted nodes
+int FGArray::fit( double error ) {
     double x[ARRAY_SIZE_1], y[ARRAY_SIZE_1];
     double m, b, max_error, error_sq;
     double x1, y1;
@@ -162,8 +196,9 @@ void FGArray::fit( double error ) {
 
     error_sq = error * error;
 
-    cout << "  Initializing output mesh structure" << endl;
-    // outputmesh_init();
+    cout << "  Initializing fitted node list" << endl;
+    corner_list.clear();
+    node_list.clear();
 
     // determine dimensions
     colmin = 0;
@@ -297,6 +332,9 @@ void FGArray::fit( double error ) {
     }
 
     // outputmesh_output_nodes(fg_root, p);
+
+    // return fit nodes + 4 corners
+    return node_list.size() + 4;
 }
 
 
@@ -539,6 +577,9 @@ FGArray::~FGArray( void ) {
 
 
 // $Log$
+// Revision 1.8  1999/04/05 02:15:23  curt
+// Make dem fitting more robust in cases when no dem file available.
+//
 // Revision 1.7  1999/03/27 14:05:10  curt
 // More sensible handling of the case where no dem file for this tile exists
 // (or has been generated).
diff --git a/Array/array.hxx b/Array/array.hxx
index 601d0fb56..2ec9e2a51 100644
--- a/Array/array.hxx
+++ b/Array/array.hxx
@@ -89,10 +89,11 @@ public:
     int close();
 
     // parse a Array file
-    int parse();
+    int parse( FGBucket& b );
 
-    // Use least squares to fit a simpler data set to dem data
-    void fit( double error );
+    // Use least squares to fit a simpler data set to dem data.
+    // Return the number of fitted nodes
+    int fit( double error );
 
     // add a node to the output corner node list
     void add_corner_node( int i, int j, double val );
@@ -122,6 +123,9 @@ public:
 
 
 // $Log$
+// Revision 1.6  1999/04/05 02:15:24  curt
+// Make dem fitting more robust in cases when no dem file available.
+//
 // Revision 1.5  1999/03/29 13:11:02  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)
diff --git a/Array/testarray.cxx b/Array/testarray.cxx
index 74012eb93..1a0a4d55c 100644
--- a/Array/testarray.cxx
+++ b/Array/testarray.cxx
@@ -23,7 +23,7 @@ main(int argc, char **argv) {
     cout << "arrayfile = " << arrayfile << endl;
     
     FGArray a(arrayfile);
-    a.parse();
+    a.parse( b );
 
     lon *= 3600;
     lat *= 3600;

From 773d67b82328338594f023a750bbaa3e9b8059e6 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 5 Apr 1999 02:16:02 +0000
Subject: [PATCH 281/283] Fixed a compiler warning.

---
 Combine/genfans.cxx | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Combine/genfans.cxx b/Combine/genfans.cxx
index 57aa05f46..856a3d79c 100644
--- a/Combine/genfans.cxx
+++ b/Combine/genfans.cxx
@@ -68,7 +68,8 @@ static int_list make_best_fan( const triele_list& master_tris,
 {
     int_list best_result;
 
-    // try starting with local triangle to find the best fan arrangement
+    // try starting with each of local_tris to find the best fan
+    // arrangement
     for ( int start = 0; start < (int)local_tris.size(); ++start ) {
 	// cout << "trying with first triangle = " << local_tris[start] << endl;
 
@@ -138,6 +139,7 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
     fans.clear();
 
     while ( ! tris.empty() ) {
+	// cout << "building reverse_list" << endl;
 	reverse_list by_node;
 	by_node.clear();
 
@@ -157,6 +159,8 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	// find the node in the tris list that attaches to the most
 	// triangles
 
+	// cout << "find most connected node" << endl;
+
 	int_list biggest_group;
 	reverse_list_iterator r_current = by_node.begin();
 	reverse_list_iterator r_last = by_node.end();
@@ -174,7 +178,9 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 	// cout << "center node = " << index << endl;
 
 	// make the best fan we can out of this group
+	// cout << "before make_best_fan()" << endl;
 	int_list best_fan = make_best_fan( tris, index, biggest_group );
+	// cout << "after make_best_fan()" << endl;
 
 	// generate point form of best_fan
 	int_list node_list;
@@ -225,7 +231,7 @@ fan_list FGGenFans::greedy_build( triele_list tris ) {
 
 // report average fan size
 double FGGenFans::ave_size() {
-    double sum;
+    double sum = 0.0;
 
     fan_list_iterator current = fans.begin();
     fan_list_iterator last = fans.end();
@@ -238,6 +244,9 @@ double FGGenFans::ave_size() {
 
 
 // $Log$
+// Revision 1.6  1999/04/05 02:16:02  curt
+// Fixed a compiler warning.
+//
 // Revision 1.5  1999/03/31 23:46:49  curt
 // Debugging output tweaks.
 //

From b18c82c33b658dc912fac24d1a6ec92049d8a5a4 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 5 Apr 1999 02:16:51 +0000
Subject: [PATCH 282/283] Dynamically update "error" until the resulting tile
 data scales within a lower and upper bounds.

---
 Main/construct.cxx       | 83 +++++++++++++++++++++++++++++++++-------
 Triangulate/triangle.cxx | 15 +++++++-
 Triangulate/triangle.hxx |  5 +++
 Triangulate/trinodes.hxx | 10 +++++
 Triangulate/trisegs.hxx  |  7 ++++
 5 files changed, 105 insertions(+), 15 deletions(-)

diff --git a/Main/construct.cxx b/Main/construct.cxx
index 85227747b..1c5c117a9 100644
--- a/Main/construct.cxx
+++ b/Main/construct.cxx
@@ -26,6 +26,7 @@
 #include <dirent.h>     // for directory reading
 
 #include <Bucket/newbucket.hxx>
+#include <Include/fg_constants.h>
 
 #include <Debug/logstream.hxx>
 #include <Array/array.hxx>
@@ -46,15 +47,18 @@ int load_dem(const string& work_base, FGBucket& b, FGArray& array) {
 
     if ( ! array.open(dem_path) ) {
 	cout << "ERROR: cannot open " << dem_path << endl;
-	return 0;
     }
 
-    array.parse();
-    array.fit( 200 );
+    array.parse( b );
 
     return 1;
 }
 
+// fit dem nodes, return number of fitted nodes
+int fit_dem(FGArray& array, int error) {
+    return array.fit( error );
+}
+
 
 // do actual scan of directory and loading of files
 int actual_load_polys( const string& dir, FGBucket& b, FGClipper& clipper ) {
@@ -165,17 +169,65 @@ void construct_tile( const string& work_base, const string& output_base,
 {
     cout << "Construct tile, bucket = " << b << endl;
 
+    // fit with ever increasing error tolerance until we produce <=
+    // 80% of max nodes.  We should really have the sim end handle
+    // arbitrarily complex tiles.
+
+    const int min_nodes = 50;
+    const int max_nodes = (int)(MAX_NODES * 0.8);
+
+    bool acceptable = false;
+    double error = 200.0;
+    int count = 0;
+
     // load and fit grid of elevation data
     FGArray array;
     load_dem( work_base, b, array );
 
-    // load and clip 2d polygon data
-    FGClipper clipper;
-    load_polys( work_base, b, clipper );
-
-    // triangulate the data for each polygon
     FGTriangle t;
-    do_triangulate( array, clipper, t );
+
+    while ( ! acceptable ) {
+	// fit the data
+	array.fit( error );
+
+	// load and clip 2d polygon data
+	FGClipper clipper;
+	load_polys( work_base, b, clipper );
+
+	// triangulate the data for each polygon
+	do_triangulate( array, clipper, t );
+
+	acceptable = true;
+
+	count = t.get_out_nodes_size();
+
+	if ( (count < min_nodes) && (error >= 25.0) ) {
+	    // reduce error tolerance until number of points exceeds the
+	    // minimum threshold
+	    cout << "produced too few nodes ..." << endl;
+
+	    acceptable = false;
+
+	    error /= 1.5;
+	    cout << "Setting error to " << error << " and retrying fit." 
+		 << endl;
+	}
+
+	if ( (count > max_nodes) && (error <= 1000.0) ) {
+	    // increase error tolerance until number of points drops below
+	    // the maximum threshold
+	    cout << "produced too many nodes ..." << endl;
+	    
+	    acceptable = false;
+
+	    error *= 1.5;
+	    cout << "Setting error to " << error << " and retrying fit." 
+		 << endl;
+	}
+    }
+
+    cout << "finished fit with error = " << error << " node count = " 
+	 << count << endl;
 
     // generate the output
     FGGenOutput output;
@@ -207,15 +259,16 @@ main(int argc, char **argv) {
     // lon = -90.757128; lat = 46.790212;      // WI32
     // lon = -122.220717; lat = 37.721291;     // KOAK
     // lon = -111.721477; lat = 40.215641;     // KPVU
-    lon = -122.309313; lat = 47.448982;     // KSEA
+    // lon = -122.309313; lat = 47.448982;     // KSEA
+    lon = -148.798131; lat = 63.645099;     // AK06 (Danali, AK)
 
-    double min_x = lon - 1;
+    double min_x = lon - 3;
     double min_y = lat - 1;
     FGBucket b_min( min_x, min_y );
-    FGBucket b_max( lon + 1, lat + 1 );
+    FGBucket b_max( lon + 3, lat + 1 );
 
     FGBucket b_omit(550314L);
-    // FGBucket b(942698L);
+    // FGBucket b(517745L);
     // FGBucket b(-146.248360, 61.133950);
     // construct_tile( work_base, output_base, b );
     // exit(0);
@@ -245,6 +298,10 @@ main(int argc, char **argv) {
 
 
 // $Log$
+// Revision 1.18  1999/04/05 02:16:51  curt
+// Dynamically update "error" until the resulting tile data scales within
+// a lower and upper bounds.
+//
 // Revision 1.17  1999/04/03 05:22:57  curt
 // Found a bug in dividing and adding unique verticle segments which could
 // cause the triangulator to end up in an infinite loop.  Basically the code
diff --git a/Triangulate/triangle.cxx b/Triangulate/triangle.cxx
index 6ce08c492..38b8bf1ac 100644
--- a/Triangulate/triangle.cxx
+++ b/Triangulate/triangle.cxx
@@ -44,6 +44,9 @@ FGTriangle::build( const point_list& corner_list,
     FGTriPoly poly;
     int index;
 
+    in_nodes.clear();
+    trisegs.clear();
+
     // Point3D junkp;
     // int junkc = 0;
     // char junkn[256];
@@ -70,6 +73,8 @@ FGTriangle::build( const point_list& corner_list,
     cout << "prepairing node list and polygons" << endl;
 
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
+	polylist[i].clear();
+
 	// cout << "area type = " << i << endl;
 	current = gpc_polys.polys[i].begin();
 	last = gpc_polys.polys[i].end();
@@ -328,7 +333,7 @@ int FGTriangle::run_triangulate() {
     vorout.normlist = (REAL *) NULL;      // Needed only if -v switch used.
     
     // TEMPORARY
-    write_out_data(&in);
+    // write_out_data(&in);
 
     // Triangulate the points.  Switches are chosen to read and write
     // a PSLG (p), preserve the convex hull (c), number everything
@@ -343,12 +348,13 @@ int FGTriangle::run_triangulate() {
     triangulate(tri_options.c_str(), &in, &out, &vorout);
 
     // TEMPORARY
-    // write_out_data(&out);
+    write_out_data(&out);
 
     // now copy the results back into the corresponding FGTriangle
     // structures
 
     // nodes
+    out_nodes.clear();
     for ( int i = 0; i < out.numberofpoints; i++ ) {
 	Point3D p( out.pointlist[2*i], out.pointlist[2*i + 1], 0.0 );
 	// cout << "point = " << p << endl;
@@ -356,6 +362,7 @@ int FGTriangle::run_triangulate() {
     }
 
     // triangles
+    elelist.clear();
     int n1, n2, n3;
     double attribute;
     for ( int i = 0; i < out.numberoftriangles; i++ ) {
@@ -398,6 +405,10 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.16  1999/04/05 02:17:11  curt
+// Dynamically update "error" until the resulting tile data scales within
+// a lower and upper bounds.
+//
 // Revision 1.15  1999/04/03 05:22:58  curt
 // Found a bug in dividing and adding unique verticle segments which could
 // cause the triangulator to end up in an infinite loop.  Basically the code
diff --git a/Triangulate/triangle.hxx b/Triangulate/triangle.hxx
index b561bd2c1..676f5056c 100644
--- a/Triangulate/triangle.hxx
+++ b/Triangulate/triangle.hxx
@@ -84,6 +84,7 @@ public:
     int run_triangulate();
 
     inline FGTriNodes get_out_nodes() const { return out_nodes; }
+    inline size_t get_out_nodes_size() const { return out_nodes.size(); }
     inline triele_list get_elelist() const { return elelist; }
 };
 
@@ -92,6 +93,10 @@ public:
 
 
 // $Log$
+// Revision 1.11  1999/04/05 02:17:12  curt
+// Dynamically update "error" until the resulting tile data scales within
+// a lower and upper bounds.
+//
 // Revision 1.10  1999/03/29 13:11:08  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)
diff --git a/Triangulate/trinodes.hxx b/Triangulate/trinodes.hxx
index 6b05a42df..f7c5fdd55 100644
--- a/Triangulate/trinodes.hxx
+++ b/Triangulate/trinodes.hxx
@@ -62,6 +62,9 @@ public:
     FGTriNodes( void );
     ~FGTriNodes( void );
 
+    // delete all the data out of node_list
+    inline void clear() { node_list.clear(); }
+
     // Add a point to the point list if it doesn't already exist.
     // Returns the index (starting at zero) of the point in the list.
     int unique_add( const Point3D& p );
@@ -79,6 +82,9 @@ public:
 
     // return the ith point
     inline Point3D get_node( int i ) const { return node_list[i]; }
+
+    // return the size of the node list
+    inline size_t size() const { return node_list.size(); }
 };
 
 
@@ -112,6 +118,10 @@ inline bool FGTriNodes::course_close_enough( const Point3D& p1,
 
 
 // $Log$
+// Revision 1.8  1999/04/05 02:17:13  curt
+// Dynamically update "error" until the resulting tile data scales within
+// a lower and upper bounds.
+//
 // Revision 1.7  1999/03/29 13:11:10  curt
 // Shuffled stl type names a bit.
 // Began adding support for tri-fanning (or maybe other arrangments too.)
diff --git a/Triangulate/trisegs.hxx b/Triangulate/trisegs.hxx
index 09fd5b921..2766bcf15 100644
--- a/Triangulate/trisegs.hxx
+++ b/Triangulate/trisegs.hxx
@@ -93,6 +93,9 @@ public:
     FGTriSegments( void );
     ~FGTriSegments( void );
 
+    // delete all the data out of seg_list
+    inline void clear() { seg_list.clear(); }
+
     // Add a segment to the segment list if it doesn't already exist.
     // Returns the index (starting at zero) of the segment in the
     // list.
@@ -115,6 +118,10 @@ public:
 
 
 // $Log$
+// Revision 1.4  1999/04/05 02:17:14  curt
+// Dynamically update "error" until the resulting tile data scales within
+// a lower and upper bounds.
+//
 // Revision 1.3  1999/03/27 05:30:18  curt
 // Handle corner nodes separately from the rest of the fitted nodes.
 // Add fitted nodes in after corners and polygon nodes since the fitted nodes

From 4c3f4116ac1c6288faf1494080eb8f2daa7e7b5f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 5 Apr 1999 02:20:53 +0000
Subject: [PATCH 283/283] Don't build showme if no X11.

---
 Triangle/Makefile.am | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Triangle/Makefile.am b/Triangle/Makefile.am
index 17f6825cd..caa86591b 100644
--- a/Triangle/Makefile.am
+++ b/Triangle/Makefile.am
@@ -15,6 +15,10 @@ noinst_LIBRARIES = libTriangle.a
 
 libTriangle_a_SOURCES = triangle.c triangle.h
 
+if HAVE_XWINDOWS
+
 bin_PROGRAMS = showme
 showme_SOURCES = showme.c
 showme_LDADD = -lX11
+
+endif
\ No newline at end of file