GPS_naar_xy
, deze werkt GPS-coördinaten om tot
cartesische co\"ordinaten.
converteer_begrenzing
, deze werkt een string van
n maal 12 cijfers om tot n~coördinaatparen ---
elk 12-tal wordt aan GPS_naar_xy
onderworpen.
berekenen
, deze doet het eigenlijke werk:
uit twee stel GPS-coördinaten hun hemelsbrede afstand
in hectometers bepalen.
Om te beginnen een paar constanten:
#define MINUUT 18.525 /* gekregen van A.W.A. Gerrits */ #define SECONDE MINUUT/60 /* \'e\'en seconde in hectometers */ #define PI 3.141592654 /* $\pi$ */Verder een paar structuren, makkelijk voor bij het programmeren.
struct gc {double gy,my,sy,gx,mx,sx;}; /* voor splitsen van GPS-string */ struct punt {double x,y;}; /* vectoren */ struct hoek {struct hoek *next; double x,y;}; /* hoekpunten met pointers */Hier zijn dat de variabelen die gebruikt gaan worden.
int AANTALHOEK; struct hoek *beginhoek, *hoekpunten; /* pointers omdat de lengte onbekend is */ struct punt zwaartepunt, p1, p2; char *GPS_string; double cosinus;Het
zwaartepunt
wordt gebruikt om de coördinaten niet al te groot
te laten worden.
In het array hoekpunten
zullen de cartesische coördinaten van de
hoekpunten van de veelhoek opgeslagen worden.
De string GPS_string
bevat de 12n cijfers.
De cosinus
is de factor die horizontale secondes in hectometers omzet.
De laatste functie is een hulpfunctie die een GPS-string in zes stukken ter lengte twee hakt.
char begrenzing[100]; strcpy(begrenzing, "520821050214520503050737520317050632520439050001520612045938");De naam is niet belangrijk; de lengte 100 is gekozen omdat we ten hoogste 8 punten verwachten. In
converteer_begrenzing
wordt hieruit later het aantal hoekpunten berekend
volgens
AANTALHOEK := length(GPS_string)/12;Bovenstaande waarde komt uit de interne notitie van A.W.A. Gerrits (9 augustus 1999); dit zijn de daar vetgedrukte `Veld GPS' coördinaten.
In wat volgt zal weinig code opgenomen worden, we beperken ons tot het beschrijven van hetgeen de code geacht wordt te doen.
split
splitst een twaalfcijferige string in zes groepjes
van twee en zet deze deze direct om in getallen:
gy, my, sy, gx, mx
en sx (graden, minuten en seconden);
het punt ligt op gy° my'sy'' NB
en gx°mx'sx'' OL.
Van de oosterlengte wordt 5° afgetrokken en van de noorderbreedte
wordt 52° afgetrokken --- dit om de uitkomsten zo klein mogelijk
te houden.
Tenslotte worden deze getallen omgezet in xy-coördinaten volgens
x := (3600g_x+60m_x+s_x)*SECONDE*cosinus-zwaartepunt.x y := (3600g_y+60m_y+s_y)*SECONDE- zwaartepunt.y}Het zwaartepunt dient andermaal om de getallen binnen de perken te houden. Tijdens de uitvoering van
converteer_begrenzing
geldt
zwaartepunt=(0,0)
;
aan het eind van die procedure wordt het gelijk gesteld aan het zwaartepunt
van de veelhoek.
Deze laatste waarde wordt dus bij elke aanroep van berekenen
gebruikt.
GPS_string
.
De eerste keer om de waarde van cosinus
te bepalen; deze waarde is nodig
om lengtegraden in hectometers om te zetten.
Als we ons de aarde als een volmaakte bol voorstellen dat is een graad in de
breedterichting (noord-zuid) altijd even lang, zeg g hectometer.
Een graad in de lengterichting wordt van de evenaar tot aan de Noordpool
steeds korter; op de parallel van hoek alpha is een graad nog
g cos(alpha) hectometer lang.
In het proefgebied Leidscherijn varieert cos(alpha) tussen
0.61374 en 0.6149; aangenomen dat toekomstige proefgebieden niet
veel groter zijn is onze keuze
cosinus := cos((max_breedte+min_breedte)/2);niet zo slecht.
Bij de tweede gang door GPS_string
worden de coördinaten van de
hoekpunten uitgerekend, met gebruik van GPS_naar_xy
en onder de aanname
dat zwaartepunt=(0,0)
.
Aan het eind wordt het zwaartepunt uitgerekend, vastgelegd en van alle
hoekpunten afgetrokken.
NB. De eenheid in dit alles is de hectometer, omdat MINUUT
en dus ook SECONDE
in hectometers zijn uitgedrukt.
De strings worden omgezet in punten: p1 is het beginpunt en p2 is het eindpunt. De vector (rx,ry) is de richtingsvector van de lijn l door p1 en p2. De vergelijking van deze lijn is ryx-rxy = b, waarbij b=ryp1,x-rxp1,y.
Vervolgens lopen we de zijden van de veelhoek langs om te kijken of deze de lijn l snijden en in de voorkomende gevallen het getal lambda te bepalen waarvoor p1+lambda(rx,ry) op de zijde ligt. Zodra twee punten gevonden zijn stoppen we omdat we, wegens de convexiteit van de veelhoek, weten dat we ze allemaal hebben.
Als [u,v] zo'n zijde is dan berekenen we de getallen b0=ryux-rxuy en b1=ryux-rxuy. Als nu b0<b<b1 of b1<b<b0 dan snijden l en de zijde elkaar; dit controleren we door naar het teken van (b0-b)(b1-b) te kijken. Als dit product negatief is berekenen we onze lambda. De echte werkwijze is iets uitgebreider, daar we altijd even kijken of een hoekpunt niet toevallig op l ligt.
Aan het eind hebben we, normaal gesproken, twee waarden lambda1 en lambda2. We denken ons l geöri\"enteerd van p1 naar p2; daarom verwisselen we lambda1 en lambda2 als lambda1>lambda2. We willen dat lambda1 het `linker' snijpunt aanwijst.
Als lambda1<0 dan zetten we lambda1:=0; het stuk tussen het linker snijpunt en p1 wordt immers niet vergoed. Evenzo zetten we lambda2:=0 als lambda2>1. De hemelsbrede afstand is nu
afstand :=(lambda2-lambda1)*sqrt(rx2+ry2)Dit kan negatief zijn: als lambda2<0 of lambda1>1. In dat geval heeft de rit het gebied in het geheel niet aangedaan. We zetten dan alsnog
afstand:=0
.
De functie geeft tenslotte de afstand aan het systeem door.