|
Scientific Visualization and Animation: Examples from Geography
|
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
Notation
/**
* Convert from spherical longitude/latitude to
* 3D rectangular coordinates (with the origin at the
* center of the sphere)
*
* @param lon The longitude in degrees (IN)
* @param lat The latitude in degrees (IN)
* @param x The x-coordinate (OUT)
* @param y The y-coordinate (OUT)
* @param x The z-coordinate (OUT)
*/
void lonlat2xyz(double lon, double lat, double &x, double &y, double &z)
{
double coslat, coslon, sinlat, sinlon;
coslat = cos(lat*RADIANS_PER_DEGREE);
coslon = cos(lon*RADIANS_PER_DEGREE);
sinlat = sin(lat*RADIANS_PER_DEGREE);
sinlon = sin(lon*RADIANS_PER_DEGREE);
x = (coslat * sinlon);
y = (sinlat);
z = (coslat * coslon);
}
#ifndef FEATURE_C
#define FEATURE_C
/**
* A generic geographic feature (e.g., a polygon, piecewise linear curve)
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
struct feature
{
int id; // Unique identifier
char *type; // POLYGON, LINE_STRIP, ...
int size; // Number of vertices
double *lon; // Longitudes
double *lat; // Latitudes
double *x; // Cartesian x-coordinate
double *y; // Cartesian y-coordinate
double *z; // Cartesian z-coordinate
double *xProj; // Projected x-coordinate (for maps)
double *yProj; // Prohected y-coordinate (for maps)
};
#endif
/**
* Create the array of features, read the countries from
* the file, create the polygons, and insert them
* into the array of features
*
* @return The index of the next empty feature
*/
int readPolygons()
{
char name[80];
double lat, lon;
feature *f;
FILE *in;
int countryNumber, k, numberOfCountries;
int numberOfPolygons, polygonNumber, size;
in = fopen("world.txt", "r");
fscanf(in, "%d,%d", &numberOfPolygons, &numberOfCountries);
numberOfFeatures = numberOfPolygons + GRID_SIZE;
features = new feature[numberOfFeatures];
for (k=0; k<numberOfPolygons; k++)
{
fscanf(in, "%d,%d,%d,%s", &polygonNumber, &countryNumber, &size, name);
f = new feature;
initializeFeature(f, size);
f->id = countryNumber;
f->type = "POLYGON";
f->size = size;
for (int i=0; i<size; i++)
{
fscanf(in, "%lf,%lf", &lon, &lat);
setCoordinate(f, i, lon, lat);
}
features[k] = *f;
}
fclose(in);
return k;
}
/**
* Create the lines that comprise the longitude/latitude
* grid and insert them into the array of features
*
* @param firstIndex The index to use for the first line
*/
void createGrid(int firstIndex)
{
feature *f;
int k, size;
k = firstIndex;
// Create the longitude lines
for (int lon=-180; lon<=180; lon+=10) // 37 lines
{
size = 19;
f = new feature;
initializeFeature(f, size);
f->id = 214;
f->type = "LINE_STRIP";
f->size = size;
int i = 0;
for (int lat=-90; lat<=90; lat+=10)
{
setCoordinate(f, i, (double)lon, (double)lat);
i++;
}
features[k] = *f;
k++;
}
// Create the latitude lines
for (int lat=-90; lat<=90; lat+=10) // 19 lines
{
size = 37;
f = new feature;
initializeFeature(f, size);
f->id = 214;
f->type = "LINE_STRIP";
f->size = size;
int i = 0;
for (int lon=-180; lon<=180; lon+=10)
{
setCoordinate(f, i, (double)lon, (double)lat);
i++;
}
features[k] = *f;
k++;
}
}
/**
* Display the Earth
*/
void onDisplay()
{
feature *f;
GLenum type;
GLfloat v[3];
for (int i=0; i<numberOfFeatures; i++)
{
// Get the Feature
f = &features[i];
// Determine the Feature's type
if (strcmp(f->type, "POLYGON") == 0) type = GL_POLYGON;
else if (strcmp(f->type, "LINE_STRIP") == 0) type = GL_LINE_STRIP;
else type = GL_POINTS;
// Begin the graphics primitive
glBegin(type);
{
glColor3fv(colors[f->id]);
for (int j=0; j<f->size; j++)
{
// Use the 3D rectangular coordinates
v[0] = f->x[j];
v[1] = f->y[j];
v[2] = f->z[j];
glVertex3fv(v);
}
}
glEnd();
}
}
/**
* The entry point of the application.
*
* @param argc The number of command line arguments
* @param argv The array of command line arguments
* @return A status code
*/
int main(int argc, char **argv)
{
float min[] = {-3.0, -3.0, -3.0};
float max[] = { 3.0, 3.0, 3.0};
int k;
// Create the array of colors
initializeColors();
// Create the Feature set
k = readPolygons();
createGrid(k);
// Create and initialize the SVA window
svaCreate(argc, argv, min, max);
svaShowAxes(false);
// Start the SVA visualization
svaStartVisualization();
}
Projection Surfaces
Light Sources
The World
/**
* Project from spherical longitude/latitude to
* 2D rectangular coordinates (with the origin at the
* equator and Greenwich meridian)
*
* @param lon The longitude in degrees (IN)
* @param lat The latitude in degrees (IN)
* @param x The x-coordinate (OUT)
* @param y The y-coordinate (OUT)
*/
void cylindricalEqualArea(double lon, double lat, double &x, double &y)
{
x = lon*RADIANS_PER_DEGREE;
y = sin(lat*RADIANS_PER_DEGREE);
}
/**
* Display the Earth
*/
void onDisplay()
{
feature *f;
GLenum type;
GLfloat v[3];
for (int i=0; i<numberOfFeatures; i++)
{
// Get the Feature
f = &features[i];
// Determine the Feature's type
if (strcmp(f->type, "POLYGON") == 0) type = GL_POLYGON;
else if (strcmp(f->type, "LINE_STRIP") == 0) type = GL_LINE_STRIP;
else type = GL_POINTS;
// Begin the graphics primitive
glBegin(type);
{
glColor3fv(colors[f->id]);
for (int j=0; j<f->size; j++)
{
// Use the projected coordinates
v[0] = f->xProj[j];
v[1] = f->yProj[j];
v[2] = 0.0;
glVertex3fv(v);
}
}
glEnd();
}
}