From 528c12a6827e1949b2609b63fe1154959e8c3e2f Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 29 Jan 2001 04:30:31 +0000
Subject: [PATCH] These add a --min-angle options to fgfs-tools-client, and
 make the E00 support a lot more robust.

---
 src/BuildTiles/Parallel/client.cxx |  12 +-
 src/Lib/Polygon/names.cxx          |   1 +
 src/Lib/Polygon/names.hxx          |   1 +
 src/Lib/e00/Makefile.am            |   6 +-
 src/Lib/e00/e00.cxx                | 437 +++++++++++----------
 src/Lib/e00/e00.hxx                | 332 ++++++++--------
 src/Lib/e00/teste00.cxx            |  42 ++-
 src/Prep/E00Lines/Makefile.am      |   2 +-
 src/Prep/E00Lines/main.cxx         | 586 ++++++++++++++++++++++++++---
 9 files changed, 1013 insertions(+), 406 deletions(-)

diff --git a/src/BuildTiles/Parallel/client.cxx b/src/BuildTiles/Parallel/client.cxx
index 855ce6f6..46ea04b3 100644
--- a/src/BuildTiles/Parallel/client.cxx
+++ b/src/BuildTiles/Parallel/client.cxx
@@ -175,8 +175,8 @@ long int get_next_task( const string& host, int port, long int last_tile ) {
 // successfully
 bool construct_tile( const SGBucket& b,
 		     const string& result_file,
-		     const string &cover ) {
-    double angle = 10.0;
+		     const string &cover,
+		     float angle ) {
     bool still_trying = true;
 
     while ( still_trying ) {
@@ -216,6 +216,9 @@ bool construct_tile( const SGBucket& b,
 		    angle = 5.0;
 		    still_trying = true;
 		} else if ( angle > 4.0 ) {
+		    angle = 1.0;
+		    still_trying = true;
+		} else if ( angle > 0.0 ) {
 		    angle = 0.0;
 		    still_trying = true;
 		}
@@ -257,6 +260,7 @@ int main(int argc, char *argv[]) {
     string cover;
     string host = "127.0.0.1";
     int port=4001;
+    float angle = 10.0;
 
     //
     // Parse the command-line arguments.
@@ -277,6 +281,8 @@ int main(int argc, char *argv[]) {
 	rude = true;
       } else if (arg.find("--cover=") == 0) {
 	cover = arg.substr(8);
+      } else if (arg.find("--min-angle=") == 0) {
+	angle = atof(arg.substr(12).c_str());
       } else if (arg.find("--") == 0) {
 	usage(argv[0]);
       } else {
@@ -315,7 +321,7 @@ int main(int argc, char *argv[]) {
     check_master_switch();
 
     while ( (tile = get_next_task( host, port, last_tile )) >= 0 ) {
-	result = construct_tile( SGBucket(tile), result_file, cover );
+	result = construct_tile( SGBucket(tile), result_file, cover, angle );
 	if ( result ) {
 	    last_tile = tile;
 	} else {
diff --git a/src/Lib/Polygon/names.cxx b/src/Lib/Polygon/names.cxx
index 41f8eb97..25832f3c 100644
--- a/src/Lib/Polygon/names.cxx
+++ b/src/Lib/Polygon/names.cxx
@@ -70,6 +70,7 @@ inline static void init ()
   set_area("Reservoir", ReservoirArea);
   set_area("Reservoir   Intermittent", IntReservoirArea);
   set_area("IntermittentReservoir", IntReservoirArea);
+  set_area("Freeway", FreewayArea);
   set_area("Road", RoadArea);
   set_area("Railroad", RailroadArea);
   set_area("Stream", StreamArea);
diff --git a/src/Lib/Polygon/names.hxx b/src/Lib/Polygon/names.hxx
index d623fc98..8fadfee6 100644
--- a/src/Lib/Polygon/names.hxx
+++ b/src/Lib/Polygon/names.hxx
@@ -44,6 +44,7 @@ enum AreaType {
     IntLakeArea,
     ReservoirArea,
     IntReservoirArea,
+    FreewayArea,
     RoadArea,
     RailroadArea,
     StreamArea,
diff --git a/src/Lib/e00/Makefile.am b/src/Lib/e00/Makefile.am
index 25e97f1e..d3b241bf 100644
--- a/src/Lib/e00/Makefile.am
+++ b/src/Lib/e00/Makefile.am
@@ -5,6 +5,8 @@ libe00_a_SOURCES = e00.cxx e00.hxx
 noinst_PROGRAMS = teste00
 
 teste00_SOURCES = teste00.cxx
-teste00_LDADD = libe00.a
-
+teste00_LDADD = libe00.a -lsgmisc -lz
 
+INCLUDES += \
+	-I$(top_srcdir)/src \
+	-I$(top_srcdir)/src/Lib
diff --git a/src/Lib/e00/e00.cxx b/src/Lib/e00/e00.cxx
index cbf66ce4..2780d978 100644
--- a/src/Lib/e00/e00.cxx
+++ b/src/Lib/e00/e00.cxx
@@ -39,22 +39,25 @@ append (string &s, double f)
 }
 
 static void
-skipWhitespace (istream &input)
+skipNewlines (istream &input)
 {
   char c;
   input.get(c);
-  while (isspace(c)) {
+//   while (isspace(c)) {
+//     input.get(c);
+//   }
+  while (c == '\n' || c == '\r') {
     input.get(c);
   }
   input.putback(c);
 }
 
 static void
-readStringItem (istream &input, string &line, int width)
+readItem (istream &input, string &line, int width)
 {
   char c;
   
-  skipWhitespace(input);
+  skipNewlines(input);
   line.resize(0);
   
   for (int i = 0; i < width; i++) {
@@ -89,6 +92,43 @@ checkZeros (istream &input)
 }
 
 
+static void
+expect (istream &input, int i)
+{
+  int in;
+  input >> in;
+  if (in != i) {
+    string message = "Expected ";
+    append(message, i);
+    throw E00Exception(message.c_str());
+  }
+}
+
+static void
+expect (istream &input, double f)
+{
+  double in;
+  input >> in;
+  if (in != f) {
+    string message = "Expected ";
+    append(message, f);
+    throw E00Exception(message.c_str());
+  }
+}
+
+static void
+expect (istream &input, const char *s)
+{
+  string in;
+  input >> in;
+  if (in != s) {
+    string message = "Expected ";
+    message += s;
+    throw E00Exception(message.c_str());
+  }
+}
+
+
 
 ////////////////////////////////////////////////////////////////////////
 // Implementation of E00
@@ -105,136 +145,6 @@ E00::~E00 ()
 }
 
 
-void
-E00::expect (int i)
-{
-  int in;
-  *_input >> in;
-  if (in != i) {
-    string message = "Expected ";
-    append(message, i);
-    throw E00Exception(message.c_str());
-  }
-}
-
-void
-E00::expect (double f)
-{
-  double in;
-  *_input >> in;
-  if (in != f) {
-    string message = "Expected ";
-    append(message, f);
-    throw E00Exception(message.c_str());
-  }
-}
-
-void
-E00::expect (const char * s)
-{
-  string in;
-  *_input >> in;
-  if (in != s) {
-    string message = "Expected ";
-    message += s;
-    throw E00Exception(message.c_str());
-  }
-}
-
-
-
-////////////////////////////////////////////////////////////////////////
-// XML output.
-////////////////////////////////////////////////////////////////////////
-
-static void
-writeVertex (ostream &output, double x, double y)
-{
-  output << "<v x=\"" << x << "\" y=\"" << y << "\"/>" << endl;
-}
-
-void
-E00::write (ostream &output) const
-{
-  int i, j, k;
-
-  output << "<?xml version=\"1.0\"?>" << endl << endl;
-  output << "<GIS>" << endl << endl;
-
-  if (arc_section.size() == 0) {
-    for (int i = 0; i < (int)lab_section.size(); i++) {
-      output << "<point>" << endl;
-      writeVertex(output, lab_section[i].coord.x, lab_section[i].coord.y);
-      output << "</point>" << endl << endl;
-    }
-  }
-
-  for ( i = 0; i < (int)arc_section.size(); i++) {
-    const e00ARC &arc = arc_section[i];
-    if (!arc.inPolygon) {
-      output << "<line>" << endl;
-      for ( j = 0; j < (int)arc.coordinates.size(); j++) {
-	writeVertex(output, arc.coordinates[j].x, arc.coordinates[j].y);
-      }
-      output << "</line>" << endl << endl;;
-    }
-  }
-
-				// NB: skip enclosing poly
-  for ( i = 1; i < (int)pal_section.size(); i++) {
-    const e00PAL &pal = pal_section[i];
-    output << "<polygon>" << endl;
-    for ( j = 0; j < pal.numArcs; j++) {
-      bool isReversed = false;
-      int arcNum = pal.arcs[j].arcNum;
-      if (arcNum < 0) {
-	arcNum = 0 - arcNum;
-	isReversed = true;
-      }
-      const e00ARC &arc = arc_section[arcNum];
-      output << "<arc coverage=\"" << arc.coverageId << "\">" << endl;
-      if (isReversed) {
-	for ( k = arc.numberOfCoordinates - 1; k >= 0; k--) {
-	  writeVertex(output, arc.coordinates[k].x, arc.coordinates[k].y);
-	}
-      } else {
-	for ( k = 0; k < arc.numberOfCoordinates; k++) {
-	  writeVertex(output, arc.coordinates[k].x, arc.coordinates[k].y);
-	}
-      }
-      output << "</arc>" << endl;
-    }
-    output << "</polygon>" << endl << endl;
-  }
-
-  output << "</GIS>" << endl;
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////
-// Public query methods.
-////////////////////////////////////////////////////////////////////////
-
-int
-E00::nPoints () const
-{
-  return lab_section.size();
-}
-
-int
-E00::nLines () const
-{
-  return lineArcs.size();
-}
-
-int
-E00::nPolygons () const
-{
-  return pal_section.size();
-}
 
 
 
@@ -255,6 +165,7 @@ E00::readE00 (istream &input)
 
     *_input >> token;
 
+    cerr << "Reading " << token << " section" << endl;
     if (token == "ARC") {
       readARC();
     } else if (token == "CNT") {
@@ -273,6 +184,14 @@ E00::readE00 (istream &input)
       readTOL();
     } else if (token == "IFO") {
       readIFO();
+    } else if (token == "TX6") {
+      readTX6();
+    } else if (token == "TX7") {
+      readTX7();
+    } else if (token == "RXP") {
+      readRXP();
+    } else if (token == "RPL") {
+      readRPL();
     } else if (token == "EOS") {
       postProcess();
       return;
@@ -283,6 +202,7 @@ E00::readE00 (istream &input)
   }
 
   throw E00Exception("File ended without EOS line");
+  _input = 0;
 }
 
 
@@ -292,8 +212,8 @@ E00::readE00 (istream &input)
 void
 E00::readHeader ()
 {
-  expect("EXP");
-  expect(0);
+  expect(*_input, "EXP");
+  expect(*_input, 0);
   *_input >> pathName;
 }
 
@@ -304,14 +224,12 @@ E00::readHeader ()
 void
 E00::readARC ()
 {
-  e00ARC arc;
-  e00Coord coord;
+  ARC arc;
+  Coord coord;
 
   checkPrecision(*_input);
-
   *_input >> arc.coverageNum;
   while (arc.coverageNum != -1) {
-    arc.inPolygon = false;
     *_input >> arc.coverageId;
     *_input >> arc.fromNode;
     *_input >> arc.toNode;
@@ -324,6 +242,7 @@ E00::readARC ()
       *_input >> coord.y;
       arc.coordinates.push_back(coord);
     }
+    arc.in_polygon = false;	// we'll check later
     arc_section.push_back(arc);
     *_input >> arc.coverageNum;
   }
@@ -338,14 +257,16 @@ E00::readARC ()
 void
 E00::readCNT ()
 {
-  e00CNT cnt;
+  int numLabels;
   int label;
 
   checkPrecision(*_input);
 
-  *_input >> cnt.numLabels;
+  *_input >> numLabels;
 
-  while (cnt.numLabels != -1) {
+  while (numLabels != -1) {
+    CNT cnt;
+    cnt.numLabels = numLabels;
     *_input >> cnt.centroid.x;
     *_input >> cnt.centroid.y;
     for (int i = 0; i < cnt.numLabels; i++) {
@@ -353,7 +274,7 @@ E00::readCNT ()
       cnt.labels.push_back(label);
     }
     cnt_section.push_back(cnt);
-    *_input >> cnt.numLabels;
+    *_input >> numLabels;
   }
 
   checkZeros(*_input);
@@ -363,7 +284,7 @@ E00::readCNT ()
 void
 E00::readLAB ()
 {
-  e00LAB lab;
+  LAB lab;
 
   checkPrecision(*_input);
   *_input >> lab.coverageId;
@@ -387,7 +308,7 @@ E00::readLAB ()
 void
 E00::readLOG ()
 {
-  e00LOG log;
+  LOG log;
   string line;
 
   checkPrecision(*_input);
@@ -409,8 +330,9 @@ E00::readLOG ()
 void
 E00::readPAL ()
 {
-  e00PAL pal;
-  e00PAL::ARC arc;
+  PAL pal;
+  PAL::ARCref arc;
+  int count = 1;
 
   checkPrecision(*_input);
   *_input >> pal.numArcs;
@@ -422,6 +344,19 @@ E00::readPAL ()
     pal.arcs.resize(0);
     for (int i = 0; i < pal.numArcs; i++) {
       *_input >> arc.arcNum;
+      if (count > 1) {
+	if (arc.arcNum > 0)
+	  _getARC(arc.arcNum).in_polygon = true;
+	else
+	  _getARC(0-arc.arcNum).in_polygon = true;
+      }
+      int num = (arc.arcNum < 0 ? 0 - arc.arcNum : arc.arcNum);
+      if (num != 0 &&
+	  getARC(num).leftPolygon != count &&
+	  getARC(num).rightPolygon != count) {
+	cerr << "Polygon " << count << " includes arc " << num
+	     << " which doesn't reference it" << endl;
+      }
       *_input >> arc.nodeNum;
       *_input >> arc.polygonNum;
       pal.arcs.push_back(arc);
@@ -429,6 +364,7 @@ E00::readPAL ()
 
     pal_section.push_back(pal);
     *_input >> pal.numArcs;
+    count++;
   }
 
   checkZeros(*_input);
@@ -438,7 +374,7 @@ E00::readPAL ()
 void
 E00::readPRJ ()
 {
-  e00PRJ prj;
+  PRJ prj;
   string line;
 
   checkPrecision(*_input);
@@ -472,7 +408,7 @@ E00::readSIN ()
 void
 E00::readTOL ()
 {
-  e00TOL tol;
+  TOL tol;
 
   checkPrecision(*_input);
   *_input >> tol.type;
@@ -487,20 +423,68 @@ E00::readTOL ()
 }
 
 
+void
+E00::readTX6 ()
+{
+  string dummy;
+  *_input >> dummy;
+				// FIXME: will fail if "JABBERWOCKY" appears
+				// in the text annotation itself
+  while (dummy != "JABBERWOCKY")
+    *_input >> dummy;
+}
+
+
+void
+E00::readTX7 ()
+{
+  string dummy;
+  *_input >> dummy;
+				// FIXME: will fail if "JABBERWOCKY" appears
+				// in the text annotation itself
+  while (dummy != "JABBERWOCKY")
+    *_input >> dummy;
+}
+
+void
+E00::readRXP ()
+{
+  string dummy;
+  *_input >> dummy;
+				// FIXME: will fail if "JABBERWOCKY" appears
+				// in the text annotation itself
+  while (dummy != "JABBERWOCKY")
+    *_input >> dummy;
+}
+
+void
+E00::readRPL ()
+{
+  string dummy;
+  *_input >> dummy;
+				// FIXME: will fail if "JABBERWOCKY" appears
+				// in the text annotation itself
+  while (dummy != "JABBERWOCKY")
+    *_input >> dummy;
+}
+
+
 void
 E00::readIFO ()
 {
-  e00IFO ifo;
-  e00IFO::ItemDef def;
-  e00IFO::Entry entry;
-  string line;
+  string line = "";
   int intval;
   double realval;
 
   checkPrecision(*_input);
 
-  *_input >> ifo.fileName;
-  while (ifo.fileName.find("EOI") != 0) {
+  while (line == "")
+    *_input >> line;
+  while (line != string("EOI")) {
+
+    IFO ifo;
+    IFO::Entry entry;
+    ifo.fileName = line;
 
 				// 'XX' may be absent
     *_input >> ifo.isArcInfo;
@@ -517,19 +501,21 @@ E00::readIFO ()
 				// Read the item definitions
     ifo.defs.resize(0);
     for (int i = 0; i < ifo.numItems; i++) {
+      IFO::ItemDef def;
+
       *_input >> def.itemName;
       *_input >> def.itemWidth;
-      expect(-1);
+      expect(*_input, -1);
       *_input >> def.itemStartPos;
-      expect(-1);
+      expect(*_input, -1);
       def.itemStartPos -= 4;
       def.itemStartPos /= 10;
       *_input >> def.itemOutputFormat[0];
       *_input >> def.itemOutputFormat[1];
       *_input >> def.itemType;
-      expect(-1);
-      expect(-1);
-      expect(-1);
+      expect(*_input, -1);
+      expect(*_input, -1);
+      expect(*_input, -1);
       *_input >> def.seqId;
       ifo.defs.push_back(def);
       getline(*_input, line);
@@ -542,18 +528,51 @@ E00::readIFO ()
       for (int j = 0; j < ifo.numItems; j++) {
 	line.resize(0);
 	string &type = ifo.defs[j].itemType;
-	if (type == "20-1") {	// character field
-	  readStringItem(*_input, line, ifo.defs[j].itemOutputFormat[0]);
-	} else if (type == "50-1") { // integer
-	  *_input >> intval;
-	  append(line, intval);
-	} else if (type == "60-1") { // real number
-	  *_input >> realval;
-	  append(line, realval);
-	} else {		// assume integer
-	  cerr << "Unknown IFO item type '30-1': assuming integer" << endl;
-	  *_input >> intval;
-	  append(line, intval);
+
+	if (type == "10-1") {	// date
+	  readItem(*_input, line, 8);
+	}
+
+	else if (type == "20-1") {	// character field
+	  readItem(*_input, line, ifo.defs[j].itemOutputFormat[0]);
+	} 
+
+	else if (type == "30-1") { // fixed-width integer
+	  readItem(*_input, line, ifo.defs[j].itemOutputFormat[0]);
+	} 
+
+	else if (type == "40-1") { // single-precision float
+	  readItem(*_input, line, 14);
+	}
+
+	else if (type == "50-1") { // integer
+	  if (ifo.defs[j].itemWidth == 2) {
+	    readItem(*_input, line, 6);
+	  } else if (ifo.defs[j].itemWidth == 4) {
+	    readItem(*_input, line, 11);
+	  } else {
+	    cerr << "Unexpected width " << ifo.defs[j].itemWidth
+		 << " for item of type 50-1" << endl;
+	    exit(1);
+	  }
+	} 
+
+	else if (type == "60-1") { // real number
+	  if (ifo.defs[j].itemWidth == 4) {
+	    readItem(*_input, line, 14);
+	  } else if (ifo.defs[j].itemWidth == 8) {
+	    readItem(*_input, line, 24);
+	  } else {
+	    cerr << "Unexpected width " << ifo.defs[j].itemWidth
+		 << " for item of type 60-1" << endl;
+	    exit(1);
+	  }
+	} 
+
+	else {		// assume integer
+	  cerr << "Unknown IFO item type " << type
+	       << " assuming integer" << endl;
+	  exit(1);
 	}
 	entry.push_back(line);
       }
@@ -561,7 +580,9 @@ E00::readIFO ()
     }
 
     ifo_section.push_back(ifo);
-    *_input >> ifo.fileName;
+    line = "";
+    while (line == "")
+      *_input >> line;
   }
 }
 
@@ -580,31 +601,59 @@ E00::readUnknown ()
 void
 E00::postProcess ()
 {
+  // TODO
+}
 
-				// Flag the arcs so that we know what is
-				// and isn't part of a polygon.
-  for (int i = 0; i < (int)pal_section.size(); i++) {
-    e00PAL &pal = pal_section[i];
-    for (int j = 0; j < (int)pal.arcs.size(); j++) {
-      int arcNum = pal.arcs[j].arcNum;
-      if (arcNum >= (int)arc_section.size()) {
-	cerr << "Polygon includes non-existent arc " << arcNum << endl;
-      } else {
-	arc_section[arcNum].inPolygon = true;
-      }
-    }
+
+
+////////////////////////////////////////////////////////////////////////
+// Other access methods.
+////////////////////////////////////////////////////////////////////////
+
+const E00::IFO *
+E00::getIFO (const string &fileName) const
+{
+  for (int i = 0; i < ifo_section.size(); i++) {
+    if (ifo_section[i].fileName == fileName)
+      return &(ifo_section[i]);
+  }
+  return 0;
+}
+
+const string *
+E00::getIFOItem (const string &fileName, int entry,
+		 const string &itemName) const
+{
+  const IFO * ifo = getIFO(fileName);
+  if (ifo == 0)
+    return 0;
+
+  int pos = -1;
+  for (int i = 0; i < ifo->defs.size(); i++) {
+    if (ifo->defs[i].itemName == itemName)
+      pos = i;
   }
 
-				// Now, check which arcs aren't flagged
-				// and assign them to the appropriate
-				// lists.
-  for (int i = 0; i < (int)arc_section.size(); i++) {
-    e00ARC &arc = arc_section[i];
-    if (!arc.inPolygon) {
-	lineArcs.push_back(&arc);
-    }
+  if (pos == -1)
+    return 0;
+
+  return &(ifo->entries[entry-1][pos]);
+}
+
+const string *
+E00::getIFOItemType (const string &fileName, const string &itemName) const
+{
+  const IFO * ifo = getIFO(fileName);
+  if (ifo == 0)
+    return 0;
+
+  int pos = -1;
+  for (int i = 0; i < ifo->defs.size(); i++) {
+    if (ifo->defs[i].itemName == itemName)
+      return &(ifo->defs[i].itemType);
   }
 
+  return 0;
 }
 
 // end of e00.cxx
diff --git a/src/Lib/e00/e00.hxx b/src/Lib/e00/e00.hxx
index a51005b2..273b093f 100644
--- a/src/Lib/e00/e00.hxx
+++ b/src/Lib/e00/e00.hxx
@@ -1,145 +1,170 @@
+// e00.hxx - declarations for E00 file processing.
+
+#ifndef __E00_HXX
+#define __E00_HXX 1
+
 #include <simgear/compiler.h>
 
 #include <vector>
-#include <map>
-#include STL_STRING
+#include <string>
 #include <iostream>
 
-FG_USING_STD(vector);
-FG_USING_STD(map);
-FG_USING_STD(string);
-FG_USING_STD(istream);
-FG_USING_STD(ostream);
+using std::vector;
+using std::string;
+using std::istream;
 
-struct E00Exception
+
+// An exception reading an E00 file.
+
+class E00Exception
 {
-  E00Exception (const char * msg) : message(msg) {}
-  string message;
+public:
+  E00Exception (const string &message) : _message(message) {}
+  virtual const string &getMessage () const { return _message; }
+private:
+  string _message;
 };
 
 
-// A coordinate in two-dimensional space.
-
-struct e00Coord
-{
-  double x;
-  double y;
-};
-
-
-// Arc Coordinates and Topology
-
-struct e00ARC
-{
-  bool inPolygon;
-  int coverageNum;
-  int coverageId;
-  int fromNode;
-  int toNode;
-  int leftPolygon;
-  int rightPolygon;
-  int numberOfCoordinates;
-  vector<e00Coord> coordinates;
-};
-
-
-// Polygon Centroid Coordinates
-
-struct e00CNT
-{
-  int numLabels;
-  e00Coord centroid;
-  vector<int> labels;
-};
-
-
-// Label Point Coordinates and Topology
-
-struct e00LAB
-{
-  int coverageId;
-  int enclosingPolygon;
-  e00Coord coord;
-  e00Coord box1;		// obsolete
-  e00Coord box2;		// obsolete
-};
-
-
-// Coverage History
-
-struct e00LOG
-{
-  vector<string> lines;
-};
-
-
-// Polygon Topology
-
-struct e00PAL
-{
-  struct ARC
-  {
-    int arcNum;
-    int nodeNum;
-    int polygonNum;
-  };
-  int numArcs;
-  e00Coord min;
-  e00Coord max;
-  vector<ARC> arcs;
-};
-
-
-// Projection Parameters
-
-struct e00PRJ
-{
-  vector<string> lines;
-};
-
-
-// Tolerance Type
-
-struct e00TOL
-{
-  int type;
-  int status;
-  double value;
-};
-
-
-// Info Files
-
-struct e00IFO
-{
-  struct ItemDef 
-  {
-    string itemName;
-    int itemWidth;		// followed by -1
-    int itemStartPos;		// followed by 4-1
-    int itemOutputFormat[2];
-    string itemType;
-    // -1
-    // -1-1
-    string seqId;
-  };
-  typedef vector<string> Entry;
-  string fileName;
-  string isArcInfo;
-  int numItems;
-  int altNumItems;
-  int dataRecordLength;
-  int numDataRecords;
-  vector<ItemDef> defs;
-  vector<Entry> entries;
-};
-
 
 // ARCInfo file
 
 class E00 {
+
 public:
 
+
+  //////////////////////////////////////////////////////////////////////
+  // Data structures for internal use.
+  //////////////////////////////////////////////////////////////////////
+
+
+  // A coordinate in two-dimensional space.
+
+  struct Coord
+  {
+    virtual ~Coord () {}
+    double x;
+    double y;
+  };
+
+
+  // Arc co-ordinates and topology.
+
+  struct ARC
+  {
+    virtual ~ARC () {}
+    int coverageNum;
+    int coverageId;
+    int fromNode;
+    int toNode;
+    int leftPolygon;
+    int rightPolygon;
+    int numberOfCoordinates;
+    vector<Coord> coordinates;
+    bool in_polygon;
+  };
+
+
+  // Polygon Centroid Coordinates
+
+  struct CNT
+  {
+    virtual ~CNT () {}
+    int numLabels;
+    Coord centroid;
+    vector<int> labels;
+  };
+
+
+  // Label Point Coordinates and Topology
+
+  struct LAB
+  {
+    virtual ~LAB () {}
+    int coverageId;
+    int enclosingPolygon;
+    Coord coord;
+    Coord box1;		// obsolete
+    Coord box2;		// obsolete
+  };
+
+
+  // Coverage History
+
+  struct LOG
+  {
+    virtual ~LOG () {}
+    vector<string> lines;
+  };
+
+
+  // Polygon Topology
+
+  struct PAL
+  {
+    virtual ~PAL () {}
+    struct ARCref
+    {
+      int arcNum;
+      int nodeNum;
+      int polygonNum;
+    };
+    int numArcs;
+    Coord min;
+    Coord max;
+    vector<ARCref> arcs;
+  };
+
+
+  // Projection Parameters
+
+  struct PRJ
+  {
+    virtual ~PRJ () {}
+    vector<string> lines;
+  };
+
+
+  // Tolerance Type
+
+  struct TOL
+  {
+    virtual ~TOL () {}
+    int type;
+    int status;
+    double value;
+  };
+
+
+  // Info Files
+
+  struct IFO
+  {
+    virtual ~IFO () {}
+    struct ItemDef 
+    {
+      string itemName;
+      int itemWidth;		// followed by -1
+      int itemStartPos;		// followed by 4-1
+      int itemOutputFormat[2];
+      string itemType;
+      // -1
+      // -1-1
+      string seqId;
+    };
+    typedef vector<string> Entry;
+    string fileName;
+    string isArcInfo;
+    int numItems;
+    int altNumItems;
+    int dataRecordLength;
+    int numDataRecords;
+    vector<ItemDef> defs;
+    vector<Entry> entries;
+  };
+
+
   E00 ();
   virtual ~E00 ();
 
@@ -147,35 +172,37 @@ public:
 
   virtual string getPathName () const { return pathName; }
 
-  virtual int nPoints () const;
-  virtual int nLines () const;
-  virtual int nPolygons () const;
+  virtual int nPoints () const { return lab_section.size(); }
+  virtual int nLines () const { return arc_section.size(); }
+  virtual int nPolygons () const { return pal_section.size(); }
+  virtual int nInfoFiles () const { return ifo_section.size(); }
 
-  virtual const e00ARC * getPoint (int i) const { return pointArcs[i]; }
-  virtual const e00ARC * getLine (int i) const { return lineArcs[i]; }
-
-  virtual void write (ostream &output) const;
+  virtual const ARC &getARC (int i) const { return arc_section[i-1]; }
+  virtual const LAB &getLAB (int i) const { return lab_section[i-1]; }
+  virtual const PAL &getPAL (int i) const { return pal_section[i-1]; }
+  virtual const IFO &getIFO (int i) const { return ifo_section[i-1]; }
+  virtual const IFO * getIFO (const string &name) const;
+  virtual const string * getIFOItem (const string &fileName, int entry,
+				     const string &itemName) const;
+  virtual const string * getIFOItemType (const string &fileName,
+					 const string &itemName) const;
+    
 
 private:
 
-  vector<const e00ARC *> pointArcs;
-  vector<const e00ARC *> lineArcs;
+  virtual ARC &_getARC (int i) { return arc_section[i-1]; }
 
   string pathName;
-  vector<e00ARC> arc_section;
-  vector<e00CNT> cnt_section;
-  vector<e00LAB> lab_section;
-  vector<e00LOG> log_section;
-  vector<e00PAL> pal_section;
-  vector<e00PRJ> prj_section;
-  vector<e00TOL> tol_section;
-  vector<e00IFO> ifo_section;
+  vector<ARC> arc_section;
+  vector<CNT> cnt_section;
+  vector<LAB> lab_section;
+  vector<LOG> log_section;
+  vector<PAL> pal_section;
+  vector<PRJ> prj_section;
+  vector<TOL> tol_section;
+  vector<IFO> ifo_section;
 
-  istream * _input;
-
-  void expect (int i);
-  void expect (double f);
-  void expect (const char * s);
+  mutable istream * _input;
 
   void postProcess ();
 
@@ -188,6 +215,15 @@ private:
   void readPRJ ();
   void readSIN ();
   void readTOL ();
+  void readTX6 ();
+  void readTX7 ();
+  void readRXP ();
+  void readRPL ();
   void readIFO ();
   void readUnknown ();
+
 };
+
+#endif __E00_HXX
+
+// end of e00.hxx
diff --git a/src/Lib/e00/teste00.cxx b/src/Lib/e00/teste00.cxx
index af13d7a4..f7f9e07b 100644
--- a/src/Lib/e00/teste00.cxx
+++ b/src/Lib/e00/teste00.cxx
@@ -1,20 +1,19 @@
+// teste00.cxx - test the E00 parsing routines and dump some results.
 
-#include <fstream>
+#include <simgear/misc/fgstream.hxx>
 #include "e00.hxx"
 
-using std::ifstream;
-
 int main (int ac, const char ** av)
 {
   for (int i = 1; i < ac; i++) {
     cerr << "Reading " << av[i] << endl;
-    ifstream input(av[i]);
+    fg_gzifstream input(av[i]);
     E00 data;
     try {
       data.readE00(input);
     } catch (E00Exception &e) {
       cerr << "Reading " << av[i] << " failed with exception "
-	   << e.message << endl;
+	   << e.getMessage() << endl;
       exit(1);
     }
     cerr << "Read " << av[i] << " successfully" << endl;
@@ -23,8 +22,39 @@ int main (int ac, const char ** av)
     cerr << "Read " << data.nPolygons() << " polygon(s)" << endl;
     cerr << " (including enclosing polygon)" << endl;
 
-    data.write(cout);
+    for (int i = 1; i <= data.nInfoFiles(); i++) {
+      const E00::IFO &ifo = data.getIFO(i);
+      cout << "IFO file: " << ifo.fileName << endl;
+      for (int j = 0; j < ifo.numItems; j++) {
+	cout << "  " << ifo.defs[j].itemName << endl;
+      }
+    }
+
+//     for (int i = 2; i <= data.nPolygons(); i++) {
+//       const E00::PAL &pal = data.getPAL(i);
+//       for (int j = 0; j < pal.numArcs; j++) {
+// 	int arcNum = pal.arcs[j].arcNum;
+// 	if (arcNum == 0) {
+// 	  cout << endl;
+// 	} else if (arcNum < 0) {
+// 	  const E00::ARC &arc = data.getARC(0-arcNum);
+// 	  for (int k = arc.numberOfCoordinates - 1; k >= 0; k--) {
+// 	    cout << arc.coordinates[k].x << '\t'
+// 		 << arc.coordinates[k].y << endl;
+// 	  }
+// 	} else {
+// 	  const E00::ARC &arc = data.getARC(arcNum);
+// 	  for (int k = 0; k < arc.numberOfCoordinates; k++) {
+// 	    cout << arc.coordinates[k].x << '\t'
+// 		 << arc.coordinates[k].y << endl;
+// 	  }
+// 	}
+// 	cout << endl;
+//       }
+//     }
   } 
 
   return 0;
 }
+
+// end of teste00.cxx
diff --git a/src/Prep/E00Lines/Makefile.am b/src/Prep/E00Lines/Makefile.am
index 09e7e34a..8caea46c 100644
--- a/src/Prep/E00Lines/Makefile.am
+++ b/src/Prep/E00Lines/Makefile.am
@@ -6,6 +6,6 @@ e00lines_LDADD = \
 	$(top_builddir)/src/Lib/Polygon/libPolygon.a \
 	$(top_builddir)/src/Lib/poly2tri/libpoly2tri.a \
 	$(top_builddir)/src/Lib/e00/libe00.a \
-	-lsgdebug -lsgbucket -lsgmisc -lsgmath -lz -lgpc
+	-lsgdebug -lsgbucket -lsgmisc -lsgmath -lsgio -lz -lgpc
 
 INCLUDES += -I$(top_srcdir)/src/Lib
diff --git a/src/Prep/E00Lines/main.cxx b/src/Prep/E00Lines/main.cxx
index c9550384..85c7bf66 100644
--- a/src/Prep/E00Lines/main.cxx
+++ b/src/Prep/E00Lines/main.cxx
@@ -27,12 +27,16 @@
 #include <simgear/constants.h>
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/debug/logstream.hxx>
+#include <simgear/misc/fgstream.hxx>
 
+#include <iostream>
 #include <string>
-#include <fstream>
+#include <vector>
 
-using std::string;
-using std::ifstream;
+FG_USING_STD(cerr);
+FG_USING_STD(cout);
+FG_USING_STD(string);
+FG_USING_STD(vector);
 
 #include <Polygon/index.hxx>
 #include <Polygon/names.hxx>
@@ -44,7 +48,14 @@ using std::ifstream;
 #  include <Win32/mkdir.hpp>
 #endif
 
-static inline double ANGLE (double a)
+
+
+////////////////////////////////////////////////////////////////////////
+// Utility stuff.
+////////////////////////////////////////////////////////////////////////
+
+static inline double 
+ANGLE (double a)
 {
   while (a < 0.0)
     a += 360.0;
@@ -54,69 +65,192 @@ static inline double ANGLE (double a)
 }
 
 
-int
-main (int argc, const char **argv)
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Areas.
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * A rectangle (such as a bounding box).
+ */
+struct Rectangle
 {
+  Rectangle () : minX(0.0), minY(0.0), maxX(0.0), maxY(0.0) {}
+  Rectangle (double _minX, double _minY, double _maxX, double _maxY)
+    : minX(_minX), minY(_minY), maxX(_maxX), maxY(_maxY) {}
+  double minX;
+  double minY;
+  double maxX;
+  double maxY;
+  bool isInside (double x, double y) const
+  {
+    return (x >= minX && x <= maxX && y >= minY && y <= maxY);
+  }
+  bool isOverlapping (const Rectangle &rect) const
+  {
+    return (isInside(rect.minX, rect.minY) ||
+	    isInside(rect.minX, rect.maxY) ||
+	    isInside(rect.maxX, rect.minY) ||
+	    isInside(rect.maxX, rect.maxY));
+  }
+};
 
-				// Enable logging.
-  fglog().setLogLevels( FG_ALL, FG_DEBUG );
+static ostream &
+operator<< (ostream &output, const Rectangle &rect) {
+  output << '(' << rect.minX << ',' << rect.minY << "),("
+	 << rect.maxX << ',' << rect.maxY << ')';
+}
+
+/**
+ * Make a bounding box for a single ARC.
+ */
+static Rectangle
+makeBounds (const E00::ARC &arc)
+{
+  Rectangle bounds;
+  for (int i = 0; i < arc.numberOfCoordinates; i++) {
+    double x = arc.coordinates[i].x;
+    double y = arc.coordinates[i].y;
+    if (i == 0) {
+      bounds.minX = bounds.maxX = x;
+      bounds.minY = bounds.maxY = y;
+    } else {
+      if (x < bounds.minX) bounds.minX = x;
+      if (y < bounds.minY) bounds.minY = y;
+      if (x > bounds.maxX) bounds.maxX = x;
+      if (y > bounds.maxY) bounds.maxY = y;
+    }
+  }
+  return bounds;
+}
+
+/**
+ * Make a bounding box for a polygon.
+ */
+static Rectangle
+makeBounds (const E00::PAL &pal)
+{
+  return Rectangle(pal.min.x, pal.min.y, pal.max.x, pal.max.y);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Processing methods.
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * An attribute pattern.
+ */
+struct Attribute
+{
+  string file;
+  string item;
+  string value;
+};
+
+
+/**
+ * Check whether an attribute pattern matches a shape.
+ */
+static bool
+checkAttribute (const E00 &data, int index, const Attribute &att)
+{
+  const string * type = data.getIFOItemType(att.file, att.item);
+  if (type == 0)
+    return false;
+  const string * value = data.getIFOItem(att.file, index, att.item);
+  if (value == 0)
+    return false;
+
+  if (*type == "10-1") {	// date
+    return (*value == att.value);
+  }
   
-				// Check usage.
-  if ( argc != 5 ) {
-    FG_LOG( FG_GENERAL, FG_ALERT, "Usage: " << argv[0] 
-	    << " <e00_line_file> <width_meters> <area_type> <work_dir>" );
-    exit(-1);
+  else if (*type == "20-1") {	// string
+    return (*value == att.value);
   }
 
-				// Grab command-line arguments.
-  ifstream input(argv[1]);
-  if ( !input.good() ) {
-    FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << argv[1]);
-    exit(-1);
+  else if (*type == "30-1" || *type == "50-1") { // integer
+    int val1 = atoi(value->c_str());
+    int val2 = atoi(att.value.c_str());
+    return (val1 == val2);
   }
 
-  int width = atoi(argv[2]);
-  if (width <= 0) {
-    FG_LOG(FG_GENERAL, FG_ALERT, "Bad width specified " << argv[2]);
-    exit(-1);
+  else if (*type == "40-1" || *type == "60-1") { // float
+    float val1 = atof(value->c_str());
+    float val2 = atof(att.value.c_str());
+    return (val1 == val2);
   }
 
-  AreaType area_type = get_area_type(argv[3]);
-
-  string work_dir = argv[4];
-#ifdef _MSC_VER
-  fg_mkdir(work_dir.c_str());
-#else
-  string command = "mkdir -p " + work_dir;
-  system(command.c_str());
-#endif
-
-				// Read the E00 file.
-  E00 data;
-  try {
-    data.readE00(input);
-  } catch (E00Exception &e) {
-    FG_LOG(FG_GENERAL, FG_ALERT, "Reading " << argv[1]
-	   << " failed with exception " << e.message);
+  else {
+    cerr << "Unknown IFO field type " << *type << endl;
     exit(1);
   }
 
-				// Initialize the persistant polygon counter.
-  string counter_file = work_dir + "/../poly_counter";
-  poly_index_init( counter_file );
+  return (*value == att.value);
+}
 
+
+/**
+ * Create polygons out of points.
+ */
+static void
+processPoints (const E00 &data, const Rectangle &bounds,
+	       AreaType areaType, const string &workDir, int width)
+{
+  cerr << "Points not yet supported" << endl;
+}
+
+
+/**
+ * Create polygons out of all loose line segments.
+ */
+static void
+processLines (const E00 &data, const Rectangle &bounds,
+	      AreaType areaType, const string &workDir, int width,
+	      const vector<Attribute> &aat_list)
+{
   FGPolygon shape;
 
-				// Iterate through the lines.
   int nLines = data.nLines();
-  for (int i = 0; i < nLines; i++) {
-    const e00ARC * line = data.getLine(i);
-    cout << "Line has " << line->numberOfCoordinates << " coordinates" << endl;
-    for (int j = 0; j < line->numberOfCoordinates - 1; j++) {
-      double lon1 = line->coordinates[j].x;
-      double lat1 = line->coordinates[j].y;
-      double lon2 = line->coordinates[j+1].x;
-      double lat2 = line->coordinates[j+1].y;
+  cout << "Processing " << nLines << " lines." << endl;
+  for (int i = 1; i <= nLines; i++) {
+    const E00::ARC &arc = data.getARC(i);
+    Rectangle arcBounds = makeBounds(arc);
+    if (!bounds.isOverlapping(arcBounds)) {
+      cout << "Arc " << i << " outside of area; skipping" << endl;
+      cout << "Arc bounds: " << arcBounds << endl;
+      continue;
+    }
+
+				// If any arc attributes were specified,
+				// make sure at least one of them is
+				// present.
+    if (aat_list.size() > 0) {
+      bool status = false;
+      for (int j = 0; j < aat_list.size(); j++) {
+	if (checkAttribute(data, i, aat_list[j])) {
+	  status = true;
+	  break;
+	}
+      }
+      if (!status) {
+	cout << "Skipping line " << i << " (failed attribute tests)" << endl;
+	continue;
+      }
+    }
+
+				// Make the line into a polygon.
+    cout << "Line has " << arc.numberOfCoordinates << " coordinates" << endl;
+    for (int j = 0; j < arc.numberOfCoordinates - 1; j++) {
+      double lon1 = arc.coordinates[j].x;
+      double lat1 = arc.coordinates[j].y;
+      double lon2 = arc.coordinates[j+1].x;
+      double lat2 = arc.coordinates[j+1].y;
       double angle1, angle2, dist;
       geo_inverse_wgs_84(0, lat1, lon1, lat2, lon2, &angle1, &angle2, &dist);
       cout << "angle1 = " << angle1 << endl;
@@ -152,10 +286,358 @@ main (int argc, const char **argv)
       shape.add_node(0, Point3D(x, y, 0));
 
 				// Split into tiles
-      split_polygon(work_dir, area_type, shape);
+      split_polygon(workDir, areaType, shape);
+    }
+  }
+}
+
+
+/**
+ * Import all polygons.
+ */
+static void
+processPolygons (const E00 &data, const Rectangle &bounds,
+		 AreaType areaType, const string &workDir,
+		 const vector<Attribute> pat_list)
+{
+  FGPolygon shape;
+
+  int nPolygons = data.nPolygons();
+  cout << "Processing " << nPolygons << " polygons" << endl;
+
+  for (int i = 2; i <= nPolygons; i++) {
+
+				// Test whether the polygon matches
+				// at least one of the attributes
+				// provided.
+    if (pat_list.size() > 0) {
+      bool status = false;
+      for (int j = 0; j < pat_list.size(); j++) {
+	if (checkAttribute(data, i, pat_list[j])) {
+	  status = true;
+	  break;
+	}
+      }
+      if (!status) {
+	cout << "Skipping polygon " << i << " (failed attribute tests)"
+	     << endl;
+	continue;
+      }
+    }
+
+    int contour = 0;
+    const E00::PAL &pal = data.getPAL(i);
+    Rectangle palBounds = makeBounds(pal);
+    if (!bounds.isOverlapping(palBounds)) {
+      cout << "Polygon " << i << " outside of area, skipping" << endl;
+      cout << "Polygon boundary is " << palBounds << endl;
+      continue;
+    }
+    shape.erase();
+    for (int j = 0; j < pal.numArcs; j++) {
+      int arcNum = pal.arcs[j].arcNum;
+				// Starting a hole
+      if (arcNum == 0) {
+	contour++;
+	point_list contour;
+	contour.clear();
+	shape.add_contour(contour, 1);
+      } else if (arcNum < 0) {
+	const E00::ARC &arc = data.getARC(0-arcNum);
+	for (int k = arc.numberOfCoordinates - 1; k >= 0; k--)
+	  shape.add_node(contour, Point3D(arc.coordinates[k].x,
+					  arc.coordinates[k].y,
+					  0.0));
+      } else {
+	const E00::ARC &arc = data.getARC(arcNum);
+	for (int k = 0; k < arc.numberOfCoordinates; k++)
+	  shape.add_node(contour, Point3D(arc.coordinates[k].x,
+					  arc.coordinates[k].y,
+					  0.0));
+      }
+    }
+    split_polygon(workDir, areaType, shape);
+  }
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Main program.
+////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Print the command-line usage and exit.
+ */
+static void
+usage (const char * prog)
+{
+  cerr << "Usage: " << prog << " [opts] e00file ..." << endl;
+  cerr << "Options:" << endl;
+  cerr << "--points=yes|no (default: no)" << endl;
+  cerr << "--lines=yes|no (default: yes)" << endl;
+  cerr << "--polygons=yes|no (default: yes)" << endl;
+  cerr << "--min-lon=<longitude> (default: -180.0)" << endl;
+  cerr << "--min-lat=<latitude> (default: -90.0)" << endl;
+  cerr << "--max-lon=<longitude> (default: 180.0)" << endl;
+  cerr << "--max-lat=<latitude> (default: 90.0)" << endl;
+  cerr << "--area=<area_type> (default: Default)" << endl;
+  cerr << "--point-width=<meters> (default: 500)" << endl;
+  cerr << "--line-width=<meters> (default: 50)" << endl;
+  cerr << "--work-dir=<dir> (default: .)" << endl;
+  cerr << "--aat=<infofile>:<item>:<value> (may be repeated)" << endl;
+  cerr << "--pat=<infofile>:<item>:<value> (may be repeated)" << endl;
+  exit(2);
+}
+
+
+/**
+ * Parse an attribute value specification from the command line.
+ */
+static void
+parseAttribute (const char * prog, string arg, Attribute &att)
+{
+  int pos1 = arg.find(':');
+  int pos2 = arg.rfind(':');
+  if (pos1 == -1 || pos2 == -1 || pos2 <= pos1) {
+    cerr << "Bad attribute specification: " << arg << endl;
+    usage(prog);
+  }
+
+  att.file = arg.substr(0, pos1);
+  att.item = arg.substr(pos1 + 1, pos2 - (pos1 + 1));
+  att.value = arg.substr(pos2+1);
+}
+
+
+/**
+ * Main entry point.
+ */
+int
+main (int argc, const char **argv)
+{
+  vector<Attribute> aat_list;
+  vector<Attribute> pat_list;
+
+				// Enable logging.
+  fglog().setLogLevels( FG_ALL, FG_DEBUG );
+
+
+				// Default values
+  Rectangle bounds(-180.0, -90.0, 180.0, 90.0);
+  AreaType areaType = DefaultArea;
+  int pointWidth = 500;
+  int lineWidth = 50;
+  string workDir = ".";
+  bool usePoints = false;
+  bool useLines = true;
+  bool usePolygons = true;
+
+				// Command-line options
+  int argPos = 1;
+  while (argPos < argc) {
+    string arg = argv[argPos];
+
+    cout << "Trying argument " << arg << endl;
+
+    if (arg.find("--points=") == 0) {
+      if (arg.substr(9) == "yes")
+	usePoints = true;
+      else if (arg.substr(9) == "no")
+	usePoints = false;
+      else {
+	cerr << "--points option needs 'yes' or 'no'" << endl;
+	usage(argv[0]);
+      }
+      argPos++;
+    }
+
+    else if (arg.find("--lines=") == 0) {
+      if (arg.substr(9) == "yes")
+	useLines = true;
+      else if (arg.substr(9) == "no")
+	useLines = false;
+      else {
+	cerr << "--lines option needs 'yes' or 'no'" << endl;
+	usage(argv[0]);
+      }
+      argPos++;
+    }
+
+    else if (arg.find("--polygons=") == 0) {
+      if (arg.substr(9) == "yes")
+	usePolygons = true;
+      else if (arg.substr(9) == "no")
+	usePolygons = false;
+      else {
+	cerr << "--polygons option needs 'yes' or 'no'" << endl;
+	usage(argv[0]);
+      }
+      argPos++;
+    }
+
+    else if (arg.find("--min-lon=") == 0) {
+      bounds.minX = atof(arg.substr(10).c_str());
+      argPos++;
+    }
+
+    else if (arg.find("--min-lat=") == 0) {
+      bounds.minY = atof(arg.substr(10).c_str());
+      argPos++;
+    }
+
+    else if (arg.find("--max-lon=") == 0) {
+      bounds.maxX = atof(arg.substr(10).c_str());
+      argPos++;
+    } 
+
+    else if (arg.find("--max-lat=") == 0) {
+      bounds.maxY = atof(arg.substr(10).c_str());
+      argPos++;
+    }
+
+    else if (arg.find("--area=") == 0) {
+      areaType = get_area_type(arg.substr(7).c_str());
+      argPos++;
+    }
+
+    else if (arg.find("--point-width=") == 0) {
+      pointWidth = atoi(arg.substr(14).c_str());
+      argPos++;
+    }
+
+    else if (arg.find("--line-width=") == 0) {
+      lineWidth = atoi(arg.substr(13).c_str());
+      argPos++;
+    }
+
+    else if (arg.find("--work-dir=") == 0) {
+      workDir = arg.substr(11);
+      argPos++;
+    }
+
+    else if (arg.find("--aat=") == 0) {
+      Attribute att;
+      parseAttribute(argv[0], arg.substr(6), att);
+      aat_list.push_back(att);
+      cout << "Added polygon constraint for " << att.file << ": "
+	   << att.item << '=' << att.value << endl;
+      argPos++;
+    }
+
+    else if (arg.find("--pat=") == 0) {
+      Attribute att;
+      parseAttribute(argv[0], arg.substr(6), att);
+      pat_list.push_back(att);
+      cout << "Added polygon constraint for " << att.file << ": "
+	   << att.item << '=' << att.value << endl;
+      argPos++;
+    }
+
+    else if (arg == "--") {
+      argPos++;
+      break;
+    }
+
+    else if (arg.find("-") == 0) {
+      cerr << "Unrecognized option: " << arg << endl;
+      usage(argv[0]);
+    }
+
+    else {
+      break;
     }
   }
 
+				// Check for files to process
+  if (argPos >= argc) {
+    cerr << "No e00 files specified!!" << endl;
+    usage(argv[0]);
+  }
+
+  cout << "Bounds are " << bounds << endl;
+  cout << "Area type is " << get_area_name(areaType) << endl;;
+  cout << "Working directory is " << workDir << endl;
+  if (usePoints)
+    cout << "Using points with width " << pointWidth << " meters" << endl;
+  else
+    cout << "Ignoring point coverage" << endl;
+  if (useLines)
+    cout << "Using lines with width " << lineWidth << " meters" << endl;
+  else
+    cout << "Ignoring line coverage" << endl;
+  if (usePolygons)
+    cout << "Using polygons" << endl;
+  else
+    cout << "Ignoring polygon coverage" << endl;
+  if (useLines && aat_list.size() > 0) {
+    cout << "Lines must match at least one of the following:" << endl;
+    for (int i = 0; i < aat_list.size(); i++) {
+      cout << aat_list[i].file << ' ' << aat_list[i].item << ' '
+	   << aat_list[i].value << endl;
+    }
+  }
+  if (usePolygons && pat_list.size() > 0) {
+    cout << "Polygons must match at least one of the following:" << endl;
+    for (int i = 0; i < pat_list.size(); i++) {
+      cout << pat_list[i].file << ' ' << pat_list[i].item << ' '
+	   << pat_list[i].value << endl;
+    }
+  }
+
+				// Make sure the destination
+				// directory exists.
+#ifdef _MSC_VER
+  fg_mkdir(workDir.c_str());
+#else
+  string command = "mkdir -p " + workDir;
+  system(command.c_str());
+#endif
+
+				// Process all of the e00 files
+				// on the command line.
+  while (argPos < argc) {
+
+    cout << "Processing " << argv[argPos] << endl;
+
+				// Grab command-line arguments.
+    fg_gzifstream input(argv[argPos]);
+    if ( !input.good() ) {
+      FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << argv[argPos]);
+      exit(-1);
+    }
+
+				// Read the E00 file.
+    
+    E00 data;
+    try {
+      data.readE00(input);
+    } catch (E00Exception &e) {
+      FG_LOG(FG_GENERAL, FG_ALERT, "Reading " << argv[argPos]
+	     << " failed with exception " << e.getMessage());
+      exit(1);
+    }
+
+				// Initialize the persistant polygon counter.
+    string counter_file = workDir + "/../poly_counter";
+    poly_index_init( counter_file );
+    
+    if (usePoints)
+      processPoints(data, bounds, areaType, workDir, pointWidth);
+
+    if (useLines)
+      processLines(data, bounds, areaType, workDir, lineWidth, aat_list);
+
+    if (usePolygons)
+      processPolygons(data, bounds, areaType, workDir, pat_list);
+    
+    cout << "Done processing " << argv[argPos] << endl;
+    argPos++;
+  }
+
+  cout << "Done all processing." << endl;
   return 0;
 }