Doumentatie voor de geleverde functies

Inleiding

Dit document beschrijft een aantal functies die gebruikt kunnen worden om de hemelsbrede afstand, afgelegd tijdens een taxirit, snel te kunnen berekenen. We lichten achtereenvolgens de volgende functies toe:
  1. GPS_naar_xy, deze werkt GPS-coördinaten om tot cartesische co\"ordinaten.
  2. 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.
  3. berekenen, deze doet het eigenlijke werk: uit twee stel GPS-coördinaten hun hemelsbrede afstand in hectometers bepalen.

Globale variabelen

Om goed te kunnen werken moeten de functies/procedures kunnen vertrouwen dat een aantal waarden globaal in het programma bekend zijn. Deze worden in onderstaande lijstjes opgesomd.

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.

Initialisatie

Het enige dat echt geïnitialiseerd moet worden is de begrenzing, de rest wordt hieruit afgeleid. Als voorbeeld nemen we de de vijfhoek van Leidscherijn:
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.

GPS naar xy-coördinaten

De hulpfunctie 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.

De begrenzing converteren

Deze procedure loopt tweemaal door 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.

Afstand berekenen

Het berekenen van de hemelsbrede afstand tussen twee punten geschiedt als volgt.

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.