/* Generated by XDS Modula-2 to ANSI C v4.20 translator */ #define X2C_int32 #define X2C_index32 #ifndef libsrtm_H_ #include "libsrtm.h" #endif #define libsrtm_C_ #include "Windows.h" #ifndef aprsstr_H_ #include "aprsstr.h" #endif #ifndef osi_H_ #include "osi.h" #endif #ifndef Storage_H_ #include "Storage.h" #endif #ifndef aprspos_H_ #include "aprspos.h" #endif unsigned long libsrtm_srtmmem; unsigned long libsrtm_srtmmaxmem; char libsrtm_srtmdir[1024]; /* get altitude out of srtm files directory tree by oe5dxl */ #define libsrtm_SRTMXY 3600 #define libsrtm_STRIPS 3 #define libsrtm_AGELEVELS 5 typedef short * pSRTMSTRIP; struct SRTMTILE; typedef struct SRTMTILE * pSRTMTILE; struct SRTMTILE { unsigned char typ; HANDLE fd; unsigned char used[3][3600]; pSRTMSTRIP strips[3][3600]; }; typedef pSRTMTILE SRTMLAT[180]; typedef pSRTMTILE * pSRTMLAT; typedef pSRTMLAT SRTMLONG[360]; struct _0; struct _0 { HANDLE fd; char havefile; /* have tried to open file */ }; typedef struct _0 SRTM30FD[9][4]; static SRTMLONG srtmcache; static pSRTMTILE srtmmiss; /* cache no file info with pointer to here */ static SRTM30FD srtm30fd; /* open srtm30 files */ #define libsrtm_SRTM3DIR "srtm3" #define libsrtm_SRTM1DIR "srtm1" #define libsrtm_SRTM30DIR "srtm30" /* === srtm lib */ extern HANDLE libsrtm_opensrtm(unsigned char t, unsigned long tlat, unsigned long tlong) { char s[21]; unsigned long xd; unsigned long yi; unsigned long xi; unsigned long n; HANDLE f; char path[1025]; aprsstr_Assign(path, 1025ul, libsrtm_srtmdir, 1024ul); if (t==3U) aprsstr_Append(path, 1025ul, "\\srtm3\\", 8ul); else if (t==1U) aprsstr_Append(path, 1025ul, "\\srtm1\\", 8ul); if (t<=3U) { if (tlat<90UL) { s[0U] = 'S'; n = 90UL-tlat; } else { s[0U] = 'N'; n = tlat-90UL; } s[1U] = (char)(n/10UL+48UL); s[2U] = (char)(n%10UL+48UL); if (tlong<180UL) { s[3U] = 'W'; n = 180UL-tlong; } else { s[3U] = 'E'; n = tlong-180UL; } s[4U] = (char)(n/100UL+48UL); s[5U] = (char)((n/10UL)%10UL+48UL); s[6U] = (char)(n%10UL+48UL); s[7U] = '.'; s[8U] = 'h'; s[9U] = 'g'; s[10U] = 't'; s[11U] = 0; aprsstr_Append(path, 1025ul, s, 21ul); return osi_OpenRead(path, 1025ul); } else { aprsstr_Append(path, 1025ul, "\\srtm30\\", 9ul); xi = tlong/40UL; xd = xi*40UL; if (xd<180UL) { s[0U] = 'W'; n = 180UL-xd; } else { s[0U] = 'E'; n = xd-180UL; } s[1U] = (char)(n/100UL+48UL); s[2U] = (char)((n/10UL)%10UL+48UL); s[3U] = (char)(n%10UL+48UL); if (tlat>=130UL) { s[4U] = 'N'; s[5U] = '9'; yi = 3UL; } else if (tlat>=80UL) { s[4U] = 'N'; s[5U] = '4'; yi = 2UL; } else if (tlat>=30UL) { s[4U] = 'S'; s[5U] = '1'; yi = 1UL; } else { /* does not exist */ yi = 0UL; srtm30fd[xi][0U].fd = osi_InvalidFd; srtm30fd[xi][0U].havefile = 1; } /*WrInt(xi, 4);WrInt(yi, 4); WrInt(ORD(srtm30fd[xi, yi].havefile), 4); */ /*WrInt(srtm30fd[xi, yi].fd, 5); WrStrLn(" x y have fd"); */ if (srtm30fd[xi][yi].havefile) return srtm30fd[xi][yi].fd; s[6U] = '0'; s[7U] = '.'; s[8U] = 'D'; s[9U] = 'E'; s[10U] = 'M'; s[11U] = 0; aprsstr_Append(path, 1025ul, s, 21ul); f = osi_OpenRead(path, 1025ul); srtm30fd[xi][yi].fd = f; srtm30fd[xi][yi].havefile = 1; return f; } return 0; } /* end opensrtm() */ #define libsrtm_PURGEALL 10 static void purgesrtm(char all) { unsigned long destmem; unsigned long asize; unsigned long y; unsigned long x; unsigned long yd; unsigned long xd; pSRTMTILE pt; pSRTMLAT pl; pSRTMSTRIP pb; char empty; struct SRTMTILE * anonym; destmem = libsrtm_srtmmaxmem-libsrtm_srtmmaxmem/10UL; for (xd = 0UL; xd<=359UL; xd++) { pl = srtmcache[xd]; if (pl) { for (yd = 0UL; yd<=179UL; yd++) { empty = 1; pt = pl[yd]; if (pt && pt!=srtmmiss) { { /* with */ struct SRTMTILE * anonym = pt; for (y = 0UL; y<=3599UL; y++) { for (x = 0UL; x<=2UL; x++) { pb = anonym->strips[x][y]; if (pb) { if (!all && anonym->used[x][y]>0U) { --anonym->used[x][y]; /* increase age level */ empty = 0; } else { asize = 2400UL; if (anonym->typ>3U) { asize = 240UL; } Storage_DEALLOCATE((X2C_ADDRESS *) &pb, asize); libsrtm_srtmmem -= asize; anonym->strips[x][y] = 0; if ((!all && !empty) && libsrtm_srtmmem<=destmem) return; } } } /* end for */ } /* end for */ /* purged enough now */ if (all || empty) { if (anonym->typ<=3U && anonym->fd!=osi_InvalidFd) { osi_Close(anonym->fd); } Storage_DEALLOCATE((X2C_ADDRESS *) &pt, sizeof(struct SRTMTILE)); libsrtm_srtmmem -= sizeof(struct SRTMTILE); pl[yd] = 0; } } } } /* end for */ if (all) { Storage_DEALLOCATE((X2C_ADDRESS *) &pl, sizeof(SRTMLAT)); libsrtm_srtmmem -= sizeof(SRTMLAT); srtmcache[xd] = 0; } } } /* end for */ if (all) { for (x = 0UL; x<=8UL; x++) { for (y = 0UL; y<=3UL; y++) { if (srtm30fd[x][y].havefile && srtm30fd[x][y].fd!=osi_InvalidFd) { osi_Close(srtm30fd[x][y].fd); srtm30fd[x][y].fd = osi_InvalidFd; } } /* end for */ } /* end for */ } } /* end purgesrtm() */ #define libsrtm_NOALT0 32767.0 static float getsrtm1(unsigned long ilat, unsigned long ilong, unsigned long * div0) /* 1 pixel altitude */ { unsigned long rdsize; unsigned long xdeg; unsigned long ydeg; unsigned long xx; unsigned long y; unsigned long x; unsigned long i; long seek; HANDLE f; pSRTMTILE pt; pSRTMSTRIP pb; long a; unsigned char t; struct SRTMTILE * anonym; struct SRTMTILE * anonym0; unsigned long tmp; *div0 = 1UL; ydeg = ilat/3600UL; xdeg = ilong/3600UL; if (xdeg>359UL || ydeg>179UL) return 32767.0f; if (srtmcache[xdeg]==0) { /* empty lat array */ Storage_ALLOCATE((X2C_ADDRESS *) &srtmcache[xdeg], sizeof(SRTMLAT)); if (srtmcache[xdeg]==0) return 32767.0f; /* out of memory */ libsrtm_srtmmem += sizeof(SRTMLAT); memset((X2C_ADDRESS)srtmcache[xdeg],(char)0,sizeof(SRTMLAT)); } else if (srtmcache[xdeg][ydeg]==srtmmiss) return 32767.0f; /* tile file not avaliable */ pt = srtmcache[xdeg][ydeg]; if (pt==0) { t = 1U; f = libsrtm_opensrtm(1U, ydeg, xdeg); if (f==osi_InvalidFd) { t = 3U; f = libsrtm_opensrtm(3U, ydeg, xdeg); if (f==osi_InvalidFd) { t = 30U; f = libsrtm_opensrtm(30U, ydeg, xdeg); if (f==osi_InvalidFd) { srtmcache[xdeg][ydeg] = srtmmiss; return 32767.0f; } } } /*INC(open); */ Storage_ALLOCATE((X2C_ADDRESS *) &pt, sizeof(struct SRTMTILE)); /* a new 1x1 deg buffer */ if (pt==0) return 32767.0f; libsrtm_srtmmem += sizeof(struct SRTMTILE); { /* with */ struct SRTMTILE * anonym = pt; memset((char *)anonym->strips,(char)0,sizeof(pSRTMSTRIP [3][3600])); memset((char *)anonym->used,(char)0,10800UL); anonym->typ = t; anonym->fd = f; } srtmcache[xdeg][ydeg] = pt; } { /* with */ struct SRTMTILE * anonym0 = pt; *div0 = (unsigned long)anonym0->typ; if (anonym0->typ==1U) { y = ilat%3600UL; x = ilong%3600UL; xx = x/1200UL; x = x%1200UL; } else if (anonym0->typ==3U) { y = (ilat%3600UL)/3UL; x = (ilong%3600UL)/3UL; xx = 0UL; } else { y = (ilat%3600UL)/30UL; x = (ilong%3600UL)/30UL; xx = 0UL; } pb = anonym0->strips[xx][y]; if (pb==0) { if (anonym0->typ==1U) { seek = (long)((3599UL-y)*7202UL+xx*2400UL); rdsize = 2400UL; } else if (anonym0->typ==3U) { seek = (long)((1199UL-y)*2402UL); rdsize = 2400UL; } else { seek = (long)((xdeg%40UL)*240UL)-(long)((ilat/30UL)*9600UL); if (ydeg>=130UL) seek += 207350400L; else if (ydeg>=80UL) seek += 149750400L; else if (ydeg>=30UL) seek += 92150400L; else return 32767.0f; rdsize = 240UL; /* fill 1/10 buffer */ } /*INC(miss); */ Storage_ALLOCATE((X2C_ADDRESS *) &pb, rdsize); if (pb==0) return 32767.0f; libsrtm_srtmmem += rdsize; anonym0->strips[xx][y] = pb; osi_Seek(anonym0->fd, (unsigned long)seek); if (osi_RdBin(anonym0->fd, (char *)pb, 2400u/1u, rdsize)!=(long)rdsize) { tmp = rdsize/2UL-1UL; i = 0UL; if (i<=tmp) for (;; i++) { pb[i] = 32767; if (i==tmp) break; } /* end for */ } else { /* c-translator frissts nicht FOR i:=0 TO rdsize DIV 2-1 DO pb^[i]:=pb^[i]<<8 + pb^[i] >>8 END; (* motorola format *) */ tmp = rdsize/2UL-1UL; i = 0UL; if (i<=tmp) for (;; i++) { pb[i] = (short)(X2C_LSH((unsigned short)pb[i],16, 8)|X2C_LSH((unsigned short)pb[i],16,-8)); if (i==tmp) break; } /* end for */ } } /* motorola format */ /*ELSE INC(hit); */ /* IF used[xx][y]used[xx][y] = 5U; a = (long)pb[x]; if (a>30000L || a<-30000L) return 32767.0f; return (float)a; } } /* end getsrtm1() */ #define libsrtm_NOALT 32767.0 #define libsrtm_ERRALT 30000.0 extern float libsrtm_getsrtm(struct aprsstr_POSITION pos, unsigned long quality, float * resolution) { unsigned long d; unsigned long div0; unsigned long ilong; unsigned long ilat; float vy; float vx; float a3; float a2; float a1; float a0; /*limpos(pos); */ if (libsrtm_srtmmaxmem>0UL && libsrtm_srtmmem>libsrtm_srtmmaxmem) { /*WrInt(srtmmem, 15); */ purgesrtm(0); } /*WrInt(srtmmem, 15);WrStrLn(" purged"); */ pos.lat = 3.24E+5f+pos.lat*2.0626480625299E+5f; pos.long0 = 6.48E+5f+pos.long0*2.0626480625299E+5f; if (pos.lat>=0.0f) { ilat = (unsigned long)X2C_TRUNCC(pos.lat,0UL,X2C_max_longcard); } else ilat = 0UL; if (pos.long0>=0.0f) { ilong = (unsigned long)X2C_TRUNCC(pos.long0,0UL,X2C_max_longcard); } else ilong = 0UL; a0 = getsrtm1(ilat, ilong, &div0); if (div0==1UL) { *resolution = 30.0f; if (quality>29UL) return a0; } else if (div0==3UL) { *resolution = 90.0f; if (quality>60UL) return a0; } else { *resolution = 900.0f; if (quality>300UL) return a0; } /*interpolate 4 dots */ a1 = getsrtm1(ilat, ilong+div0, &d); a2 = getsrtm1(ilat+div0, ilong, &d); a3 = getsrtm1(ilat+div0, ilong+div0, &d); if (a0>30000.0f) { /* ignore missing pixels */ a0 = a1; if (a0>30000.0f) { a0 = a2; if (a0>30000.0f) { a0 = a3; if (a0>30000.0f) return 32767.0f; } } } if (a1>30000.0f) a1 = a0; if (a2>30000.0f) a2 = a0; if (a3>30000.0f) a3 = a0; if (div0==1UL) { /* interpolation wights */ vx = pos.long0-(float)ilong; vy = pos.lat-(float)ilat; } else if (div0==3UL) { vx = (pos.long0-(float)((ilong/3UL)*3UL))*3.3333333333333E-1f; vy = (pos.lat-(float)((ilat/3UL)*3UL))*3.3333333333333E-1f; } else { vx = (pos.long0-(float)((ilong/30UL)*30UL))*3.3333333333333E-2f; vy = (pos.lat-(float)((ilat/30UL)*30UL))*3.3333333333333E-2f; } return (a0*(1.0f-vx)+a1*vx)*(1.0f-vy)+(a2*(1.0f-vx)+a3*vx)*vy; /* wighted median of 4 pixels*/ } /* end getsrtm() */ extern void libsrtm_initsrtm(void) { unsigned long yi; unsigned long xi; /*WrStrLn(" inits"); */ /*open:=0; miss:=0; hit:=0; */ memset((char *)srtmcache,(char)0,sizeof(SRTMLONG)); for (xi = 0UL; xi<=8UL; xi++) { for (yi = 0UL; yi<=3UL; yi++) { srtm30fd[xi][yi].havefile = 0; } /* end for */ } /* end for */ } /* end initsrtm() */ extern void libsrtm_closesrtmfile(void) { /*WrStrLn(" closes"); */ purgesrtm(1); /*WrInt(open, 10); WrInt(miss, 10); WrInt(hit, 10); WrStrLn(" open miss hit"); */ libsrtm_initsrtm(); } /* end closesrtmfile() */ /* === srtm lib */ /* === geoid lib */ #define libsrtm_GEOIDFN "WW15MGH.DAC" #define libsrtm_RESOL 4 /* 1/deg */ #define libsrtm_LONGS 1440 /* values in file around a latitude */ static float rdgeoid(HANDLE fd, long lat, long long0, char * ok0) { char b[2]; long n; osi_Seek(fd, (unsigned long)((lat*1440L+long0)*2L)); if (osi_RdBin(fd, (char *)b, 2u/1u, 2UL)!=2L) { n = 0L; /* no data in file */ n = 0L; *ok0 = 0; } else { n = (long)((unsigned long)(unsigned char)b[1U]+(unsigned long) (unsigned char)b[0U]*256UL); if (n>=32768L) n -= 65536L; } return (float)n; } /* end rdgeoid() */ extern float libsrtm_egm96(struct aprsstr_POSITION pos, char * ok0) /* read and interpolate geoid correction from datafile */ { long ilong; long ilat; HANDLE fd; float g; float flong; float flat; char path[1025]; aprsstr_Assign(path, 1025ul, libsrtm_srtmdir, 1024ul); if (path[0]) aprsstr_Append(path, 1025ul, "\\", 2ul); aprsstr_Append(path, 1025ul, "WW15MGH.DAC", 12ul); fd = osi_OpenRead(path, 1025ul); *ok0 = fd!=osi_InvalidFd; g = 0.0f; if (*ok0) { pos.lat = 90.0f-pos.lat*5.729577951472E+1f; pos.long0 = pos.long0*5.729577951472E+1f; if (pos.long0<0.0f) pos.long0 = 360.0f+pos.long0; pos.lat = pos.lat*4.0f; pos.long0 = pos.long0*4.0f; if (pos.lat>=0.0f) { ilat = (long)(unsigned long)X2C_TRUNCC(pos.lat,0UL, X2C_max_longcard); } else ilat = 0L; if (pos.long0>=0.0f) { ilong = (long)(unsigned long)X2C_TRUNCC(pos.long0,0UL, X2C_max_longcard); } else ilong = 0L; flat = pos.lat-(float)ilat; flong = pos.long0-(float)ilong; g = ((rdgeoid(fd, ilat, ilong, ok0)*(1.0f-flat)+rdgeoid(fd, ilat+1L, ilong, ok0)*flat)*(1.0f-flong)+(rdgeoid(fd, ilat, ilong+1L, ok0)*(1.0f-flat)+rdgeoid(fd, ilat+1L, ilong+1L, ok0)*flat)*flong)*0.01f; osi_Close(fd); } return g; } /* end egm96() */ extern void libsrtm_BEGIN(void) { static int libsrtm_init = 0; if (libsrtm_init) return; libsrtm_init = 1; aprspos_BEGIN(); aprsstr_BEGIN(); osi_BEGIN(); Storage_ALLOCATE((X2C_ADDRESS *) &srtmmiss, 1UL); /* make empty tile for fast nofile hint */ libsrtm_initsrtm(); libsrtm_srtmmem = 0UL; libsrtm_srtmmaxmem = 0UL; /* 0 no auto purge */ libsrtm_srtmdir[0] = 0; }