/*[LISTING THREE]*/
/* ---------------------------------------------------------------- *
* BUILD Program: Construct a seamless global database of line *
* segments from text files defining the location of line vertices. *
* Two levels of detail are provided: dense and sparse. The input *
* consists of two flat ASCII text files; one each for dense and *
* sparse coastline segment vertices. The segment is begun with a *
* line containing an asterisk marker (*) as its first character. *
* The remainder of such line is ignored, and may be used to name *
* the segment. End-of-file is signalled by a similar marker line. *
* Line segment vertex coordinates follow each marker line, one *
* latitude/longitude pair per line. Coordinates are given in *
* degrees, as free-format, white-space or comma delimited decimal *
* fraction character strings. Numbers are signed according to *
* the international geographic coordinates sign convention: *
* westerly longitudes and southerly latitudes are negative. *
* ---------------------------------------------------------------- */
#include
#include
#include
#include "algebra.c"
#define LINE_LNGTH 128
#define MAX_VRTX 1024
void buildFiles(FILE *, FILE *, FILE *);
void main(void) {
FILE *fpTextLines;
FILE *fpIndex;
FILE *fpCoords;
char *fnTextLines0 = "coast0.lns"; /* dense input segments */
char *fnTextLines1 = "coast1.lns"; /* sparse input segments */
char *fnIndex0 = "coast0.idx"; /* dense database index */
char *fnIndex1 = "coast1.idx"; /* sparse database index */
char *fnCoords = "coast.dat"; /* composite coordinate file */
/* ---------------------------------------------------------------- */
if ((fpTextLines = fopen(fnTextLines1, "rt")) == NULL) {
fprintf(stderr,"Input file (%s) open failed.\n", fnTextLines1);
exit(1);
}
if ((fpIndex = fopen(fnIndex1, "wb")) == NULL) {
fprintf(stderr,"Index file (%s) open failed.\n", fnIndex1);
exit(1);
}
if ((fpCoords = fopen(fnCoords, "wb")) == NULL) {
fprintf(stderr,"Data file (%s) open failed.\n", fnCoords);
exit(1);
}
fprintf(stderr, "\nSparse line segment input file...\n");
buildFiles(fpTextLines, fpIndex, fpCoords);
fclose(fpTextLines);
fclose(fpIndex); /* Note that the coordinate file stays open! */
if ((fpTextLines = fopen(fnTextLines0, "rt")) == NULL) {
fprintf(stderr,"Input file (%s) open failed.\n", fnTextLines0);
exit(1);
}
if ((fpIndex = fopen(fnIndex0, "wb")) == NULL) {
fprintf(stderr,"Index file (%s) open failed.\n", fnIndex0);
exit(1);
}
fprintf(stderr, "\nDense line segment input file...\n");
buildFiles(fpTextLines, fpIndex, fpCoords);
fclose(fpTextLines);
fclose(fpIndex);
fclose(fpCoords);
fprintf(stderr, "\nTwo-level coastline database created:\n");
fprintf(stderr, "Index files: %s, %s\n", fnIndex0, fnIndex1);
fprintf(stderr, "Coordinate data file: %s\n", fnCoords);
}
/* ---- Read Line Segment File, Write Index File and Vertex Coordinates ---- */
void buildFiles(FILE *fpTextLines, FILE *fpIndex, FILE *fpCoords) {
static struct vct3 vertex[MAX_VRTX];
struct indexRec indexRec;
struct plpt stereoPlaneVertex;
struct ltln inVertex;
struct lclpt shortVertex;
double s, d;
int i, fileLine, lineCount;
long totalVertexCount;
char inLine[LINE_LNGTH + 1];
/* ---------------------------------------------------------------- */
fileLine = lineCount = indexRec.vertexCount = 0;
indexRec.segmentId = 0;
totalVertexCount = 0L;
while (fgets(inLine, LINE_LNGTH, fpTextLines)) {
fileLine++;
if (inLine[0] == '*') { /* line segment header, end-of-file? */
if (indexRec.vertexCount) { /* process accumulated segment */
fprintf(stderr,"line:%d vertices:%d \r",
lineCount, indexRec.vertexCount);
indexRec.center.di = 0.0; /* find object "center" */
indexRec.center.dj = 0.0;
indexRec.center.dk = 0.0;
for (i = 0; i < indexRec.vertexCount; i++) {
indexRec.center.di += vertex[i].di;
indexRec.center.dj += vertex[i].dj;
indexRec.center.dk += vertex[i].dk;
}
NormalizeDcos3(&indexRec.center);
indexRec.radius = 0.0; /* center-far-vertex distance */
for (i = 0; i < indexRec.vertexCount; i++) {
d = ArcDist(&indexRec.center, vertex + i);
if (d > indexRec.radius) indexRec.radius = d;
}
if (indexRec.radius < 1.0e-10) {
indexRec.radius = 0.0;
s = 0.0;
}
else s = LC_SCALE / indexRec.radius;
indexRec.fileOffset = ftell(fpCoords);
fwrite(&indexRec, sizeof(struct indexRec), 1, fpIndex);
for (i = 0; i < indexRec.vertexCount; i++) {
MapStereo(&indexRec.center, vertex + i,
&stereoPlaneVertex);
shortVertex.est = (short)(s * stereoPlaneVertex.est);
shortVertex.nrt = (short)(s * stereoPlaneVertex.nrt);
fwrite(&shortVertex, sizeof(struct lclpt),1, fpCoords);
}
totalVertexCount += indexRec.vertexCount;
indexRec.vertexCount = 0;
lineCount++;
}
}
else { /* next in a series of line segment vertices */
inVertex.lat = DEG2RAD * atof(strtok(inLine, " ,\t\n"));
inVertex.lng = DEG2RAD * atof(strtok(NULL, " ,\t\n"));
if (((fabs(inVertex.lat) < 1.0e-10)
&& (fabs(inVertex.lng) < 1.0e-10)) /* 0.0 lat, 0.0 long? */
|| (fabs(inVertex.lat) > 0.5 * PI)
|| (fabs(inVertex.lng) > PI)) { /* lat/long out of range? */
fprintf(stderr,"\nBad data, file line %d", fileLine);
exit(1);
}
if (indexRec.vertexCount == MAX_VRTX) {
fprintf(stderr,"\nSegment vertex buffer overflow...");
exit(1);
}
LatLongToDcos3(&inVertex, vertex + indexRec.vertexCount++);
}
}
fprintf(stderr,"...processed, line segments:%d, vertices:%ld\n",
lineCount, totalVertexCount);
}