1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
/* topo.c */
/*
* Earth topography
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "binio.h"
static float Topo_westlon, Topo_eastlon, Topo_northlat, Topo_southlat;
static int Topo_rows, Topo_cols;
static short *TopoData;
/*** load_topo ********************************************************
Read a topography file and initialize Topo and TopoData.
Input: filename - name of topo file.
Return: 0 if error, otherwise non-zero for success.
**********************************************************************/
int load_topo( char filename[] )
{
static int already_loaded = 0;
int f;
char id[40];
if (!already_loaded) {
f = open( filename, O_RDONLY );
if (f<0) {
/* printf("Topo file %s not found\n", filename );*/
return 0;
}
/* Read file header */
read_bytes( f, id, 40 );
if (strcmp(id,"TOPO")==0) {
/* OLD STYLE: bounds given as ints */
int k;
read_int4( f, &k ); Topo_westlon = k / 100.0;
read_int4( f, &k ); Topo_eastlon = k / 100.0;
read_int4( f, &k ); Topo_northlat = k / 100.0;
read_int4( f, &k ); Topo_southlat = k / 100.0;
}
else if (strcmp(id,"TOPO2")==0) {
/* NEW STYLE: bounds given as floats */
read_float4( f, &Topo_westlon );
read_float4( f, &Topo_eastlon );
read_float4( f, &Topo_northlat );
read_float4( f, &Topo_southlat );
}
else {
printf("%s is not a TOPO file\n", filename);
close(f);
return 0;
}
read_int4( f, &Topo_rows );
read_int4( f, &Topo_cols );
/* allocate storage for the topo values */
TopoData = (short *) malloc( Topo_rows*Topo_cols*sizeof(short) );
if (!TopoData) {
close(f);
return 0;
}
/* read the topo values */
read_int2_array( f, TopoData, Topo_rows*Topo_cols );
/* all done */
close(f);
already_loaded = 1;
}
return 1;
}
static int LatSamples = 1;
static int LonSamples = 1;
/*
* Before calling the elevation function below, one should first call
* this function to indicate approximately how many degrees of latitude
* and longitude are between adjacent samplings (i.e. calls to elevation()).
* With this hint we can determine how many samples of the topography to
* take then average together in the elevation() function.
* Input: latres - latitude resolution
* lonres - longitude resolution
*/
void set_topo_sampling( float latres, float lonres )
{
LatSamples = (int) (latres / ((Topo_northlat-Topo_southlat) / (Topo_rows-1)));
LonSamples = (int) (lonres / ((Topo_westlon-Topo_eastlon) / (Topo_cols-1)));
if (LatSamples<=0) LatSamples = 1;
if (LonSamples<=0) LonSamples = 1;
}
/* TODO: sampling */
/*** elevation ********************************************************
Return the elevation of the topography at location (lat,lon) and a
flag indicating water or land.
Input: lat, lon - location in degrees
water - pointer to integer
Output: water - set to 1 if water, 0 if land.
Returned: elevation in meters at (lat,lon) or 0 if error.
**********************************************************************/
float elevation( float lat, float lon, int *water )
{
float fr, fc;
int rowa, cola, rowb, colb;
float hgt;
int count, r, c;
int val, watcount;
if (!TopoData || lon<Topo_eastlon || lon>Topo_westlon
|| lat<Topo_southlat || lat>Topo_northlat) {
if (water)
*water = 0;
return 0.0;
}
/* Return elevation at (lat,lon) by sampling LatSamples x LonSamples */
/* values centered at that location. */
/* calculate range of rows */
fr = Topo_rows * (lat - Topo_northlat) / (Topo_southlat - Topo_northlat);
rowa = (int) fr - LatSamples/2;
rowb = rowa+LatSamples;
if (rowa<0)
rowa = 0;
if (rowb>=Topo_rows)
rowb = Topo_rows-1;
/* calculate range of columns */
fc = Topo_cols * (lon-Topo_westlon) / (Topo_eastlon - Topo_westlon);
cola = (int) fc - LonSamples/2;
colb = cola+LonSamples;
if (cola<0)
cola = 0;
if (colb>=Topo_cols)
colb = Topo_cols-1;
/* find average height in sample area */
hgt = 0.0;
count = watcount = 0;
for (r=rowa;r<=rowb;r++) {
for (c=cola;c<=colb;c++) {
val = TopoData[r*Topo_cols+c];
if (val&1)
watcount++;
hgt += (float) (val / 2);
count++;
}
}
hgt = hgt / (float) count;
/* calculate water flag */
if (water) {
if (watcount>count/2)
*water = 1;
else
*water = 0;
}
return hgt;
}
/*
* Deallocate memory used for storing topography.
*/
void free_topo( void )
{
if (TopoData) {
free( TopoData );
TopoData = NULL;
}
}
|