(* gcc -o panorama Lib.o aprspos.o aprsstr.o flush.o libsrtm.o osi.o pngwrite.o panorama.o /usr/local/xds/lib/x86/libts.a /usr/local/xds/lib/x86/libxds.a -lm libz.a filesize.o imagetext.o pngread.o libpng.a libz.a libjpeg.a *) <*+M2EXTENSIONS *> <*-CHECKDIV *> <*-CHECKRANGE *> <*-GENFRAME*> <*-COVERFLOW *> <*-IOVERFLOW*> <*-NOPTRALIAS*> <*-DOREORDER*> <*-PROCINLINE*> <*-GENPTRINIT*> <*+STORAGE *> <*CPU="PENTIUM"*> <* IF __GEN_C__ THEN *> <*+M2EXTENSIONS *> <*+STORAGE *> <*-GENCTYPES*> <*+COMMENT*> <*-GENHISTORY*> <*-GENDEBUG*> <*-GENDATE*> <*-LINENO*> <*-CHECKINDEX*> <*-CHECKDINDEX*> <*+GENCDIV*> <*-GENKRC*> <*+NOOPTIMIZE*> <*-GENSIZE*> <*-ASSERT*> <*-CHECKNIL*> <*-COVERFLOW*> <*-IOVERFLOW*> <*-CHECKRANGE*> <*-CHECKSET*> <*-CHECKDIV*> <*-GENCONSTENUM*> <*-ASSERT*> <* ELSE *> <*+GENHISTORY*> <*+GENDEBUG*> <*+LINENO*> <*+CHECKNIL*> <*+CHECKINDEX*> <*+CHECKDINDEX*> <*HEAPLIMIT="1000000000"*> <* END *> MODULE panorama; (* make panorama image with srtm data by oe5dxl *) FROM SYSTEM IMPORT FILL, ADR, INT16, INT8, CAST, CARD8, CARD16, SHIFT; FROM osi IMPORT Werr, WrStr, WrStrLn, WrInt, File, OpenWrite, Close, WrBin, WrFixed, ALLOCATE, DEALLOCATE, NextArg, RdBin, FdValid, OpenRead, Flush; FROM libsrtm IMPORT getsrtm, srtmdir, closesrtmfile, srtmmaxmem, getsrtmlong, METAINFO, pMETAINFO, ATTRWATER, ATTRWOOD, ATTRURBAN, accessescached, accesses; FROM aprsstr IMPORT POSITION, IntToStr, Append, Assign, DateToStr, FixToStr, Length, loctopos, StrToFix, StrToInt, StrToCard, TIME, InStr; IMPORT pngwrite, pngread, osi; FROM imagetext IMPORT pIMAGE, writestr, strsize, fontsizex, fontsizey; FROM math IMPORT sqrt, sin, cos, tan, atan, exp, log, pow, floor, fmod, asin; CONST TESTX=2; TESTY=359; PI=3.1415926535; PI2=PI*2.0; RAD=PI2/360.0; EARTH=6370.0; NOALT=20000; NL=12C; LF=12C; REFRACC=0.0000000785; MAXSYMSIZE=48; (* max input symbol size *) SUNSIZE=0.55*0.5*RAD; SHOWTREEDIST=20; (* show trees m from cam *) ZEROTREEALT=2600; FULLTREEALT=1200; TREERASTERSIZE=8.0; (* default m full treesize *) STAMTHICKNESS=0.015; TREEFORM=0.9; (* 0.9 *) STAMLEN=0.35; MINTREESIZE=3; NOISESIZE=1024; MAXHIST=250; MINHIST=10; MAXLUM=16383; TREERAND=3; (* tree position noise *) LUMMUL=8.0; (* real to cardinal colour values in main image *) ALTICOLORANG=1000; (* colourized altitude *) WATERMIRRORGAP=0.2; (* m over water start ray path *) WATERSURFACEDUST=0.6; WAVLEN=5000000.0; TREENOTCH=0.3; (* random tree kill *) cFOGLUMr=900.0; (* low elevation heaven light *) cFOGLUMg=1250.0; cFOGLUMb=2300.0; SUNLUM=5000.0; cMAXCHROMr=1.0; (* sun passed thu air *) cMAXCHROMg=0.9; cMAXCHROMb=0.6; (*0.8*) cFARCHROMr=1.0; (* sun in space *) cFARCHROMg=1.0; cFARCHROMb=1.0; cMEADOWr=310.0*0.8; cMEADOWg=430.0*0.8; cMEADOWb=215.0*0.8; (* 235 *) cMEADOWVOIDr=458.0*0.9; cMEADOWVOIDg=458.0*0.9; cMEADOWVOIDb=429.0*0.9; cCOASTSANDr=380.0; cCOASTSANDg=450.0; cCOASTSANDb=450.0; cSNOWr=840.0; (*940 930 920 *) cSNOWg=830.0; cSNOWb=820.0; cSNOWSHADOWr=79.0; (*100 145 280*) cSNOWSHADOWg=115.0; cSNOWSHADOWb=220.0; cSTAMr=140.0*0.7; (* 292 271 249 *) cSTAMg=130.0*0.7; cSTAMb=120.0*0.7; cSTAMVAR=15.0; cTREEr=210.0*0.72; (* 200 245 190 *0.85 *) cTREEg=270.0*0.72; cTREEb=225.0*0.72; cCITYCOL=400.0; cCITYMEADOWr=258.0; cCITYMEADOWg=366.0; cCITYMEADOWb=292.0; cCITYSTREETr=249.0; cCITYSTREETg=282.0; cCITYSTREETb=282.0; cCITYDUSTr=0.18; cCITYDUSTg=0.15; cCITYDUSTb=0.1; cROCKr=418; cROCKg=458; cROCKb=448; cUNDERWATERr=360.0*0.5; (* 360 360 330 * 0.6 *) cUNDERWATERg=320.0*0.5; cUNDERWATERb=300.0*0.5; cWATERALIASr=120.0; (* basic watercolour 33 81 99 *0.9 *) cWATERALIASg=170.0; cWATERALIASb=220.0; cHEAVENr=150.0; cHEAVENg=300.0; cHEAVENb=3500.0; cLAMPHr=0.3; cLAMPHg=0.24; cLAMPHb=0.2; cLAMPWr=0.3; cLAMPWg=0.3; cLAMPWb=0.3; cLAMPTr=0.4; cLAMPTg=0.1; cLAMPTb=0.0; TYPE SET8=SET OF [0..7]; SET16=SET OF [0..15]; SET32=SET OF [0..31]; COL=RECORD r,g,b:REAL END; CCOL=RECORD r,g,b:CARDINAL END; SCREENTYPE=(eCURVED, eFLAT, eCAMERA); POSITIONL=RECORD long, lat:LONGREAL; END; PANOWIN=RECORD flatscreen:SCREENTYPE; eye, horizon:POSITIONL; eyealt, eyeog, angle, elevation, yzoom, refract:REAL; hx, hy, mx, my:INTEGER; (* mouse pos on panwin and fullwin *) minlum, maxlum:CARDINAL; (* hint for text contrast *) sunazi, sunele, hseg, dist:REAL; (* poi fast preselect circular segment *) image:pIMAGE; END; PIX8A=RECORD r8, g8, b8, alpha:CARD8 END; (* colour pixel with alpha *) SYMBOL=ARRAY[0..MAXSYMSIZE-1] OF ARRAY[0..MAXSYMSIZE-1] OF PIX8A; pPOI=POINTER TO POI; POI=RECORD next:pPOI; r,g,b,alpha:CARDINAL; symbol, woodsymbol:SYMBOL; xs,ys:CARDINAL; altIsOG, withwoodicon:BOOLEAN; prio:CARD8; poifn, iconfn, iconwoodfn, iconhint:ARRAY[0..1023] OF CHAR; END; pPOISTORE=POINTER TO POISTORE; POISTORE=RECORD next:pPOISTORE; pp:pPOI; x, y:REAL; prio:CARDINAL; dist:REAL; thrutree:BOOLEAN; textposx:INTEGER; text:ARRAY[0..50] OF CHAR; END; pWAYPOINTS=POINTER TO WAYPOINTS; WAYPOINTS=RECORD wps:ARRAY[0..63] OF RECORD pos:POSITIONL; alt:REAL END; next:pWAYPOINTS; END; pPOIMAP=POINTER TO POIMAP; (* store image columns with poi text *) POIMAP=ARRAY OF SET32; pTRACK=POINTER TO TRACK; TRACK=RECORD next:pTRACK; r,g,b, altmode:CARDINAL; width, fd:INTEGER; cnt:CARDINAL; fn:ARRAY[0..99] OF CHAR; END; NORMVEC=RECORD x,y,z:REAL END; LVEC=RECORD x,y,z:LONGREAL END; ROTVEC=RECORD sx,cx,sy,cy:LONGREAL END; RGB=RECORD r,g,b:REAL END; GLANCESET=RECORD sunvec, eyevec, surfacevec:NORMVEC END; TREEHINT=RECORD hith, hitx, hity, sx,sy, peakh, areapeak, regionpeak, hitradius, stamtoeye, og, passdist, aliasm, missspace:REAL; nx, ny:INTEGER; treepass, isstam:BOOLEAN; tslant, varh, rooth:REAL; meta:METAINFO; nvec:NORMVEC; water, wood, urban:CARD8; END; TREEHINTS=ARRAY[FALSE..TRUE] OF TREEHINT; NOISEMAP=ARRAY[0..NOISESIZE-1] OF ARRAY[0..NOISESIZE-1] OF REAL; ALTCOLTAB=RECORD c:ARRAY[0..1023] OF CCOL; tag:ARRAY[0..5] OF CCOL; len:CARDINAL; END; pDROPSHADOW=POINTER TO DROPSHADOW; DROPSHADOW=RECORD next:pDROPSHADOW; dist, alt:LONGREAL; colum:INTEGER; END; DDSTACK=RECORD startdist:REAL; stoppalt:REAL; END; VAR image :pIMAGE; poifiles :pPOI; trackfiles :pTRACK; dateh, timeh, imagefn, csvfn, colfn:ARRAY[0..1023] OF CHAR; xsize, ysize:INTEGER; posa, posb, teye :POSITIONL; refraction, igamma, elev, angle, yzoom, wavelength, waterslant:REAL; gammatab :ARRAY[0..MAXLUM] OF CHAR; millisec, altcolstep, rastercsv, poisize, scalesize, whitelim, blacklim, poilabel, fonttypfoot, fonttyp :CARDINAL; watercol, heavencol :COL; desertcol :RGB; dropshadows, alticolour, defaultocean, verb, flatwater :BOOLEAN; flatscreen :SCREENTYPE; treeraster, coslat, treerasterlat, treerasterlong, treescramblat, treescramblong, maxmountain, rndseed: LONGREAL; surfacedust, waterglance, watertransparency, treerastersize, abscolmin, abscolmax, alticolmin, alticolmax, zerotreealt, fulltreealt, treeshrink, camog, camalt, sunaz, sunel, moonazim,moonelev, moondist, snowalt, slowaltslant, newsnow, waveamp, dusthighpass, treesize, botanicslant, ignorblack, ignorwhite, showstamdist, videolat, logfilm, urbanoff, sandgranularity, minpoialt :REAL; csvfd :INTEGER; csvvec :RECORD act:CARDINAL; v:ARRAY[0..999] OF RECORD p:POSITION; a:REAL; END; END; poirect0, poirect1:POSITION; (* poi fast preselect rectangle *) CRCL, CRCH : ARRAY[0..255] OF CARD8; CRC: ARRAY[0..65535] OF CARD16; noisemap:NOISEMAP; noisevec:ARRAY[0..8191] OF REAL; altcoltab:ALTCOLTAB; freeshadow, newshadow:pDROPSHADOW; poistore:pPOISTORE; poimap:pPOIMAP; debugxi,debugyi:INTEGER; debugx, debugy, debugz, debugg:REAL; PROCEDURE StrToFixL(VAR x:LONGREAL; s-:ARRAY OF CHAR):BOOLEAN; CONST M=MAX(LONGREAL)*0.01; VAR i:CARDINAL; p:LONGREAL; neg, ok:BOOLEAN; BEGIN i:=0; neg:=FALSE; ok:=FALSE; WHILE (i<=HIGH(s)) & (s[i]=" ") DO INC(i) END; IF s[i]="-" THEN neg:=TRUE; INC(i) END; x:=0.0; WHILE (i<=HIGH(s)) & (s[i]>="0") & (s[i]<="9") DO IF x="0") & (s[i]<="9") DO x:=x + p*LFLOAT(ORD(s[i])-ORD("0")); p:=p*0.1; INC(i); ok:=TRUE; END; END; IF neg THEN x:=-x END; RETURN ok & ((i>HIGH(s)) OR (s[i]=0C)) END StrToFixL; PROCEDURE Error(text:ARRAY OF CHAR); BEGIN Werr(text); Werr(" error abort"+LF); HALT END Error; PROCEDURE hex(n:CARDINAL):CHAR; BEGIN n:=n MOD 16; IF n<=9 THEN RETURN CHR(n+ORD("0")) END; RETURN CHR(n+(ORD("A")-10)) END hex; PROCEDURE WrHex(x, digits, len:CARDINAL); VAR i:CARDINAL; s:ARRAY[0..255] OF CHAR; BEGIN IF digits>HIGH(s) THEN digits:=HIGH(s) END; i:=digits; WHILE (i0 DO DEC(digits); s[digits]:=hex(x); x:=x DIV 16; END; WrStr(s); END WrHex; PROCEDURE Random():LONGREAL; BEGIN rndseed:=rndseed + PI; rndseed:=rndseed*rndseed; rndseed:=rndseed*rndseed; rndseed:=rndseed*rndseed; rndseed:=rndseed - LFLOAT(TRUNC(rndseed)); RETURN rndseed END Random; PROCEDURE truncc(r:REAL):CARDINAL; BEGIN IF r<=0.0 THEN RETURN 0 ELSIF r>=2000000000.0 THEN RETURN 2000000000 ELSE RETURN TRUNC(r) END; <* IF NOT __GEN_C__ THEN *> EXCEPT WrStrLn("error in TRUNC() "); RETURN 0 <* END *> END truncc; PROCEDURE Gencrctab; CONST POLINOM=08408H; VAR i,crc,c:CARDINAL; BEGIN FOR c:=0 TO 255 DO crc:=255-c; FOR i:=0 TO 7 DO IF ODD(crc) THEN crc:=CAST(CARDINAL, CAST(BITSET, ASH(crc, -1))/CAST(BITSET,POLINOM)) ELSE crc:=ASH(crc, -1) END; END; CRCL[c]:=crc; CRCH[c]:=255 - ASH(crc, -8); END; crc:=1; FOR i:=0 TO HIGH(CRC) DO IF ODD(crc) THEN crc:=CAST(CARDINAL, CAST(BITSET, ASH(crc, -1))/CAST(BITSET,POLINOM)) ELSE crc:=ASH(crc, -1) END; CRC[i]:=crc; END; END Gencrctab; PROCEDURE frac(r:LONGREAL):REAL; BEGIN RETURN r-floor(r) END frac; PROCEDURE fracint(r:LONGREAL; VAR i:INTEGER):REAL; VAR ri:LONGREAL; BEGIN ri:=floor(r); i:=VAL(INTEGER, ri); RETURN r-ri; END fracint; PROCEDURE min(a,b:REAL):REAL; BEGIN IF ab THEN RETURN a END; RETURN b END max; PROCEDURE imin(a,b:INTEGER):INTEGER; BEGIN IF ab THEN RETURN a END; RETURN b END imax; PROCEDURE sqr(x:REAL):REAL; BEGIN RETURN x*x END sqr; PROCEDURE plus(x:REAL):REAL; BEGIN IF x>=0.0 THEN RETURN x END; RETURN 0.0 END plus; PROCEDURE satan(x:REAL):REAL; (* satturating tan at +-pi/2 *) CONST LIM=PI*0.5-0.0001; BEGIN IF x>=LIM THEN x:=LIM ELSIF x<=-LIM THEN x:=-LIM END; RETURN tan(x) END satan; PROCEDURE one(x:REAL):REAL; BEGIN IF x<0.0 THEN x:=0.0 ELSIF x>1.0 THEN x:=1.0 END; RETURN x END one; PROCEDURE atang2(x, y:REAL):REAL; VAR w:REAL; BEGIN IF ABS(x)>ABS(y) THEN w:=osi.arctan(y/x); IF x<0.0 THEN IF y>0.0 THEN w:=PI+w ELSE w:=w-PI END; END; ELSIF y<>0.0 THEN w:=(PI*0.5-osi.arctan(x/y)); IF y<0.0 THEN w:=w-PI END; ELSE w:=0.0 END; RETURN w END atang2; PROCEDURE atang2l(x, y:LONGREAL):LONGREAL; VAR w:LONGREAL; BEGIN IF ABS(x)>ABS(y) THEN w:=atan(y/x); IF x<0.0 THEN IF y>0.0 THEN w:=PI+w ELSE w:=w-PI END; END; ELSIF y<>0.0 THEN w:=(PI*0.5-atan(x/y)); IF y<0.0 THEN w:=w-PI END; ELSE w:=0.0 END; RETURN w END atang2l; PROCEDURE posvalidl(pos-:POSITIONL):BOOLEAN; BEGIN RETURN (pos.lat<>0.0) OR (pos.long<>0.0) END posvalidl; PROCEDURE distancel(home, dist:POSITIONL):REAL; VAR x, y:REAL; BEGIN x:=ABS(dist.long-home.long); y:=ABS(dist.lat -home.lat); IF (x=0.0) & (y=0.0) THEN RETURN 0.0 ELSIF x+y<0.04 THEN (* near *) x:=x*cos((home.lat+dist.lat)*0.5); RETURN EARTH*sqrt(x*x+y*y) ELSE (* far *) IF x>PI2 THEN x:=PI2-x END; x:=sin(dist.lat)*sin(home.lat) + cos(dist.lat)*cos(home.lat)*cos(x); IF ABS(x)>=1.0 THEN RETURN 0.0 END; RETURN EARTH*osi.arccos(x) END; END distancel; PROCEDURE azimuthl(home,dist:POSITIONL):REAL; VAR h, ldiff:REAL; BEGIN ldiff:=dist.long-home.long; IF (ldiff=0.0) OR (cos(home.lat)=0.0) OR (cos(dist.lat)=0.0) THEN IF home.lat<=dist.lat THEN RETURN 0.0 ELSE RETURN 180.0 END; ELSE h:=360.0/PI2*osi.arctan(cos(home.lat)*((tan(home.lat)*cos(ldiff)-tan(dist.lat))/sin(ldiff))); IF ldiff<0.0 THEN RETURN h+270.0 ELSE RETURN h+90.0 END; END; END azimuthl; PROCEDURE makenoise; VAR x, y:CARDINAL; v:REAL; PROCEDURE swap(w:CARDINAL):CARDINAL; BEGIN RETURN w MOD 256*256+w DIV 256 END swap; BEGIN FILL(ADR(noisemap), 0C, SIZE(noisemap)); FOR y:=0 TO NOISESIZE DO FOR x:=0 TO NOISESIZE-1 DO v:=Random()-0.5; noisemap[y MOD NOISESIZE][x]:=noisemap[y MOD NOISESIZE][x]*0.7 + v; noisemap[y MOD NOISESIZE][x]:=noisemap[y MOD NOISESIZE][x]*0.3333 + noisemap[(y+(NOISESIZE-1)) MOD NOISESIZE][x]*0.3333 + noisemap[(y+1) MOD NOISESIZE][x]*0.3333; END; END; FILL(ADR(noisevec), 0C, SIZE(noisevec)); FOR x:=0 TO HIGH(CRC) DO noisevec[x MOD (HIGH(noisevec)+1)]:=noisevec[x MOD (HIGH(noisevec)+1)]*0.7 + FLOAT(CRC[x])*(1.0/65536.0)-0.5; noisevec[x MOD (HIGH(noisevec)+1)]:=noisevec[(x+HIGH(noisevec)) MOD (HIGH(noisevec)+1)]*0.3333 + noisevec[x MOD (HIGH(noisevec)+1)]*0.3333 + noisevec[(x+1) MOD (HIGH(noisevec)+1)]*0.3333; END; v:=0.0; FOR x:=1 TO HIGH(noisevec) DO v:=noisevec[x]-noisevec[x-1]; IF v>0.1 THEN v:=0.1 ELSIF v<-0.1 THEN v:=-0.1 END; noisevec[x]:=noisevec[x-1]+v; (* IF noisevec[x]>0.0 THEN noisevec[x]:=sqrt(noisevec[x]) ELSIF noisevec[x]<0.0 THEN noisevec[x]:=-sqrt(-noisevec[x]) END; v:=v+(noisevec[x]-v)*0.2; noisevec[x]:=noisevec[x]-v; *) END; v:=0.0; (* normalize level *) FOR x:=0 TO HIGH(noisemap) DO FOR y:=0 TO HIGH(noisemap) DO v:=v+ABS(noisemap[y][x]); END; END; v:=sqr(FLOAT(HIGH(noisemap)+1))/v; FOR x:=0 TO HIGH(noisemap) DO FOR y:=0 TO HIGH(noisemap) DO noisemap[y][x]:=noisemap[y][x]*v; END; END; -- WrFixed(v/sqr(FLOAT(HIGH(noisemap)+1)), 3, 10); WrStrLn(""); END makenoise; (* PROCEDURE rndx(x:LONGREAL):REAL; BEGIN x:=x*10.0; RETURN (sin(x*072030.0)*0.0020-sin(x*1721560.0)*0.0014+sin(x*5303500.0)*0.0033 -sin(x*787666.0)*0.0044+sin(x*1287666.0)*0.0051-sin(x*2355636.0)*0.0065)*5.5; END rndx; PROCEDURE rndy(x:LONGREAL):REAL; BEGIN x:=x*10.0; RETURN (sin(x*104830.0)*0.0014-sin(x*2741560.0)*0.0026-sin(x*6373800.0)*0.0035 +sin(x*986626.0)*0.0032-sin(x*2247676.0)*0.0053+sin(x*3254666.0)*0.0047)*5.5; END rndy; *) PROCEDURE rndx(x:LONGREAL):REAL; VAR a,b,i:CARDINAL; BEGIN a:=VAL(INTEGER, x*1000000.0); b:=0; FOR i:=0 TO 4 DO INC(b, b+ORD(ODD(a))); a:=a DIV 2; END; x:=FLOAT(b); IF ODD(a) THEN x:=-x END; RETURN x*0.005 END rndx; PROCEDURE rndy(x:LONGREAL):REAL; VAR a,b,i:CARDINAL; BEGIN a:=VAL(INTEGER, x*1000000.0); b:=0; FOR i:=0 TO 4 DO INC(b, b+ORD(ODD(a))); a:=a DIV 2; END; x:=FLOAT(b); IF ODD(a) THEN x:=-x END; RETURN x*0.006; END rndy; PROCEDURE posinval(VAR pos:POSITIONL); BEGIN pos.long:=0.0; pos.lat:=0.0 END posinval; PROCEDURE posvalid(pos-:POSITION):BOOLEAN; BEGIN RETURN (pos.lat<>0.0) OR (pos.long<>0.0) END posvalid; PROCEDURE radtodeg(p:POSITION):POSITION; BEGIN p.lat:=p.lat*(1.0/RAD); p.long:=p.long*(1.0/RAD); RETURN p END radtodeg; PROCEDURE radmod(w:REAL):REAL; BEGIN WHILE w>PI DO w:=w-2*PI END; WHILE w<-PI DO w:=w+2*PI END; RETURN w END radmod; PROCEDURE wgs84s(lat, long, nn:REAL; VAR x,y,z:REAL); VAR h, c:REAL; BEGIN h:=nn+EARTH*1000.0; z:=h*sin(lat); c:=cos(lat); y:=h*sin(long)*c; x:=h*cos(long)*c; END wgs84s; PROCEDURE wgs84sl(lat, long, nn:LONGREAL; VAR x,y,z:LONGREAL); VAR h, c:LONGREAL; BEGIN h:=nn+EARTH*1000.0; z:=h*sin(lat); c:=cos(lat); y:=h*sin(long)*c; x:=h*cos(long)*c; END wgs84sl; PROCEDURE wgs84r(x,y,z:REAL; VAR lat, long, heig:REAL); VAR h:REAL; BEGIN h:=x*x + y*y; IF ABS(x)>ABS(y) THEN long:=osi.arctan(y/x); IF x<0.0 THEN IF y>0.0 THEN long:=PI+long ELSE long:=long-PI END; END; ELSE long:=PI*0.5-osi.arctan(x/y); IF y<0.0 THEN long:=long-PI END; END; lat:=osi.arctan(z/sqrt(h)); heig:=sqrt(h + z*z) - EARTH*1000.0; END wgs84r; PROCEDURE wgs84rl(x,y,z:LONGREAL; VAR lat, long:LONGREAL; VAR heig:LONGREAL); VAR h:LONGREAL; BEGIN h:=x*x + y*y; IF ABS(x)>ABS(y) THEN long:=atan(y/x); IF x<0.0 THEN IF y>0.0 THEN long:=PI+long ELSE long:=long-PI END; END; ELSE long:=PI*0.5-atan(x/y); IF y<0.0 THEN long:=long-PI END; END; lat:=atan(z/sqrt(h)); heig:=sqrt(h + z*z) - EARTH*1000.0; END wgs84rl; PROCEDURE distnear(a-,b-:POSITIONL):REAL; VAR x,y:REAL; BEGIN x:=(a.long-b.long)*coslat; y:=a.lat -b.lat; RETURN (EARTH*1000.0)*osi.sqrt(x*x+y*y) END distnear; PROCEDURE readsymbol(VAR img:SYMBOL; VAR x,y:CARDINAL; fn-:ARRAY OF CHAR); CONST BYTESPERPIX=4; TYPE ROWS=ARRAY[0..MAXSYMSIZE-1] OF PIX8A; pROWS=POINTER TO ROWS; VAR rows:ARRAY[0..MAXSYMSIZE-1] OF pROWS; maxx, maxy, maxxbyte, res, i:INTEGER; BEGIN maxx:=MAXSYMSIZE; maxy:=MAXSYMSIZE; maxxbyte:=maxx*BYTESPERPIX; (* maxxbyte = maxx*4: switch on alpha channel *) FOR i:=0 TO MAXSYMSIZE-1 DO rows[i]:=ADR(img[i][0]) END; res:=pngread.readpng(fn, rows, maxx, maxy, maxxbyte); IF res=0 THEN x:=maxx; y:=maxy; ELSE Error("icon image not readable"); -- x:=0; -- y:=0; END; --WrInt(res, 5); WrInt(maxx, 5); WrInt(maxy, 5); WrStrLn(""); END readsymbol; PROCEDURE makegammatab(min, max:CARDINAL); VAR c, span:CARDINAL; g:REAL; BEGIN IF max<=min THEN min:=0; max:=HIGH(gammatab) END; span:=max-min; g:=1.0/igamma; FOR c:=0 TO HIGH(gammatab) DO IF c>min THEN IF c<=max THEN gammatab[c]:=CHR(TRUNC(exp(log(FLOAT(c-min)/FLOAT(span))*g)*255.5)); ELSE gammatab[c]:=CHR(255) END; ELSE gammatab[c]:=CHR(0) END; END; END makegammatab; PROCEDURE histogram(img:pIMAGE; nosat:BOOLEAN; VAR min, max:CARDINAL); VAR x, y, pc, pixc, iw, ib, mid, maxe:CARDINAL; fmin, mul, fr, fg, fb, w, rw, ilog, llog:REAL; h,hh:ARRAY[0..MAXLUM] OF CARDINAL; -- hr:ARRAY[0..MAXLUM] OF REAL; BEGIN FILL(ADR(h), 0C, SIZE(h)); FILL(ADR(hh), 0C, SIZE(hh)); FOR y:=0 TO HIGH(img^[0]) DO FOR x:=0 TO HIGH(img^) DO WITH img^[x][y] DO -- pc:=(VAL(CARDINAL, r)*3 + VAL(CARDINAL, g)*5 + VAL(CARDINAL, b)*2) DIV 10; (* PAL luma *) pc:=(VAL(CARDINAL, r)*3 + VAL(CARDINAL, g)*5 + VAL(CARDINAL, b)*1) DIV 9; (* snow shadow blue, dust blue dimms *) IF nosat THEN IF r>pc THEN pc:=r END; (* saturated single colours *) IF g>pc THEN pc:=g END; IF b>pc THEN pc:=b END; END; IF pc>MAXLUM THEN pc:=MAXLUM END; INC(hh[pc]); (* whole image *) IF NOT ODD(b) THEN INC(h[pc]) END; (* only earth no heaven or mirrored heaven *) END; END; END; pixc:=(HIGH(img^)+1)*(HIGH(img^[0])+1); ib:=truncc(FLOAT(pixc)*ABS(ignorblack)*0.01); min:=1; (* dont use unfilled black stripes *) WHILE (ib>=h[min]) & (min=hh[max]) & (max>0) DO DEC(iw, hh[max]); DEC(max) END; iw:=TRUNC(FLOAT(pixc)*ignorwhite*0.01); maxe:=MAXLUM; WHILE (iw>=h[maxe]) & (maxe>0) DO DEC(iw, h[maxe]); DEC(maxe) END; maxe:=imax(maxe, whitelim); min:=imin(min, blacklim); max:=imax(max, whitelim); (* with heaven *) --- check contrast for auto filmlinearity llog:=logfilm; IF logfilm<0.0 THEN (* contrast auto *) llog:=200000.0; WHILE (llog>100.0) & (llog*osi.ln(1.0+FLOAT(max)/llog)>FLOAT(maxe)) DO llog:=llog*0.95 END; END; IF llog>0.0 THEN ilog:=1.0/llog; max:=TRUNC(llog*osi.ln(1.0+FLOAT(max)*ilog)); END; IF ignorblack<0.0 THEN min:=truncc(FLOAT(max)*ABS(ignorblack)) END; IF min>=max THEN max:=min+1 END; fmin:=FLOAT(min); mul:=MAXLUM/(FLOAT(max)-fmin); IF verb THEN WrStr("min..allmax, earthmax, log: "); WrInt(min, 6);WrInt(max, 6); WrInt(maxe, 6);WrFixed(llog, 1,10); WrStrLn(""); END; FOR y:=0 TO HIGH(img^[0]) DO FOR x:=0 TO HIGH(img^) DO WITH img^[x][y] DO fr:=FLOAT(r); fg:=FLOAT(g); fb:=FLOAT(b); w:=fr*0.3 + fg*0.5 + fb*0.2 + 0.1; rw:=1.0/w; fr:=fr*rw; fg:=fg*rw; fb:=fb*rw; w:=w-fmin; IF w<0.1 THEN w:=0.1 END; IF llog<>0.0 THEN w:=llog*osi.ln(1.0+w*ilog) END; w:=mul*w; fr:=fr*w; IF fr>MAXLUM-1 THEN fr:=FLOAT(MAXLUM-1) END; fg:=fg*w; IF fg>MAXLUM-1 THEN fg:=FLOAT(MAXLUM-1) END; fb:=fb*w; IF fb>MAXLUM-1 THEN fb:=FLOAT(MAXLUM-1) END; r:=TRUNC(fr); g:=TRUNC(fg); b:=TRUNC(fb); (* r:=TRUNC(w*fr); g:=TRUNC(w*fg); b:=TRUNC(w*fb); IF r>MAXLUM THEN r:=MAXLUM END; IF g>MAXLUM THEN g:=MAXLUM END; IF b>MAXLUM THEN b:=MAXLUM END; *) END; END; END; min:=0; max:=MAXLUM; END histogram; PROCEDURE wrpng():INTEGER; PROCEDURE pngc(c:CARD16):CARD8; BEGIN IF c<=HIGH(gammatab) THEN RETURN ORD(gammatab[c]) ELSE RETURN 255 END END pngc; VAR pngimg:pngwrite.PNGPIXMAP; x, y, ret:INTEGER; -- min, max:CARDINAL; BEGIN ret:=-2; ALLOCATE(pngimg.image, xsize*ysize*3); IF pngimg.image<>NIL THEN (* histogram(image, min, max); makegammatab(min, max); *) FOR y:=0 TO ysize-1 DO FOR x:=0 TO xsize-1 DO WITH image^[x][ysize-1-y] DO WITH pngimg.image^[x+y*xsize] DO red:=pngc(r); green:=pngc(g); blue:=pngc(b) END; END; END; END; pngimg.width:=xsize; pngimg.height:=ysize; ret:=pngwrite.writepng(imagefn, pngimg); DEALLOCATE(pngimg.image, xsize*ysize*3); ELSE Werr("png write out of memory"+LF) END; RETURN ret END wrpng; (* ------- moon CONST E=RAD*23.4397; (* obliquity of the Earth *) PROCEDURE fdeclination(l, b:LONGREAL):LONGREAL; BEGIN RETURN asin(sin(b)*cos(E) + cos(b)*sin(E)*sin(l)) END fdeclination; PROCEDURE frightascension(l, b:LONGREAL):LONGREAL; BEGIN RETURN atang2(sin(l)*cos(E)-tan(b)*sin(E), cos(l)) END frightascension; PROCEDURE siderealtime(d, lw:LONGREAL):LONGREAL; BEGIN RETURN RAD*(280.16 + 360.9856235*d) - lw END siderealtime; PROCEDURE faltitude(h, phi, dec:REAL):REAL; BEGIN RETURN asin(sin(phi)*sin(dec) + cos(phi)*cos(dec)*cos(h)) END faltitude; PROCEDURE fazimuth(h, phi, dec:REAL):REAL; BEGIN RETURN atang2(sin(h), cos(h)*sin(phi) - tan(dec)*cos(phi)) END fazimuth; PROCEDURE mooncoords(d:LONGREAL; VAR declination, distance, rightascension:REAL); VAR el, m, f, l, b:LONGREAL; BEGIN el:=(218.316 + 13.176396*d)*RAD; m:= (134.963 + 13.064993*d)*RAD; f:= (93.272 + 13.229350*d)*RAD; l:=el + 6.289*RAD*sin(m); (* latitude *) b:=5.128*RAD*sin(f); (* longitude *) distance:=385001 - 20905*cos(m); (* distance to the moon in km *) declination:=fdeclination(l, b); rightascension:=frightascension(l, b); END mooncoords; PROCEDURE moonposition(lat, long:LONGREAL; time:CARDINAL; VAR az, el, distance:REAL); VAR lw, phi, declination, bigh, rightascension, h:REAL; d:LONGREAL; s:ARRAY[0..30] OF CHAR; BEGIN lw:=-long; phi:=lat; d:=(LFLOAT(time) - LFLOAT(86400*((2000-1970)*1461 DIV 4)))/86400.0 - 0.5 (*49925*); WrFixed(d, 5, 15);WrStrLn("=jd"); mooncoords(d, declination, distance, rightascension); bigh:=siderealtime(d, lw) - rightascension; h:=faltitude(bigh, phi, declination); (* Altitude correction for refraction *) h:=h + (RAD*0.017)/tan(h + (RAD*10.26)/(h + RAD*5.10)); az:=fazimuth(bigh, phi, declination); el:=h; END moonposition; PROCEDURE time2moon(t:CARDINAL; mypos:POSITIONL; VAR moonaz, moonel:REAL); BEGIN moonposition(mypos.lat, mypos.long, t, moonaz, moonel, moondist); moonaz:=moonaz+PI; IF moonaz>2*PI THEN moonaz:=moonaz-2*PI END; WrStr("moon az el:"); WrFixed(moonaz/RAD, 2, 7); WrFixed(moonel/RAD, 2, 7); WrFixed(moondist, 0, 12);WrStrLn(""); END time2moon; ------- moon *) ------ sun PROCEDURE wrsun(sunaz, sunel:REAL); BEGIN IF verb THEN WrFixed(sunaz, 2, 7); WrStrLn(" sunaz"); WrFixed(sunel, 2, 7); WrStrLn(" sunel"); END; END wrsun; PROCEDURE time2sun(date, time:ARRAY OF CHAR; mypos:POSITIONL; VAR sunaz, sunel:REAL):BOOLEAN; VAR t, day:TIME; PROCEDURE dig(c:CHAR; VAR err:BOOLEAN):CARDINAL; BEGIN IF (c<"0") OR (c>"9") THEN err:=TRUE; RETURN 0 ELSE RETURN ORD(c)-ORD("0") END; END dig; PROCEDURE StrToDate(s:ARRAY OF CHAR; VAR time:TIME):BOOLEAN; (* *) VAR y, m, d, k:CARDINAL; err:BOOLEAN; BEGIN err:=FALSE; y:=dig(s[0], err)*1000 + dig(s[1], err)*100 + dig(s[2], err)*10 + dig(s[3], err); IF (y<1970) OR (y>2100) THEN RETURN FALSE END; time:=(y-1970)*365 + (y-1969) DIV 4; m:=dig(s[4], err)*10 + dig(s[5], err); d:=dig(s[6], err)*10 + dig(s[7], err); IF (d<1) OR (d>31) THEN RETURN FALSE END; k:=ORD(y MOD 4=0); INC(time, d-1); IF m>2 THEN INC(time, k) END; CASE m OF 1: |2: IF d>28+k THEN err:=TRUE END; INC(time, 31); |3: INC(time, 31+28); |4: IF d>30 THEN err:=TRUE END; INC(time, 31+28+31); |5: INC(time, 31+28+31+30); |6: IF d>30 THEN err:=TRUE END; INC(time, 31+28+31+30+31); |7: INC(time, 31+28+31+30+31+30); |8: INC(time, 31+28+31+30+31+30+31); |9: IF d>30 THEN err:=TRUE END; INC(time, 31+28+31+30+31+30+31+31); |10:INC(time, 31+28+31+30+31+30+31+31+30); |11:IF d>30 THEN err:=TRUE END; INC(time, 31+28+31+30+31+30+31+31+30+31); |12:INC(time, 31+28+31+30+31+30+31+31+30+31+30); ELSE err:=TRUE; END; RETURN NOT err END StrToDate; PROCEDURE StrToDaytime(s:ARRAY OF CHAR; VAR time:TIME):BOOLEAN; (* *) VAR h, mi, se:CARDINAL; err:BOOLEAN; BEGIN err:=FALSE; h:=dig(s[0], err)*10 + dig(s[1], err); IF h>24 THEN RETURN FALSE END; mi:=dig(s[2], err)*10 + dig(s[3], err); IF mi>=60 THEN RETURN FALSE END; se:=dig(s[4], err)*10 + dig(s[5], err); IF se>=60 THEN RETURN FALSE END; time:=h*3600 + mi*60 + se; RETURN NOT err END StrToDaytime; PROCEDURE arcsin(x:REAL):REAL; BEGIN RETURN osi.arctan(x/sqrt(1.0-x*x)) END arcsin; PROCEDURE modrad(w:REAL):REAL; BEGIN RETURN (w-FLOAT(TRUNC(w/360.0)*360)) END modrad; PROCEDURE sunpos(tt:TIME; lat, long:REAL; VAR azi, ele:REAL); VAR l,g,r,aa,e,alpha,c,ga,t0,n,fhg,fg,fl,ta:REAL; BEGIN n:=FLOAT(tt - 86400*((2000-1970)*1461 DIV 4))/86400.0 - 0.5; l:=280.46 + 0.9856474*n; l:=modrad(l); g:=357.528 + 0.9856003*n; g:=modrad(g)*RAD; aa:=l + 1.915*sin(g) + 0.02*sin(g*2.0); e:=23.439 - 0.0000004*n; c:=cos(aa*RAD); alpha:=osi.arctan(cos(e*RAD)*sin(aa*RAD)/c)/RAD; IF c<0.0 THEN alpha:=alpha + 180.0 END; ga:=arcsin(sin(e*RAD)*sin(aa*RAD))/RAD; t0:=(VAL(REAL,VAL(INTEGER,n))+0.5)/36525; fhg:=6.697376 + 2400.05134*t0 + 1.002738*FLOAT(tt MOD 86400)/3600.0; fhg:=fhg - FLOAT(TRUNC(fhg/24.0))*24.0; fg:=fhg*15.0; fl:=fg+long; ta:=fl-alpha; c:=cos(ta*RAD)*sin(lat*RAD) - tan(ga*RAD)*cos(lat*RAD); azi:=osi.arctan(sin(ta*RAD)/c)/RAD + 360.0 + 180.0; IF c<0.0 THEN azi:=azi + 180.0 END; azi:=azi-FLOAT(TRUNC(azi/360.0))*360.0; ele:=arcsin(cos(ga*RAD)*cos(ta*RAD)*cos(lat*RAD) + sin(ga*RAD)*sin(lat*RAD))/RAD; r:=0.017/tan((ele+10.3/(ele+5.11))*RAD); ele:=ele+r; END sunpos; PROCEDURE Refraction(el:REAL):REAL; (* in rad *) BEGIN RETURN (PI*0.5-el-arcsin(6366.0/(6366.0+12.0)*cos(el)))/RAD*0.15 END Refraction; BEGIN IF StrToDate(date, day) & StrToDaytime(time, t) THEN sunpos(t+day*86400, mypos.lat/RAD, mypos.long/RAD, sunaz, sunel); (* sunaz:=sunaz*RAD; sunel:=sunel*RAD; day:=25568+t DIV (60*60*24); day:=1 + day*4 MOD 1461 DIV 4; AzimutHoehe(mypos.lat, day, FLOAT(t MOD 86400)/3600.0 + mypos.long/(RAD*15.0) - 12.0+zeitgleichung(day), sunaz, sunel); *) --WrFixed(sunel,5,10);WrFixed(Refraction(sunel*RAD),5,10);WrStrLn("=sunrefrac"); sunel:=sunel + Refraction(sunel*RAD); wrsun(sunaz, sunel); -- time2moon(t+day*86400, mypos, moonazim, moonelev); RETURN TRUE END; RETURN FALSE; END time2sun; PROCEDURE autosun(VAR az, el:REAL; pos:POSITIONL; pan:REAL); BEGIN IF (pos.lat>0.0)=(pan<180.0) THEN az:=90.0 ELSE az:=-90.0 END; az:=pan+az; IF az<0.0 THEN az:=az+360.0 ELSIF az>360.0 THEN az:=az-360.0 END; el:=15+0.58*(90.0-ABS(pos.lat)/RAD)*ABS(cos(az*RAD)); --WrFixed(ABS(pos.lat)/RAD, 3, 9); WrStrLn("=r"); END autosun; ------- sun PROCEDURE Parms; VAR altOG, err:BOOLEAN; h, iconfn, iconwoodfn, iconhint:ARRAY[0..1023] OF CHAR; pan, dist, rn, sunazim, sunelev:REAL; label, pri:CARDINAL; p:INTEGER; ppoi:pPOI; ptrk:pTRACK; col:INTEGER; PROCEDURE getpos(VAR p:POSITIONL; e-:ARRAY OF CHAR); VAR ps:POSITION; BEGIN NextArg(h); loctopos(ps, h); IF posvalid(ps) THEN p.lat:=ps.lat; p.long:=ps.long ELSE IF NOT StrToFixL(p.lat, h) OR (ABS(p.lat)>=90) THEN Error(e) END; NextArg(h); IF NOT StrToFixL(p.long, h) OR (ABS(p.long)>180) THEN Error(e) END; p.lat :=p.lat*RAD; p.long:=p.long*RAD; END; END getpos; BEGIN err:=FALSE; label:=0; iconfn:=""; iconwoodfn:=""; iconhint:=""; pan:=0.0; dist:=0.0; dateh:=""; timeh:=""; altOG:=FALSE; millisec:=0; pri:=0; LOOP NextArg(h); IF h[0]=0C THEN EXIT END; IF (h[0]="-") & (h[1]<>0C) & (h[2]=0C) THEN IF h[1]="i" THEN NextArg(imagefn); IF (imagefn[0]=0C) OR (imagefn[0]="-") THEN Error("-i ") END; ELSIF h[1]="P" THEN ALLOCATE(ppoi, SIZE(ppoi^)); IF ppoi=NIL THEN Error("poifile, out of memory") END; ppoi^.r:=255; ppoi^.g:=255; ppoi^.b:=255; ppoi^.alpha:=255; NextArg(h); ppoi^.prio:=pri; (* prefer first pois if no place for text *) INC(pri); IF StrToInt(h, col) THEN ppoi^.r:=col; NextArg(h); IF StrToInt(h, col) THEN ppoi^.g:=col; NextArg(h); IF StrToInt(h, col) THEN ppoi^.b:=col; NextArg(h); IF StrToInt(h, col) THEN ppoi^.alpha:=col; NextArg(h); END; END; END; END; Assign(ppoi^.poifn, h); IF (ppoi^.poifn[0]=0C) OR (ppoi^.poifn[0]="-") THEN Error("-P ") END; Assign(ppoi^.iconfn, iconfn); Assign(ppoi^.iconwoodfn, iconwoodfn); Assign(ppoi^.iconhint, iconhint); ppoi^.altIsOG:=altOG; altOG:=FALSE; ppoi^.next:=poifiles; poifiles:=ppoi; ELSIF h[1]="E" THEN ALLOCATE(ptrk, SIZE(ptrk^)); IF ptrk=NIL THEN Error("trackfile, out of memory") END; ptrk^.r:=200; ptrk^.g:=100; ptrk^.b:=50; ptrk^.width:=2; ptrk^.altmode:=0; NextArg(h); IF StrToInt(h, col) THEN ptrk^.r:=col; NextArg(h); IF StrToInt(h, col) THEN ptrk^.g:=col; NextArg(h); IF StrToInt(h, col) THEN ptrk^.b:=col; NextArg(h); IF StrToInt(h, col) THEN ptrk^.width:=col; NextArg(h); IF StrToInt(h, col) THEN ptrk^.altmode:=col; NextArg(h); END; END; END; END; END; Assign(ptrk^.fn,h); (* for -v *) ptrk^.fd:=OpenRead(h); IF ptrk^.fd<0 THEN Error("-E trackfile not readable") END; IF (h[0]=0C) OR (h[0]="-") THEN Error("-E ") END; ptrk^.next:=trackfiles; trackfiles:=ptrk; ELSIF h[1]="c" THEN NextArg(csvfn); IF (csvfn[0]=0C) OR (csvfn[0]="-") THEN Error("-c ") END; ELSIF h[1]="C" THEN NextArg(h); IF NOT StrToInt(h, col) OR (col<0) THEN Error("-C ") END; rastercsv:=col; ELSIF h[1]="I" THEN NextArg(iconfn); IF (iconfn[0]=0C) OR (iconfn[0]="-") THEN Error("-I (png)") END; NextArg(iconwoodfn); IF iconwoodfn[0]="-" THEN Error("-I (png)") END; ELSIF h[1]="J" THEN NextArg(iconhint); IF (iconhint[0]=0C) OR (iconhint[0]="-") THEN Error("-J ") END; IF iconhint[0]="," THEN iconhint[0]:=0C END; ELSIF h[1]="v" THEN verb:=TRUE; ELSIF h[1]="O" THEN altOG:=TRUE; ELSIF h[1]="Z" THEN defaultocean:=TRUE; ELSIF h[1]="j" THEN dropshadows:=TRUE; ELSIF h[1]="u" THEN NextArg(h); IF NOT StrToFix(urbanoff, h) THEN Error("-u ") END; ELSIF h[1]="f" THEN NextArg(h); IF h[0]="0" THEN flatscreen:=eFLAT ELSIF h[0]="1" THEN flatscreen:=eCAMERA ELSE Error("-f ") END; ELSIF h[1]="x" THEN NextArg(h); IF NOT StrToInt(h, xsize) OR (xsize<20) OR (xsize>=32000) THEN Error("-x ") END; ELSIF h[1]="y" THEN NextArg(h); IF NOT StrToInt(h, ysize) OR (ysize<20) OR (ysize>=8192) THEN Error("-y ") END; ELSIF h[1]="M" THEN NextArg(h); IF NOT StrToCard(h, srtmmaxmem) THEN Error("-M ") END; ELSIF h[1]="p" THEN NextArg(srtmdir); IF (srtmdir[0]=0C) OR (srtmdir[0]="-") THEN Error("-p ") END; ELSIF h[1]="a" THEN getpos(posa, "-a or "); ELSIF h[1]="b" THEN getpos(posb, "-b or "); ELSIF h[1]="A" THEN NextArg(h); IF NOT StrToFix(camog, h) OR (camog<0) OR (camog>500000) THEN Error("-A (0..500000)") END; ELSIF h[1]="d" THEN NextArg(h); IF NOT StrToFix(pan, h) THEN Error("-d ") END; NextArg(h); IF NOT StrToFix(dist, h) THEN Error("-d ") END; ELSIF h[1]="S" THEN NextArg(dateh); NextArg(timeh); ELSIF h[1]="V" THEN NextArg(h); IF NOT StrToCard(h, poilabel) THEN Error("-V ") END; INC(poilabel); ELSIF h[1]="W" THEN flatwater:=TRUE; NextArg(h); IF NOT StrToFix(waveamp, h) OR (waveamp<0.0) OR (waveamp>10.0) THEN Error("-W ") END; waveamp:=waveamp*0.01; NextArg(h); IF NOT StrToFix(wavelength, h) THEN Error("-W ") END; NextArg(h); IF NOT StrToFix(waterslant, h) THEN Error("-W ") END; ELSIF h[1]="m" THEN NextArg(h); IF NOT StrToFix(rn, h) THEN Error("-m "); END; maxmountain:=rn; ELSIF h[1]="N" THEN NextArg(h); IF NOT StrToFix(abscolmin, h) THEN Assign(colfn, h); NextArg(h); IF NOT StrToFix(abscolmin, h) THEN Error("-N [] "); END; END; NextArg(h); IF NOT StrToFix(abscolmax, h) THEN Error("-N [] "); END; NextArg(h); IF NOT StrToCard(h, altcolstep) THEN Error("-N [] "); END; alticolour:=TRUE; ELSIF h[1]="t" THEN NextArg(h); IF NOT StrToFix(treesize, h) THEN Error("-t "); END; NextArg(h); IF NOT StrToFix(botanicslant, h) THEN Error("-t "); END; NextArg(h); IF NOT StrToFix(treerastersize, h) OR (treerastersize<1.0) OR (treerastersize>100.0) THEN Error("-t [1..100m]") END; ELSIF h[1]="T" THEN NextArg(h); IF NOT StrToFix(zerotreealt, h) THEN Error("-T "); END; NextArg(h); IF NOT StrToFix(fulltreealt, h) THEN Error("-T "); END; IF zerotreealt<=fulltreealt THEN Error("-T no_tree_alt <= full_tree_alt ?"); END; ELSIF h[1]="l" THEN NextArg(h); IF NOT StrToFix(ignorblack, h) THEN Error("-l "); END; NextArg(h); IF NOT StrToFix(ignorwhite, h) THEN Error("-l "); END; ELSIF h[1]="D" THEN NextArg(h); IF NOT StrToFix(desertcol.r, h) THEN Error("-D "); END; NextArg(h); IF NOT StrToFix(desertcol.g, h) THEN Error("-D "); END; NextArg(h); IF NOT StrToFix(desertcol.b, h) THEN Error("-D "); END; NextArg(h); IF NOT StrToFix(sandgranularity, h) THEN Error("-D "); END; (* desertcol.r:=desertcol.r*16.0; desertcol.g:=desertcol.g*16.0; desertcol.b:=desertcol.b*16.0; *) ELSIF h[1]="o" THEN NextArg(h); IF NOT StrToFix(minpoialt, h) OR (minpoialt<-20000.0) OR (minpoialt>20000.0) THEN Error("-o (0..20000)") END; ELSIF h[1]="K" THEN NextArg(h); IF NOT StrToFix(logfilm, h) THEN Error("-K ") END; ELSIF h[1]="G" THEN NextArg(h); IF NOT StrToFix(snowalt, h) THEN Error("-G ") END; NextArg(h); IF NOT StrToFix(slowaltslant, h) THEN Error("-G ") END; IF slowaltslant<1.0 THEN slowaltslant:=1.0 END; ELSIF h[1]="r" THEN NextArg(h); IF NOT StrToFix(refraction, h) OR (refraction<0.0) OR (refraction>1.0) THEN Error("-r [0.0..1.0]") END; ELSIF h[1]="e" THEN NextArg(h); IF NOT StrToFix(elev, h) OR (elev<-90.0) OR (elev>90.0) THEN Error("-e [-90.0..90.0]") END; ELSIF h[1]="w" THEN NextArg(h); IF NOT StrToFix(angle, h) OR (angle<0.1) OR (angle>360.0) THEN Error("-w [0.1..360.0]") END; ELSIF h[1]="L" THEN NextArg(h); IF NOT StrToCard(h, blacklim) THEN Error("-L "); END; NextArg(h); IF NOT StrToCard(h, whitelim) THEN Error("-L "); END; ELSIF h[1]="Q" THEN NextArg(h); IF NOT StrToFix(videolat, h) OR (videolat<-89.0) OR (videolat>89.0) THEN Error("-Q [-89..89]") END; ELSIF h[1]="z" THEN NextArg(h); IF NOT StrToFix(yzoom, h) OR (yzoom<0.001) OR (yzoom>10.0) THEN Error("-z [0.0..10.0]") END; ELSIF h[1]="s" THEN NextArg(h); IF NOT StrToCard(h, poisize) OR (poisize>20) THEN Error("-s 1..20") END; ELSIF h[1]="g" THEN NextArg(h); IF NOT StrToFix(igamma, h) OR (igamma<0.1) OR (igamma>10.0) THEN Error("-g [0.1..10] (1.0)") END; ELSIF h[1]="H" THEN NextArg(h); IF NOT StrToFix(heavencol.r,h) OR (heavencol.r>=256.0) THEN Error("-H 0..255") END; NextArg(h); IF NOT StrToFix(heavencol.g,h) OR (heavencol.g>=256.0) THEN Error("-H 0..255") END; NextArg(h); IF NOT StrToFix(heavencol.b,h) OR (heavencol.b>=256.0) THEN Error("-H 0..255") END; heavencol.r:=heavencol.r*16.0; heavencol.g:=heavencol.g*16.0; heavencol.b:=heavencol.b*16.0; ELSIF h[1]="R" THEN NextArg(h); IF NOT StrToFix(watercol.r,h) OR (watercol.r>=1024.0) THEN Error("-R ") END; NextArg(h); IF NOT StrToFix(watercol.g,h) OR (watercol.g>=1024.0) THEN Error("-R ") END; NextArg(h); IF NOT StrToFix(watercol.b,h) OR (watercol.b>=1024.0) THEN Error("-R ") END; NextArg(h); IF NOT StrToFix(waterglance,h) THEN Error("-R >") END; NextArg(h); IF NOT StrToFix(watertransparency,h) THEN Error("-R ") END; NextArg(h); IF NOT StrToFix(surfacedust,h) THEN Error("-R ") END; ELSIF h[1]="F" THEN NextArg(h); IF h[0]="1" THEN fonttyp:=6 ELSIF h[0]="2" THEN fonttyp:=8 ELSIF h[0]="3" THEN fonttyp:=10 ELSE Error("-F [,] (1:6x10 2:8x14 3:10x20)") END; IF h[1]="," THEN IF h[2]="1" THEN fonttypfoot:=6 ELSIF h[2]="2" THEN fonttypfoot:=8 ELSIF h[2]="3" THEN fonttypfoot:=10 ELSE Error("-F [,] (1:6x10 2:8x14 3:10x20)") END; END; ELSIF h[1]="h" THEN WrStrLn(""); WrStrLn("Panorama"); WrStrLn(" -A Camera over ground or over NN [m] (10)"); WrStrLn(" -a | [locator] Camera position lat long (degrees) or qth locator"); WrStrLn(" -b | [locator] Pan to point lat long (degrees) or qth locator"); WrStrLn(" -C write CSV line for every N'th column"); WrStrLn(" -c CSV file name"); WrStrLn(" -D Sand/Rock colour and granularity (with -t 0 0 -u 0)"); WrStrLn(" -d Relative to position a (alternativ to -b)"); WrStrLn(" km distance sight limit"); WrStrLn(" -E [ ] draw track (lat,long[,altNN]) mode=0: always on ground,"); WrStrLn(" mode=1: use alt if above ground, mode=2: no track if alt under gnd"); WrStrLn(" mode=3: use altOG with minimum -o "); WrStrLn(" blank csv line starts a new track (same colour/mode)"); WrStrLn(" -e Camera Elevation (degrees) (0.0)"); WrStrLn(" speed optimizer, surface contrast and dust calculation"); WrStrLn(" are able to handle only small elevations!"); WrStrLn(" -F [,] Font Size POI,footline (1) 1: 6x10, 2: 8x14, 3: 10x20"); WrStrLn(" -f 0 Flat screen perpendicular, 1 screen normal to sight (no latitude scale)"); WrStrLn(" default courved projection area (needed at >=180deg sight)"); WrStrLn(" -G Glazier/Snow altitude and fade out (5000 500)"); WrStrLn(" -g Image Gamma 0.1..10 (1.0)"); WrStrLn(" -H Heaven colour (50 70 300)"); WrStrLn(" -h this"); WrStrLn(' -I | "" Symbol Image File Name with, w/o wood, set before -P'); WrStrLn(" -i Image File Name"); WrStrLn(" -j dropshadows on (test implementation, very slow)"); WrStrLn(" -J text appended to csv lines, set before -P, off with -J ,"); WrStrLn(" -K compress sunlight/dust to fit in image brightness (4000) 0=linear else auto"); WrStrLn(" -l <%> <%> fit image contrast to saturate % of all black/white pixels (-0.1 1.0)"); WrStrLn(" negative black level use -level of while"); WrStrLn(" -L limit contrast expansion black white (400 1000)"); WrStrLn(" -M SRTM-Cache Limit (100000000)"); WrStrLn(" -m limit searching montain size in viewed area for speed on long distance (8900)"); WrStrLn(" -N [] Colourize altitude m, 0 is autoscale"); WrStrLn(" file: [] ... min to max (0..255)"); WrStrLn(" : w water, t trees, u urban, x ?, y ?"); WrStrLn(" -O POI File altitude is over ground not NN, set before -P"); WrStrLn(" -o min. POI altitude over ground (1)"); WrStrLn(" if given in POI file and higher use this"); WrStrLn(" -P [ []] optional icon colours (0..255) POI File Name"); WrStrLn(" repeat for more files add -V for labeling"); WrStrLn(" -p folder with /srtm1 /srtm3 /srtm30"); WrStrLn(" -Q for video enter raw latitude for squarish tree raster (default camera lat)"); WrStrLn(" camera altitude now over NN"); WrStrLn(" -R Water Colour mirroring sight (350 300 200 1 1)"); WrStrLn(" -r 0.0(vacuum)..1.0(earth is a disk) (0.13)"); WrStrLn(" -S [+] |