Post Reply 
Great Circle Information
05-17-2018, 07:42 PM (This post was last modified: 05-17-2018 07:44 PM by toml_12953.)
Post: #1
Great Circle Information
Another program by Stephen R. Schmitt!
Code:
distance();
course();
latitude();
longitude();

export GreatCircle()

begin

    local sgn, deg, minn, secc;
    local lat1, lat2, lat3, lat4;
    local lon1, lon2, lon3, lon4;
    local dist, crse;

    // Sydney, AS     33°53' S  151°13' E
    lat1 := latitude(  -1,  33, 53, 0 );
    lon1 := longitude( 1, 151, 13, 0 );
    
    // London, UK,    51°30' N    0°07' W
    lat2 := latitude(  1, 51, 30, 0 );
    lon2 := longitude( -1,  0,  7, 0 );

    // Boston, MA US  42°21' N   71°04' W
    lat3 := latitude(  1, 42, 21, 0 );
    lon3 := longitude( -1, 71,  4, 0 );

    // Tokyo, JA,     35°41' N  139°45' E
    lat4 := latitude(  1,  35, 41, 0 );
    lon4 := longitude( 1, 139, 45, 0 );

    print();
    print("Sydney, AS to London, UK");
    dist := distance(lat1, lon1, lat2, lon2);
    crse := course(lat1, lon1, lat2, lon2);
    print("distance = "+ round(dist,2)+ "  kilometers");
    print("heading  = "+ round(crse,2)+ "° true (initially)\n");

    print("London, UK to Boston, MA US");
    dist := distance(lat2, lon2, lat3, lon3);
    crse := course(lat2, lon2, lat3, lon3);
    print("distance = "+ round(dist,2)+ "  kilometers");
    print("heading  = "+ round(crse,2)+ "° true (initially)\n");
    
    print("Boston, MA US to Tokyo, JA");
    dist := distance(lat3, lon3, lat4, lon4);
    crse := course(lat3, lon3, lat4, lon4);
    print("distance = "+ round(dist,2)+ "  kilometers");
    print("heading  = "+ round(crse,2)+ "° true (initially)\n");

    print("Tokyo, JA to Sydney, AS");
    dist := distance(lat4, lon4, lat1, lon1);
    crse := course(lat4, lon4, lat1, lon1);
    print("distance = "+ round(dist,2)+ "  kilometers");
    print("heading  = "+ round(crse,2)+ "° true (initially)");

end;

// distance using Meeus approximation
distance( lat1, lon1, lat2, lon2 )

begin

    local F := (lat1 + lat2)/2.0;
    local G := (lat1 - lat2)/2.0;
    local L := (lon1 - lon2)/2.0;

    local sinG2 := sin(G)^2;
    local cosG2 := cos(G)^2;
    local sinF2 := sin(F)^2;
    local cosF2 := cos(F)^2;
    local sinL2 := sin(L)^2;
    local cosL2 := cos(L)^2;

    local S := sinG2*cosL2 + cosF2*sinL2;
    local C := cosG2*cosL2 + sinF2*sinL2;

    local w := atan(sqrt(S/C));
    local R := sqrt(S*C)/w;

    local a := 6378.137;            // WGS-84 equatorial radius
    local f := 1.0/298.257223563;   // WGS-84 ellipsoid flattening factor

    local D := 2*w*a;
    local H1 := (3*R - 1)/(2*C);
    local H2 := (3*R + 1)/(2*S);

    local dist := D*(1 + f*H1*sinF2*cosG2 - f*H2*cosF2*sinG2);

    return round(100*dist,0)/100.0;

end;

// course using spherical trigonometry
// does not work if one latitude is polar!!!
course( lat1, lon1, lat2, lon2 )

begin
    local L, D, cosD, C, cosC;

    L    := lon2 - lon1;
    cosD := sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(L);  
    D    := acos(cosD);
    cosC := (sin(lat2) - cosD*sin(lat1))/(sin(D)*cos(lat1));
    
    // numerical error can result in |cosC| slightly > 1.0 
    if cosC > 1.0  then
        cosC := 1.0;
    end;
    if cosC < -1.0 then
        cosC := -1.0;
    end;
 
    C := 180.0*acos(cosC)/PI;

    if sin(L) < 0.0 then
        C := 360.0 - C;
    end;

    return round(100*C,0)/100.0;

end;

// convert to radians
latitude( sgn, deg, minn, secc )

begin
    local lat := 0;

    if (0.0 <= secc) and (secc < 60.0) then
        lat := lat + secc/3600.0;
    else
        print("check latitude seconds!");
    end;

    if (0.0 <= minn) and (minn < 60.0) then
        lat := lat + minn/60.0;
    else
        print("check latitude minutes!");
    end;

    if (0.0 <= deg) and (deg <= 90.0) then
        lat := lat + deg;
    else
        print("check latitude degrees!");
    end;

    if (0.0 <= lat) and (lat <= 90.0) then
        lat := PI*lat/180.0;
    else
        print("latitude range error!");
    end;

    // assert (sgn = +1) or (sgn = -1)
    return sgn*lat;

end;

// convert to radians
longitude( sgn, deg, minn, secc )

begin
    local lon := 0;

    if (0.0 <= secc) and (secc < 60.0) then
        lon := lon + secc / 3600.0;
    else
        print("check longitude seconds!");
    end;

    if (0.0 <= minn) and (minn < 60.0) then
        lon := lon + minn / 60.0;
    else
        print("check longitude minutes!");
    end;

    if (0.0 <= deg) and (deg <= 180.0) then
        lon := lon + deg;
    else
        print("check longitude degrees!");
    end;

    if (0.0 <= lon) and (lon <= 180.0) then
        lon := PI * lon / 180.0;
    else
        print("longitude range error!");
    end;

    // assert (sgn = +1) or (sgn = -1)
    return sgn*lon;

end;

Tom L

DM42 SN: 00025 (Beta)
SN: 00221 (Production)
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)