1
0
Fork 0

These add a --min-angle options to fgfs-tools-client,

and make the E00 support a lot more robust.
This commit is contained in:
curt 2001-01-29 04:30:31 +00:00
parent 1190702047
commit 528c12a682
9 changed files with 1013 additions and 406 deletions

View file

@ -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 {

View file

@ -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);

View file

@ -44,6 +44,7 @@ enum AreaType {
IntLakeArea,
ReservoirArea,
IntReservoirArea,
FreewayArea,
RoadArea,
RailroadArea,
StreamArea,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}