From 8a82c389ecd128bed894d66a18740a3d6199c30f Mon Sep 17 00:00:00 2001 From: curt <curt> Date: Wed, 22 Nov 2000 22:17:58 +0000 Subject: [PATCH] Initial revision. --- src/Lib/e00/Makefile.am | 10 + src/Lib/e00/e00.cxx | 608 ++++++++++++++++++++++++++++++++++ src/Lib/e00/e00.hxx | 190 +++++++++++ src/Lib/e00/teste00.cxx | 30 ++ src/Prep/E00Lines/Makefile.am | 11 + src/Prep/E00Lines/main.cxx | 162 +++++++++ 6 files changed, 1011 insertions(+) create mode 100644 src/Lib/e00/Makefile.am create mode 100644 src/Lib/e00/e00.cxx create mode 100644 src/Lib/e00/e00.hxx create mode 100644 src/Lib/e00/teste00.cxx create mode 100644 src/Prep/E00Lines/Makefile.am create mode 100644 src/Prep/E00Lines/main.cxx diff --git a/src/Lib/e00/Makefile.am b/src/Lib/e00/Makefile.am new file mode 100644 index 00000000..25e97f1e --- /dev/null +++ b/src/Lib/e00/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = libe00.a + +libe00_a_SOURCES = e00.cxx e00.hxx + +noinst_PROGRAMS = teste00 + +teste00_SOURCES = teste00.cxx +teste00_LDADD = libe00.a + + diff --git a/src/Lib/e00/e00.cxx b/src/Lib/e00/e00.cxx new file mode 100644 index 00000000..98abd804 --- /dev/null +++ b/src/Lib/e00/e00.cxx @@ -0,0 +1,608 @@ +// e00.cxx: implementation of ArcInfo (e00) reader. + +#include "e00.hxx" + +#include <vector> +#include <map> +#include <string> +#include <iostream> +#include <cctype> + +#include <stdio.h> + +using std::vector; +using std::map; +using std::string; +using std::istream; +using std::cerr; +using std::endl; + + +//////////////////////////////////////////////////////////////////////// +// Static helper functions. +//////////////////////////////////////////////////////////////////////// + +static void +append (string &s, int i) +{ + char buf[128]; + sprintf(buf, "%d", i); + s += buf; +} + +static void +append (string &s, double f) +{ + char buf[128]; + sprintf(buf, "%f", f); + s += buf; +} + +static void +skipWhitespace (istream &input) +{ + char c; + input.get(c); + while (isspace(c)) { + input.get(c); + } + input.putback(c); +} + +static void +readStringItem (istream &input, string &line, int width) +{ + char c; + + skipWhitespace(input); + line.resize(0); + + for (int i = 0; i < width; i++) { + input.get(c); + if (c == '\n' || c == '\r') // premature termination + return; + else + line += c; + } +} + +static void +checkPrecision (istream &input) +{ + int i; + + input >> i; + if (i != 2 && i != 3) + throw E00Exception("Unknown precision"); +} + +static void +checkZeros (istream &input) +{ + int i, j; + + for (i = 0; i < 6; i++) { + input >> j; + if (j != 0) + throw E00Exception("Expected -1 followed by six zeros"); + } +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of E00 +//////////////////////////////////////////////////////////////////////// + + +E00::E00 () +{ +} + + +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 +{ + 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 (int i = 0; i < (int)arc_section.size(); i++) { + const e00ARC &arc = arc_section[i]; + if (!arc.inPolygon) { + output << "<line>" << endl; + for (int 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 (int i = 1; i < (int)pal_section.size(); i++) { + const e00PAL &pal = pal_section[i]; + output << "<polygon>" << endl; + for (int 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 (int k = arc.numberOfCoordinates - 1; k >= 0; k--) { + writeVertex(output, arc.coordinates[k].x, arc.coordinates[k].y); + } + } else { + for (int 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(); +} + + + +//////////////////////////////////////////////////////////////////////// +// Reader. +//////////////////////////////////////////////////////////////////////// + +void +E00::readE00 (istream &input) +{ + string token; + + _input = &input; + + readHeader(); + + while (!_input->eof()) { + + *_input >> token; + + if (token == "ARC") { + readARC(); + } else if (token == "CNT") { + readCNT(); + } else if (token == "LAB") { + readLAB(); + } else if (token == "LOG") { + readLOG(); + } else if (token == "PAL") { + readPAL(); + } else if (token == "PRJ") { + readPRJ(); + } else if (token == "SIN") { + readSIN(); + } else if (token == "TOL") { + readTOL(); + } else if (token == "IFO") { + readIFO(); + } else if (token == "EOS") { + postProcess(); + return; + } else { + cerr << "Skipping unknown section type " << token << endl; + readUnknown(); + } + } + + throw E00Exception("File ended without EOS line"); +} + + +/** + * Read the header of an E00 file. + */ +void +E00::readHeader () +{ + expect("EXP"); + expect(0); + *_input >> pathName; +} + + +/** + * Read the ARC section of an E00 file. + */ +void +E00::readARC () +{ + e00ARC arc; + e00Coord coord; + + checkPrecision(*_input); + + *_input >> arc.coverageNum; + while (arc.coverageNum != -1) { + arc.inPolygon = false; + *_input >> arc.coverageId; + *_input >> arc.fromNode; + *_input >> arc.toNode; + *_input >> arc.leftPolygon; + *_input >> arc.rightPolygon; + *_input >> arc.numberOfCoordinates; + arc.coordinates.resize(0); + for (int i = 0; i < arc.numberOfCoordinates; i++) { + *_input >> coord.x; + *_input >> coord.y; + arc.coordinates.push_back(coord); + } + arc_section.push_back(arc); + *_input >> arc.coverageNum; + } + + checkZeros(*_input); +} + + +/** + * Read the CNT section of an E00 file. + */ +void +E00::readCNT () +{ + e00CNT cnt; + int label; + + checkPrecision(*_input); + + *_input >> cnt.numLabels; + + while (cnt.numLabels != -1) { + *_input >> cnt.centroid.x; + *_input >> cnt.centroid.y; + for (int i = 0; i < cnt.numLabels; i++) { + *_input >> label; + cnt.labels.push_back(label); + } + cnt_section.push_back(cnt); + *_input >> cnt.numLabels; + } + + checkZeros(*_input); +} + + +void +E00::readLAB () +{ + e00LAB lab; + + checkPrecision(*_input); + *_input >> lab.coverageId; + *_input >> lab.enclosingPolygon; + *_input >> lab.coord.x; + *_input >> lab.coord.y; + while (lab.coverageId != -1) { + *_input >> lab.box1.x; // obsolete + *_input >> lab.box1.y; // obsolete + *_input >> lab.box2.x; // obsolete + *_input >> lab.box2.y; // obsolete + lab_section.push_back(lab); + *_input >> lab.coverageId; + *_input >> lab.enclosingPolygon; + *_input >> lab.coord.x; + *_input >> lab.coord.y; + } +} + + +void +E00::readLOG () +{ + e00LOG log; + string line; + + checkPrecision(*_input); + getline(*_input, line); + while (line.find("EOL") != 0) { + + if (line[0] == '~') { + log_section.push_back(log); + log.lines.resize(0); + } else { + log.lines.push_back(line); + } + + getline(*_input, line); + } +} + + +void +E00::readPAL () +{ + e00PAL pal; + e00PAL::ARC arc; + + checkPrecision(*_input); + *_input >> pal.numArcs; + while (pal.numArcs != -1) { + *_input >> pal.min.x; + *_input >> pal.min.y; + *_input >> pal.max.x; + *_input >> pal.max.y; + pal.arcs.resize(0); + for (int i = 0; i < pal.numArcs; i++) { + *_input >> arc.arcNum; + *_input >> arc.nodeNum; + *_input >> arc.polygonNum; + pal.arcs.push_back(arc); + } + + pal_section.push_back(pal); + *_input >> pal.numArcs; + } + + checkZeros(*_input); +} + + +void +E00::readPRJ () +{ + e00PRJ prj; + string line; + + checkPrecision(*_input); + getline(*_input, line); + while (line.find("EOP") != 0) { + + if (line[0] == '~') { + prj_section.push_back(prj); + prj.lines.resize(0); + } else { + prj.lines.push_back(line); + } + + getline(*_input, line); + } +} + + +void +E00::readSIN () +{ + string line; + checkPrecision(*_input); + getline(*_input, line); + while (line.find("EOX") != 0) { + getline(*_input, line); + } +} + + +void +E00::readTOL () +{ + e00TOL tol; + + checkPrecision(*_input); + *_input >> tol.type; + while (tol.type != -1) { + *_input >> tol.status; + *_input >> tol.value; + tol_section.push_back(tol); + *_input >> tol.type; + } + + checkZeros(*_input); +} + + +void +E00::readIFO () +{ + e00IFO ifo; + e00IFO::ItemDef def; + e00IFO::Entry entry; + string line; + int intval; + double realval; + + checkPrecision(*_input); + + *_input >> ifo.fileName; + while (ifo.fileName.find("EOI") != 0) { + + // 'XX' may be absent + *_input >> ifo.isArcInfo; + if (ifo.isArcInfo == "XX") { + *_input >> ifo.numItems; + } else { + ifo.numItems = atoi(ifo.isArcInfo.c_str()); + ifo.isArcInfo = ""; + } + *_input >> ifo.altNumItems; + *_input >> ifo.dataRecordLength; + *_input >> ifo.numDataRecords; + + // Read the item definitions + ifo.defs.resize(0); + for (int i = 0; i < ifo.numItems; i++) { + *_input >> def.itemName; + *_input >> def.itemWidth; + expect(-1); + *_input >> def.itemStartPos; + expect(-1); + def.itemStartPos -= 4; + def.itemStartPos /= 10; + *_input >> def.itemOutputFormat[0]; + *_input >> def.itemOutputFormat[1]; + *_input >> def.itemType; + expect(-1); + expect(-1); + expect(-1); + *_input >> def.seqId; + ifo.defs.push_back(def); + getline(*_input, line); + } + + // Read the data records + ifo.entries.resize(0); + for (int i = 0; i < ifo.numDataRecords; i++) { + entry.resize(0); + 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); + } + entry.push_back(line); + } + ifo.entries.push_back(entry); + } + + ifo_section.push_back(ifo); + *_input >> ifo.fileName; + } +} + + +void +E00::readUnknown () +{ + string line; + getline(*_input, line); + while (line.find("EOX") != 0) { + getline(*_input, line); + } +} + + +void +E00::postProcess () +{ + + // 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; + } + } + } + + // 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); + } + } + +} + +// end of e00.cxx diff --git a/src/Lib/e00/e00.hxx b/src/Lib/e00/e00.hxx new file mode 100644 index 00000000..07f2f757 --- /dev/null +++ b/src/Lib/e00/e00.hxx @@ -0,0 +1,190 @@ +#include <vector> +#include <map> +#include <string> +#include <iostream> + +using std::vector; +using std::map; +using std::string; +using std::istream; + +struct E00Exception +{ + E00Exception (const char * msg) : message(msg) {} + 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: + + E00 (); + virtual ~E00 (); + + virtual void readE00 (istream &input); + + virtual string getPathName () const { return pathName; } + + virtual int nPoints () const; + virtual int nLines () const; + virtual int nPolygons () const; + + 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; + +private: + + vector<const e00ARC *> pointArcs; + vector<const e00ARC *> lineArcs; + + 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; + + istream * _input; + + void expect (int i); + void expect (double f); + void expect (const char * s); + + void postProcess (); + + void readHeader (); + void readARC (); + void readCNT (); + void readLAB (); + void readLOG (); + void readPAL (); + void readPRJ (); + void readSIN (); + void readTOL (); + void readIFO (); + void readUnknown (); +}; diff --git a/src/Lib/e00/teste00.cxx b/src/Lib/e00/teste00.cxx new file mode 100644 index 00000000..af13d7a4 --- /dev/null +++ b/src/Lib/e00/teste00.cxx @@ -0,0 +1,30 @@ + +#include <fstream> +#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]); + E00 data; + try { + data.readE00(input); + } catch (E00Exception &e) { + cerr << "Reading " << av[i] << " failed with exception " + << e.message << endl; + exit(1); + } + cerr << "Read " << av[i] << " successfully" << endl; + cerr << "Read " << data.nPoints() << " point(s)" << endl; + cerr << "Read " << data.nLines() << " line segment(s)" << endl; + cerr << "Read " << data.nPolygons() << " polygon(s)" << endl; + cerr << " (including enclosing polygon)" << endl; + + data.write(cout); + } + + return 0; +} diff --git a/src/Prep/E00Lines/Makefile.am b/src/Prep/E00Lines/Makefile.am new file mode 100644 index 00000000..09e7e34a --- /dev/null +++ b/src/Prep/E00Lines/Makefile.am @@ -0,0 +1,11 @@ +bin_PROGRAMS = e00lines + +e00lines_SOURCES = main.cxx + +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 + +INCLUDES += -I$(top_srcdir)/src/Lib diff --git a/src/Prep/E00Lines/main.cxx b/src/Prep/E00Lines/main.cxx new file mode 100644 index 00000000..c9550384 --- /dev/null +++ b/src/Prep/E00Lines/main.cxx @@ -0,0 +1,162 @@ +// main.cxx -- generate lines from E00 files. +// +// Written by David Megginson, started October 2000. Based on +// code by Curtis Olson. +// +// Copyright (C) 2000 David Megginson - david@megginson.com +// 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$ + + +#include <simgear/compiler.h> +#include <simgear/constants.h> +#include <simgear/math/sg_geodesy.hxx> +#include <simgear/debug/logstream.hxx> + +#include <string> +#include <fstream> + +using std::string; +using std::ifstream; + +#include <Polygon/index.hxx> +#include <Polygon/names.hxx> +#include <Polygon/polygon.hxx> +#include <Polygon/split.hxx> +#include <e00/e00.hxx> + +#ifdef _MSC_VER +# include <Win32/mkdir.hpp> +#endif + +static inline double ANGLE (double a) +{ + while (a < 0.0) + a += 360.0; + while (a >= 360.0) + a -= 360.0; + return a; +} + + +int +main (int argc, const char **argv) +{ + + // Enable logging. + fglog().setLogLevels( FG_ALL, FG_DEBUG ); + + // 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); + } + + // Grab command-line arguments. + ifstream input(argv[1]); + if ( !input.good() ) { + FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << argv[1]); + exit(-1); + } + + int width = atoi(argv[2]); + if (width <= 0) { + FG_LOG(FG_GENERAL, FG_ALERT, "Bad width specified " << argv[2]); + exit(-1); + } + + 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); + exit(1); + } + + // Initialize the persistant polygon counter. + string counter_file = work_dir + "/../poly_counter"; + poly_index_init( counter_file ); + + 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; + double angle1, angle2, dist; + geo_inverse_wgs_84(0, lat1, lon1, lat2, lon2, &angle1, &angle2, &dist); + cout << "angle1 = " << angle1 << endl; + cout << "angle2 = " << angle2 << endl; + cout << "dist = " << dist << endl; + shape.erase(); + + double x, y, az; + + // Corner 1 + geo_direct_wgs_84(0, lat1, lon1, ANGLE(angle1+90), width/2, &y, &x, &az); + cout << x << '\t' << y << endl; + shape.add_node(0, Point3D(x, y, 0)); + + // Corner 2 + geo_direct_wgs_84(0, lat1, lon1, ANGLE(angle1-90), width/2, &y, &x, &az); + cout << x << '\t' << y << endl; + shape.add_node(0, Point3D(x, y, 0)); + + // Corner 3 + geo_direct_wgs_84(0, lat2, lon2, ANGLE(angle2+90), width/2, &y, &x, &az); + cout << x << '\t' << y << endl; + shape.add_node(0, Point3D(x, y, 0)); + + // Corner 4 + geo_direct_wgs_84(0, lat2, lon2, ANGLE(angle2-90), width/2, &y, &x, &az); + cout << x << '\t' << y << endl; + shape.add_node(0, Point3D(x, y, 0)); + + // Corner 1, again + geo_direct_wgs_84(0, lat1, lon1, ANGLE(angle1+90), width/2, &y, &x, &az); + cout << x << '\t' << y << endl; + shape.add_node(0, Point3D(x, y, 0)); + + // Split into tiles + split_polygon(work_dir, area_type, shape); + } + } + + return 0; +} + +