Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Distance-and-Bearing/00-META.yaml
Normal file
2
Task/Distance-and-Bearing/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Distance_and_Bearing
|
||||
25
Task/Distance-and-Bearing/00-TASK.txt
Normal file
25
Task/Distance-and-Bearing/00-TASK.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
It is very important in aviation to have knowledge of the nearby airports at any time in flight.
|
||||
;Task:
|
||||
Determine the distance and bearing from an Airplane to the 20 nearest Airports whenever requested.
|
||||
Use the non-commercial data from openflights.org [https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat airports.dat] as reference.
|
||||
|
||||
|
||||
A request comes from an airplane at position ( latitude, longitude ): ( '''51.514669, 2.198581''' ).
|
||||
|
||||
|
||||
Your report should contain the following information from table airports.dat (column shown in brackets):
|
||||
|
||||
Name(2), Country(4), ICAO(6), Distance and Bearing calculated from Latitude(7) and Longitude(8).
|
||||
|
||||
|
||||
Distance is measured in nautical miles (NM). Resolution is 0.1 NM.
|
||||
|
||||
Bearing is measured in degrees (°). 0° = 360° = north then clockwise 90° = east, 180° = south, 270° = west. Resolution is 1°.
|
||||
|
||||
|
||||
;See:
|
||||
:* openflights.org/data: [https://openflights.org/data.html Airport, airline and route data]
|
||||
:* Movable Type Scripts: [https://www.movable-type.co.uk/scripts/latlong.html Calculate distance, bearing and more between Latitude/Longitude points]
|
||||
<br><br>
|
||||
|
||||
|
||||
315
Task/Distance-and-Bearing/Free-Pascal/distance-and-bearing.pas
Normal file
315
Task/Distance-and-Bearing/Free-Pascal/distance-and-bearing.pas
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
program Dist_Bearing;
|
||||
{$IFDEF FPC} {$Mode DELPHI}{$Optimization ON,ALL} {$ENDIF}
|
||||
{$IFDEF WINDOWS}{$APPTYPE CONSOLE}{$ENDIF}
|
||||
uses
|
||||
SysUtils,Math;
|
||||
const
|
||||
cDegToRad = pi / 180; cRadToDeg = 180 / pi;
|
||||
//One nautical mile ( 1" of earth circumfence )
|
||||
cOneNmInKm = (12742*pi)/360/60;
|
||||
DiaEarth = 12742/cOneNmInKm;
|
||||
type
|
||||
tLatLon = record
|
||||
lat,lon:double;
|
||||
sinLat,cosLat:double;
|
||||
sinLon,cosLon:double;
|
||||
end;
|
||||
|
||||
tDist_Dir = record
|
||||
distance,bearing:double;
|
||||
end;
|
||||
|
||||
tDst_Bear = record
|
||||
Koor1,
|
||||
Koor2 : tLatLon;
|
||||
Dist_Dir : tDist_Dir;
|
||||
end;
|
||||
|
||||
tmyName = String; //string[63-8] experiment
|
||||
tmyCountry = String; //string[31]
|
||||
tmyICAO = String; //string[7]
|
||||
tSolution = record
|
||||
Sol_Name : tmyName;
|
||||
Sol_Country :tmyCountry;
|
||||
Sol_ICAO : tmyICAO;
|
||||
Sol_Koor : tLatLon;
|
||||
Sol_dist_dir:tDist_Dir;
|
||||
end;
|
||||
|
||||
tIdxDist = record
|
||||
Distance: double;
|
||||
AirportIdx :Int32;
|
||||
end;
|
||||
tMinSols = record
|
||||
sols : array of tIdxDist;
|
||||
maxValue: double;
|
||||
actIdx,
|
||||
maxidx :Int32;
|
||||
end;
|
||||
|
||||
var
|
||||
Airports: array of tSolution;
|
||||
MinSols :tMinSols;
|
||||
cntInserts : Cardinal;
|
||||
|
||||
procedure GetSolData(const OneAirport: String;
|
||||
var TestSol :tSolution);
|
||||
var
|
||||
p1,p2,i1,i2,idx,l : integer;
|
||||
begin
|
||||
p1:=1;
|
||||
idx := 0;
|
||||
l := length(OneAirport);
|
||||
|
||||
repeat
|
||||
p2 := p1;
|
||||
i1 := p1;
|
||||
IF OneAirport[p1] <>'"' then
|
||||
Begin
|
||||
repeat
|
||||
p2 +=1;
|
||||
until (p2>l) OR (OneAirport[p2]=',');
|
||||
i2 := p2;
|
||||
end
|
||||
else
|
||||
begin
|
||||
repeat
|
||||
p2 +=1;
|
||||
until (p2>l) OR (OneAirport[p2]='"');
|
||||
i2 := p2;
|
||||
i1 +=1;
|
||||
while (p2<l) do
|
||||
begin
|
||||
p2 +=1;
|
||||
IF (OneAirport[p2]=',')then
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
idx += 1;
|
||||
|
||||
with TestSol do
|
||||
case idx of
|
||||
2: Sol_Name := copy(OneAirport,i1,i2-i1);
|
||||
4: Sol_Country := copy(OneAirport,i1,i2-i1);
|
||||
6: Sol_ICAO := copy(OneAirport,i1,i2-i1);
|
||||
7: Begin
|
||||
With Sol_Koor do begin
|
||||
lat := StrtoFloat(copy(OneAirport,i1,i2-i1))*cDegToRad;
|
||||
sincos(lat,sinLat,cosLat);
|
||||
end;
|
||||
end;
|
||||
8: Begin
|
||||
With Sol_Koor do begin
|
||||
lon := StrtoFloat(copy(OneAirport,i1,i2-i1))*cDegToRad;
|
||||
sincos(lon,sinLon,cosLon);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
p1:= p2+1;
|
||||
until (idx>7) OR (p1>l);
|
||||
end;
|
||||
|
||||
function ReadAirports(fileName:String):boolean;
|
||||
var
|
||||
TF_Buffer : array[0..1 shl 14 -1] of byte;
|
||||
AirportsFile: TextFile;
|
||||
OneAirport : String;
|
||||
l,cnt : UInt32;
|
||||
begin
|
||||
Assign(AirportsFile,fileName);
|
||||
settextbuf(AirportsFile,TF_Buffer);
|
||||
{$I-}
|
||||
reset(AirportsFile);
|
||||
{$I+}
|
||||
IF ioResult <> 0 then
|
||||
Begin
|
||||
Close(AirportsFile);
|
||||
EXIT(false);
|
||||
end;
|
||||
cnt := 0;
|
||||
l := 100;
|
||||
setlength(Airports,l);
|
||||
|
||||
while Not(EOF(AirportsFile)) do
|
||||
Begin
|
||||
Readln(AirportsFile,OneAirport);
|
||||
GetSolData(OneAirport,Airports[cnt]);
|
||||
inc(cnt);
|
||||
if cnt >= l then
|
||||
Begin
|
||||
l := l*13 div 8;
|
||||
setlength(Airports,l);
|
||||
end;
|
||||
end;
|
||||
setlength(Airports,cnt);
|
||||
Close(AirportsFile);
|
||||
exit(true);
|
||||
end;
|
||||
|
||||
procedure Out_MinSol;
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
writeln(' ICAO Distance Bearing Country Airport');
|
||||
writeln(' ---- -------- ------- -------------- -----------------------------------');
|
||||
For i := 0 to minSols.actidx do
|
||||
with AirPorts[minSols.sols[i].AirportIdx] do
|
||||
writeln(Format(' %4s %8.1f %7.0f %-14s %-35s',
|
||||
[Sol_ICAO,
|
||||
Sol_dist_dir.distance*DiaEarth,
|
||||
Sol_dist_dir.bearing*cRadToDeg,
|
||||
Sol_Country,Sol_Name]));
|
||||
writeln;
|
||||
writeln(cntInserts,' inserts to find them');
|
||||
end;
|
||||
|
||||
procedure Init_MinSol(MaxSolCount:Int32);
|
||||
begin
|
||||
setlength(MinSols.sols,MaxSolCount+1);
|
||||
MinSols.actIdx := -1;
|
||||
MinSols.maxIdx := MaxSolCount-1;
|
||||
MinSols.MaxValue := maxdouble;
|
||||
cntInserts := 0;
|
||||
end;
|
||||
|
||||
procedure Insert_Sol(var sol:tDst_Bear;nrAirport:Int32);
|
||||
var
|
||||
dist : double;
|
||||
idx : Int32;
|
||||
begin
|
||||
with MinSols do
|
||||
begin
|
||||
idx := actIdx;
|
||||
dist := sol.Dist_Dir.distance;
|
||||
|
||||
if Idx >= maxIdx then
|
||||
IF MaxValue < dist then
|
||||
Exit;
|
||||
|
||||
if idx >= 0 then
|
||||
begin
|
||||
inc(idx);
|
||||
inc(cntInserts);
|
||||
|
||||
while sols[idx-1].Distance >dist do
|
||||
begin
|
||||
sols[idx]:= sols[idx-1];
|
||||
dec(idx);
|
||||
If idx<=0 then
|
||||
BREAK;
|
||||
end;
|
||||
with sols[idx] do
|
||||
begin
|
||||
AirportIdx := nrAirport;
|
||||
Distance := dist;
|
||||
end;
|
||||
//update AirPorts[nrAirport] with right distance/bearing
|
||||
AirPorts[nrAirport].Sol_dist_dir := sol.Dist_Dir;
|
||||
if actIdx < maxIdx then
|
||||
actIdx +=1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
with sols[0] do
|
||||
begin
|
||||
AirportIdx := nrAirport;
|
||||
Distance := dist;
|
||||
end;
|
||||
AirPorts[nrAirport].Sol_dist_dir := sol.Dist_Dir;
|
||||
MinSols.actIdx := 0;
|
||||
end;
|
||||
MaxValue := sols[actIdx].Distance;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Calc_Dist_bear(var Dst_Bear:tDst_Bear);
|
||||
var
|
||||
dLonSin,dLonCos,x,y : double;
|
||||
begin
|
||||
with Dst_Bear do
|
||||
Begin
|
||||
If (Koor1.Lat = Koor2.Lat) AND (Koor1.Lon = Koor2.Lon) then
|
||||
Begin
|
||||
Dist_Dir.distance := 0;
|
||||
Dist_Dir.bearing := 0;
|
||||
Exit;
|
||||
end;
|
||||
sincos(Koor1.lon - Koor2.lon,dLonSin,dLonCos);
|
||||
//distance
|
||||
Dist_Dir.distance := arcsin(sqrt(sqr(dLonCos * Koor1.Coslat
|
||||
- Koor2.Coslat) + sqr(dLonSin* Koor1.Coslat)
|
||||
+ sqr(Koor1.sinlat - Koor2.sinlat)) / 2);
|
||||
|
||||
x := dLonSin*Koor2.Coslat;
|
||||
y := Koor1.Coslat*Koor2.sinlat - Koor1.sinlat*Koor2.Coslat*dLonCos;
|
||||
//bearing dLonSin as tmp
|
||||
dLonSin := ArcTan2(x,y);
|
||||
if dLonSin < 0 then
|
||||
dLonSin := -dLonSin
|
||||
else
|
||||
dLonSin := 2*pi-dLonSin;
|
||||
Dist_Dir.bearing := dLonSin;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FindNearest(var testKoors : tDst_Bear;cntAirports,cntNearest:Integer);
|
||||
var
|
||||
i : Int32;
|
||||
begin
|
||||
Init_MinSol(cntNearest);
|
||||
For i := 0 to cntAirports-1 do
|
||||
Begin
|
||||
testKoors.Koor2 := AirPorts[i].Sol_Koor;
|
||||
Calc_Dist_bear(testKoors);
|
||||
Insert_Sol(testKoors,i);
|
||||
end;
|
||||
end;
|
||||
|
||||
const
|
||||
rounds = 100;
|
||||
cntNearest = 20;//128;//8000;
|
||||
var
|
||||
T1,T0 : Int64;
|
||||
testKoors : tDst_Bear;
|
||||
myKoor : tLatLon;
|
||||
i,cntAirports : integer;
|
||||
begin
|
||||
|
||||
|
||||
T0 := Gettickcount64;
|
||||
IF NOT(ReadAirports('airports.dat')) then
|
||||
HALT(129);
|
||||
T1 := Gettickcount64;
|
||||
Writeln((T1-T0),' ms for reading airports.dat');
|
||||
cntAirports := length(AirPorts);
|
||||
|
||||
with myKoor do
|
||||
begin
|
||||
lat := 51.514669*cDegToRad;
|
||||
lon := 2.198581*cDegToRad;
|
||||
sincos(lat,sinLat,cosLat);
|
||||
sincos(lon,sinLon,cosLon);
|
||||
end;
|
||||
|
||||
randomize;
|
||||
T0 := Gettickcount64;
|
||||
For i := rounds-2 downto 0 do
|
||||
Begin
|
||||
testKoors.Koor1 := AirPorts[random(cntAirports)].Sol_Koor;
|
||||
FindNearest(testKoors,cntAirports,cntNearest);
|
||||
end;
|
||||
testKoors.Koor1 := myKoor;
|
||||
FindNearest(testKoors,cntAirports,cntNearest);
|
||||
T1 := Gettickcount64;
|
||||
Writeln((T1-T0),' ms for searching ',rounds,' times of '
|
||||
,cntNearest,' nearest out of ',cntAirports,' airports');
|
||||
writeln(cntInserts,' inserts to find them');
|
||||
writeln;
|
||||
|
||||
FindNearest(testKoors,cntAirports,20);
|
||||
with myKoor do
|
||||
writeln(Format('Nearest to latitude %7.5f,longitude %7.5f degrees',
|
||||
[cRadToDeg*lat,cRadToDeg*lon]));
|
||||
writeln;
|
||||
Out_MinSol;
|
||||
end.
|
||||
33
Task/Distance-and-Bearing/J/distance-and-bearing.j
Normal file
33
Task/Distance-and-Bearing/J/distance-and-bearing.j
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
DAT=: {{ require'web/gethttp csv'
|
||||
if.0=#$fread F=.'airports.dat' do.
|
||||
(gethttp y) fwrite F
|
||||
end.
|
||||
readcsv F
|
||||
}}'https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat'
|
||||
LATLONG=: _".&>6 7{"1 DAT
|
||||
|
||||
fmtm=: {{
|
||||
9!:7]9 1 1#' -'
|
||||
r=._1 _1}.1 1}.":boxopen y
|
||||
~.r[9!:7]9 1 1#'+|-'
|
||||
}}
|
||||
AIRPORTS=: 1 3 5{"1 DAT
|
||||
|
||||
deg=: %&180p_1 NB. convert from degrees
|
||||
R=: 21600 % 2p1 NB. radius of spherical earth in nautical miles
|
||||
|
||||
dist=: {{R*2*_1 o.1<.%:(*:1 o.0.5*x-y)p.x*&(2 o.{.)y}}°
|
||||
bear=: {{
|
||||
re=. (2 o.{.y)*1 o.dlon=.y-&{:x
|
||||
2p1|1r2p1-{:*.re j. ((*|.)/+.^j.x,&{.y) p.-2 o.dlon
|
||||
}}&.deg
|
||||
|
||||
NB. round y to nearest whole number under multiplying by x
|
||||
pkg=: {{ <"0 (<.0.5+x*y)%x }}
|
||||
|
||||
LABELS=: ;:'Airport Country ICAO Distance Bearing'
|
||||
|
||||
nearest=: {{
|
||||
ndx=. 20{./: d=. y dist"1 LATLONG NB. 20 nearest airports
|
||||
fmtm LABELS,(ndx{AIRPORTS),"1 (10 pkg ndx{d),.1 pkg y bear"1 ndx{LATLONG
|
||||
}}
|
||||
130
Task/Distance-and-Bearing/Java/distance-and-bearing-1.java
Normal file
130
Task/Distance-and-Bearing/Java/distance-and-bearing-1.java
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
// The Airport class holds each airport object
|
||||
package distanceAndBearing;
|
||||
public class Airport {
|
||||
private String airport;
|
||||
private String country;
|
||||
private String icao;
|
||||
private double lat;
|
||||
private double lon;
|
||||
public String getAirportName() { return this.airport; }
|
||||
public void setAirportName(String airport) { this.airport = airport; }
|
||||
public String getCountry() { return this.country; }
|
||||
public void setCountry(String country) { this.country = country; }
|
||||
public String getIcao() { return this.icao; }
|
||||
public void setIcao(String icao) { this.icao = icao; }
|
||||
public double getLat() { return this.lat; }
|
||||
public void setLat(double lat) { this.lat = lat; }
|
||||
public double getLon() { return this.lon; }
|
||||
public void setLon(double lon) { this.lon = lon; }
|
||||
@Override
|
||||
public String toString() {return "Airport: " + getAirportName() + ": ICAO: " + getIcao();}
|
||||
}
|
||||
|
||||
// The DistanceAndBearing class does all the work.
|
||||
package distanceAndBearing;
|
||||
import java.io.File;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.Collectors;
|
||||
public class DistanceAndBearing {
|
||||
private final double earthRadius = 6371;
|
||||
private File datFile;
|
||||
private List<Airport> airports;
|
||||
public DistanceAndBearing() { this.airports = new ArrayList<Airport>(); }
|
||||
public boolean readFile(String filename) {
|
||||
this.datFile = new File(filename);
|
||||
try {
|
||||
Scanner fileScanner = new Scanner(datFile);
|
||||
String line;
|
||||
while (fileScanner.hasNextLine()) {
|
||||
line = fileScanner.nextLine();
|
||||
line = line.replace(", ", "; "); // There are some commas in airport names in the dat
|
||||
// file
|
||||
line = line.replace(",\",\"", "\",\""); // There are some airport names that
|
||||
// end in a comma in the dat file
|
||||
String[] parts = line.split(",");
|
||||
Airport airport = new Airport();
|
||||
airport.setAirportName(parts[1].replace("\"", "")); // Remove the double quotes from the string
|
||||
airport.setCountry(parts[3].replace("\"", "")); // Remove the double quotes from the string
|
||||
airport.setIcao(parts[5].replace("\"", "")); // Remove the double quotes from the string
|
||||
airport.setLat(Double.valueOf(parts[6]));
|
||||
airport.setLon(Double.valueOf(parts[7]));
|
||||
this.airports.add(airport);
|
||||
}
|
||||
fileScanner.close();
|
||||
return true; // Return true if the read was successful
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false; // Return false if the read was not successful
|
||||
}}
|
||||
public double[] calculate(double lat1, double lon1, double lat2, double lon2) {
|
||||
double[] results = new double[2];
|
||||
double dLat = Math.toRadians(lat2 - lat1);
|
||||
double dLon = Math.toRadians(lon2 - lon1);
|
||||
double rlat1 = Math.toRadians(lat1);
|
||||
double rlat2 = Math.toRadians(lat2);
|
||||
double a = Math.pow(Math.sin(dLat / 2), 2)
|
||||
+ Math.pow(Math.sin(dLon / 2), 2) * Math.cos(rlat1) * Math.cos(rlat2);
|
||||
double c = 2 * Math.asin(Math.sqrt(a));
|
||||
double distance = earthRadius * c;
|
||||
DecimalFormat df = new DecimalFormat("#0.00");
|
||||
distance = Double.valueOf(df.format(distance));
|
||||
results[0] = distance;
|
||||
double X = Math.cos(rlat2) * Math.sin(dLon);
|
||||
double Y = Math.cos(rlat1) * Math.sin(rlat2) - Math.sin(rlat1) * Math.cos(rlat2) * Math.cos(dLon);
|
||||
double heading = Math.atan2(X, Y);
|
||||
heading = Math.toDegrees(heading);
|
||||
results[1] = heading;
|
||||
return results;
|
||||
}
|
||||
public Airport searchByName(final String name) {
|
||||
Airport airport = new Airport();
|
||||
List<Airport> results = this.airports.stream().filter(ap -> ap.getAirportName().contains(name))
|
||||
.collect(Collectors.toList());
|
||||
airport = results.get(0);
|
||||
return airport;
|
||||
}
|
||||
public List<Airport> findClosestAirports(double lat, double lon) {
|
||||
// TODO Auto-generated method stub
|
||||
Map<Double, Airport> airportDistances = new HashMap<>();
|
||||
Map<Double, Airport> airportHeading = new HashMap<>();
|
||||
List<Airport> closestAirports = new ArrayList<Airport>();
|
||||
// This loop finds the distance and heading for every airport and saves them
|
||||
// into two separate Maps
|
||||
for (Airport ap : this.airports) {
|
||||
double[] result = calculate(lat, lon, ap.getLat(), ap.getLon());
|
||||
airportDistances.put(result[0], ap);
|
||||
airportHeading.put(result[1], ap);
|
||||
}
|
||||
// Get the keyset from the distance map and sort it.
|
||||
ArrayList<Double> distances = new ArrayList<>(airportDistances.keySet());
|
||||
Collections.sort(distances);
|
||||
// Get the first 20 airports by finding the value in the distance map for
|
||||
// each distance in the sorted Arraylist. Then get the airport name, and
|
||||
// use that to search for the airport in the airports List.
|
||||
// Save that into a new List
|
||||
for (int i = 0; i < 20; i++) { closestAirports.add(searchByName((airportDistances.get(distances.get(i)).getAirportName())));}
|
||||
// Find the distance and heading for each of the top 20 airports.
|
||||
Map<String, Double> distanceMap = new HashMap<>();
|
||||
for (Double d : airportDistances.keySet()) { distanceMap.put(airportDistances.get(d).getAirportName(), d);}
|
||||
Map<String, Double> headingMap = new HashMap<>();
|
||||
for (Double d : airportHeading.keySet()) {
|
||||
double d2 = d;
|
||||
if(d2<0){d2+=360'}
|
||||
headingMap.put(airportHeading.get(d).getAirportName(), d2); }
|
||||
|
||||
// Print the results.
|
||||
System.out.printf("%-4s %-40s %-25s %-6s %12s %15s\n", "Num", "Airport", "Country", "ICAO", "Distance", "Bearing");
|
||||
System.out.println("-----------------------------------------------------------------------------------------------------------");
|
||||
int i = 0;
|
||||
for (Airport a : closestAirports) {
|
||||
System.out.printf("%-4s %-40s %-25s %-6s %12.1f %15.0f\n", ++i, a.getAirportName(), a.getCountry(), a.getIcao(), distanceMap.get(a.getAirportName())*0.5399568, headingMap.get(a.getAirportName()));
|
||||
}
|
||||
return closestAirports;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import distanceAndBearing.DistanceAndBearing;
|
||||
public class MyClass {
|
||||
|
||||
public static void main(String[] args) {
|
||||
DistanceAndBearing dandb = new DistanceAndBearing();
|
||||
dandb.readFile("airports.txt");
|
||||
dandb.findClosestAirports(51.514669,2.198581);
|
||||
}
|
||||
}
|
||||
83
Task/Distance-and-Bearing/Jq/distance-and-bearing.jq
Normal file
83
Task/Distance-and-Bearing/Jq/distance-and-bearing.jq
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
def pi: 1|atan * 4;
|
||||
|
||||
# Read a TSV file one line at a time,
|
||||
# and emit a stream of arrays, one array per line:
|
||||
def readTSV: [inputs | sub(" *$";"") / "\t" ];
|
||||
|
||||
def airports:
|
||||
[readTSV
|
||||
| {airportID: (.[0] | tonumber),
|
||||
name : .[1],
|
||||
city : .[2],
|
||||
country : .[3],
|
||||
iata : .[4],
|
||||
icao : .[5],
|
||||
latitude : (.[6] | tonumber),
|
||||
longitude : (.[7] | tonumber),
|
||||
altitude : (.[8] | tonumber),
|
||||
timezone : .[9],
|
||||
dst : .[10],
|
||||
tzOlson : .[11],
|
||||
type : .[12],
|
||||
source : .[13]} ];
|
||||
|
||||
def calculateDistance(lat1; lon1; lat2; lon2; units):
|
||||
if (lat1 == lat2 and lon1 == lon2) then 0
|
||||
else pi as $pi
|
||||
| ($pi * lat1 / 180) as $radlat1
|
||||
| ($pi * lat2 / 180) as $radlat2
|
||||
| (lon1 - lon2) as $theta
|
||||
| ($pi * $theta / 180) as $radtheta
|
||||
| {}
|
||||
| .dist = ($radlat1|sin) * ($radlat2|sin) +
|
||||
($radlat1|cos) * ($radlat2|cos) * ($radtheta|cos)
|
||||
| if .dist > 1 then .dist = 1 else . end
|
||||
| .dist |= (acos * 180 / $pi) * 60 * 1.1515576 # distance in statute miles
|
||||
| if (units == "K") then .dist *= 1.609344 # distance in kilometers
|
||||
elif (units == "N") then .dist *= 0.868976 # distance in nautical miles
|
||||
else .
|
||||
end
|
||||
| .dist
|
||||
end ;
|
||||
|
||||
def calculateBearing(lat1; lon1; lat2; lon2):
|
||||
if (lat1 == lat2 and lon1 == lon2) then 0
|
||||
else pi as $pi
|
||||
| ($pi * lat1 / 180) as $radlat1
|
||||
| ($pi * lat2 / 180) as $radlat2
|
||||
| ($pi * (lon2 - lon1) / 180) as $raddlon
|
||||
| ( ($raddlon|sin) * ($radlat2|cos) ) as $y
|
||||
| (($radlat1|cos) * ($radlat2|sin) -
|
||||
($radlat1|sin) * ($radlat2|cos) * ($raddlon|cos)) as $x
|
||||
| ((atan2($y;$x) * 180 / $pi) + 360) % 360
|
||||
end;
|
||||
|
||||
# request from airplane at position $X; $Y
|
||||
def request($X; $Y):
|
||||
airports as $airports
|
||||
| reduce $airports[] as $a ([];
|
||||
((calculateDistance($X; $Y; $a.latitude; $a.longitude; "N") * 10 | round)
|
||||
/ 10) as $dist
|
||||
| (calculateBearing($X; $Y; $a.latitude; $a.longitude)|round ) as $bear
|
||||
| . + [ [$a.name, $a.country, $a.icao, $dist, $bear] ] ) ;
|
||||
|
||||
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
|
||||
|
||||
def fmt:
|
||||
def l($n): lpad($n);
|
||||
"\(.[0] |l(36)) | \(.[1]|l(14)) | \(.[2]|l(4)) |\(.[3]|l(15)) |\(.[4]|l(10))";
|
||||
|
||||
# Example:
|
||||
def display($n):
|
||||
"Closest \($n) destinations relative to position \(.[0]), \(.[1]):",
|
||||
"",
|
||||
" Name | Country | ICAO | Distance in NM | Bearing in ° ",
|
||||
"-------------------------------------+----------------+------+----------------+--------------",
|
||||
(request(.[0]; .[1])
|
||||
| sort_by( .[3] )
|
||||
| .[0:$n][] | fmt ) ;
|
||||
|
||||
|
||||
[51.514669, 2.198581] | display(20)
|
||||
|
||||
''Invocation'': jq -nrRf distance-and-bearing.jq airports.tsv
|
||||
40
Task/Distance-and-Bearing/Julia/distance-and-bearing.julia
Normal file
40
Task/Distance-and-Bearing/Julia/distance-and-bearing.julia
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using DataFrames
|
||||
using CSV
|
||||
|
||||
const EARTH_RADIUS_KM = 6372.8
|
||||
const TASK_CONVERT_NM = 0.0094174
|
||||
const AIRPORT_DATA_FILE = "airports.dat.txt"
|
||||
|
||||
const QUERY = (latitude = 51.514669, longitude = 2.198581)
|
||||
|
||||
"""
|
||||
Given two latitude, longitude pairs in degrees for two points on the Earth,
|
||||
get distance (nautical miles) and initial direction of travel (degrees)
|
||||
for travel from lat1, lon1 to lat2, lon2
|
||||
"""
|
||||
function haversine(lat1, lon1, lat2, lon2)
|
||||
dlat = lat2 - lat1
|
||||
dlon = lon2 - lon1
|
||||
a = sind(dlat / 2)^2 + cosd(lat1) * cosd(lat2) * sind(dlon / 2)^2
|
||||
c = 2.0 * asind(sqrt(a))
|
||||
theta = atand(sind(dlon) * cosd(lat2),
|
||||
cosd(lat1) * sind(lat2) - sind(lat1) * cosd(lat2) * cosd(dlon))
|
||||
theta = (theta + 360) % 360
|
||||
return EARTH_RADIUS_KM * c * TASK_CONVERT_NM, theta
|
||||
end
|
||||
|
||||
""" Given latitude and longitude, find `wanted` closest airports in database file csv. """
|
||||
function find_nearest_airports(latitude, longitude, wanted = 20, csv = AIRPORT_DATA_FILE)
|
||||
airports = DataFrame(CSV.File(csv))[:, [2, 4, 6, 7, 8]]
|
||||
airports[!, "d"] .= 0.0
|
||||
airports[!, "b"] .= 0
|
||||
rename!(airports, [:Name, :Country, :ICAO, :Latitude_deg, :Longitude_deg, :Distance, :Bearing])
|
||||
for r in eachrow(airports)
|
||||
distance, bearing = haversine(latitude, longitude, r.Latitude_deg, r.Longitude_deg)
|
||||
r.Distance, r.Bearing = round(distance, digits = 1), Int(round(bearing))
|
||||
end
|
||||
sort!(airports, :Distance)
|
||||
return airports[1:wanted, [:Name, :Country, :ICAO, :Distance, :Bearing]]
|
||||
end
|
||||
|
||||
println(find_nearest_airports(QUERY.latitude, QUERY.longitude))
|
||||
60
Task/Distance-and-Bearing/Nim/distance-and-bearing.nim
Normal file
60
Task/Distance-and-Bearing/Nim/distance-and-bearing.nim
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import std/[algorithm, math, parsecsv, strformat, strutils]
|
||||
|
||||
const
|
||||
R = 6_371 / 1.852 # Mean radius of Earth in nautic miles.
|
||||
PlaneLat = 51.514669
|
||||
PlaneLong = 2.198581
|
||||
|
||||
type
|
||||
|
||||
Airport = object
|
||||
name: string
|
||||
country: string
|
||||
icao: string
|
||||
latitude: float
|
||||
longitude: float # In radians.
|
||||
altitude: float # In radians.
|
||||
|
||||
func distance(𝜑₁, λ₁, 𝜑₂, λ₂: float): float =
|
||||
## Return the distance computed using the Haversine formula.
|
||||
## Angles are in radians. The result is expressed in nautic miles.
|
||||
let a = sin((𝜑₂ - 𝜑₁) * 0.5)^2 + cos(𝜑₁) * cos(𝜑₂) * sin((λ₂ - λ₁) * 0.5)^2
|
||||
let c = 2 * arctan2(sqrt(a), sqrt(1 - a))
|
||||
result = R * c
|
||||
|
||||
func bearing(𝜑₁, λ₁, 𝜑₂, λ₂: float): float =
|
||||
## Return the bearing.
|
||||
## Angles are in radians. The result is expressed in degrees in range [0..360[.
|
||||
let Δλ = λ₂ - λ₁
|
||||
result = arctan2(sin(Δλ) * cos(𝜑₂), cos(𝜑₁) * sin(𝜑₂) - sin(𝜑₁) * cos(𝜑₂) * cos(Δλ))
|
||||
result = (result.radToDeg + 360) mod 360
|
||||
|
||||
# Parse the "airports.dat" file.
|
||||
var parser: CsvParser
|
||||
var airports: seq[Airport]
|
||||
parser.open("airports.dat")
|
||||
while parser.readRow():
|
||||
assert parser.row.len == 14
|
||||
airports.add Airport(name: parser.row[1],
|
||||
country: parser.row[3],
|
||||
icao: parser.row[5],
|
||||
latitude: parser.row[6].parseFloat().degToRad,
|
||||
longitude: parser.row[7].parseFloat().degToRad)
|
||||
|
||||
# Compute the distances then sort them keeping the airport index.
|
||||
type Distances = tuple[value: float; index: int]
|
||||
var distances : seq[Distances]
|
||||
let 𝜑₁ = PlaneLat.degToRad
|
||||
let λ₁ = PlaneLong.degToRad
|
||||
for i, airport in airports:
|
||||
distances.add (distance(𝜑₁, λ₁, airport.latitude, airport.longitude), i)
|
||||
distances.sort(Ascending)
|
||||
|
||||
# Display the result for the 20 nearest airports.
|
||||
echo &"""{"Airport":<40}{"Country":<20}{"ICAO":<9}{"Distance":<9}{"Bearing":>9}"""
|
||||
echo repeat("─", 88)
|
||||
for i in 0..19:
|
||||
let (d, idx) = distances[i]
|
||||
let ap = airports[idx]
|
||||
let b = bearing(𝜑₁, λ₁, ap.latitude, ap.longitude)
|
||||
echo &"{ap.name:<40}{ap.country:<20}{ap.icao:<11}{d:4.1f}{b.toInt:10}"
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* copy CSV aiports.dat from URL */
|
||||
csv=externstr("curl 'https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat'");
|
||||
|
||||
/* We want an easy convert from CSV to matrix. */
|
||||
/* Remove all those backslashes in airports.dat */
|
||||
{
|
||||
for(i = 1 , #csv, tmp = Vecsmall(csv[i]);
|
||||
for(j = 1 , #tmp, if(tmp[j]==92, tmp[j]=78));
|
||||
csv[i] = strchr(tmp)
|
||||
);
|
||||
};
|
||||
|
||||
{
|
||||
convert(csv,mat)=
|
||||
write1(mat,"[");
|
||||
for(i=1, #csv-1,
|
||||
write1(mat,csv[i]); write1(mat,";")
|
||||
);
|
||||
write1(mat,csv[#csv]); write(mat,"]")
|
||||
};
|
||||
|
||||
convert(csv,airports);
|
||||
M = read(airports);
|
||||
|
||||
{
|
||||
distance(lat1, lon1, lat2, lon2, unit = "mi") =
|
||||
my(dist = 0, rlat1, rlat2, rtheta);
|
||||
if(lat1!=lat2 || lon1!=lon2,
|
||||
rlat1 = lat1*Pi/180; rlat2 = lat2*Pi/180;
|
||||
rtheta = (lon1-lon2)*Pi/180;
|
||||
dist = sin(rlat1)*sin(rlat2) + cos(rlat1)*cos(rlat2)*cos(rtheta);
|
||||
dist = acos(min(dist,1))*180/Pi*60*1.1515576;
|
||||
if(unit=="Km", dist*= 1.609344, unit=="NM", dist*= 0.868976)
|
||||
);dist
|
||||
};
|
||||
|
||||
{
|
||||
bearing(lat1, lon1, lat2, lon2)=
|
||||
my(bear, rlat1, rlat2, rdlon, x, y);
|
||||
if (lat1!=lat2 || lon1!=lon2,
|
||||
rlat1 = lat1*Pi/180; rlat2 = lat2*Pi/180;
|
||||
rdlon = (lon2-lon1)*Pi/180;
|
||||
y = sin(rdlon)*cos(rlat2);
|
||||
x = cos(rlat1)*sin(rlat2) - sin(rlat1)*cos(rlat2)*cos(rdlon);
|
||||
/* Pari/GP has no built-in atan2() function. */
|
||||
if( x>0, bear=atan(y/x), x<0 && y>0, bear=atan(y/x)+Pi,
|
||||
x<0 && y==0, bear=Pi, x<0 && y<0, bear=atan(y/x)-Pi,
|
||||
x==0 && y>0, bear=Pi/2, x==0 && y<0, bear=-Pi/2);
|
||||
bear = (bear*180/Pi+360)%360;
|
||||
);bear
|
||||
};
|
||||
|
||||
{
|
||||
request(lat, lon, r = 20 , unit = "NM")=
|
||||
my(D = vector(#M[,1]), R = matrix(r+1, 5));
|
||||
R[1,1] = "NAME"; R[1,2] = "COUNTRY"; R[1,3] = "ICAO"; R[1,4] = "DISTANCE"; R[1,5] = "BEARING";
|
||||
printf("%-38s\t%-16s\t%-4s\t%s\t%s\n", R[1,1], R[1,2], R[1,3], R[1,4], R[1,5]);
|
||||
for(i = 1, #M[,1],
|
||||
D[i] = [distance(lat, lon, M[i,7], M[i,8], unit) , i];
|
||||
);
|
||||
D=vecsort(D);
|
||||
for(i = 1, r,
|
||||
R[i+1,1] = M[D[i][2],2]; R[i+1,2] = M[D[i][2],4]; R[i+1,3] = M[D[i][2],6];
|
||||
R[i+1,4] = D[i][1]; R[i+1,5] = bearing(lat, lon, M[D[i][2],7], M[D[i][2],8]);
|
||||
printf("%-38s\t%-16s\t%-4s\t%8.1f\t%7.0f\n", R[i+1,1], R[i+1,2], R[i+1,3], R[i+1,4], R[i+1,5]);
|
||||
);
|
||||
}
|
||||
|
||||
request(51.514669, 2.198581)
|
||||
53
Task/Distance-and-Bearing/Perl/distance-and-bearing.pl
Normal file
53
Task/Distance-and-Bearing/Perl/distance-and-bearing.pl
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use v5.36;
|
||||
use utf8;
|
||||
binmode STDOUT, ':utf8';
|
||||
use Text::CSV 'csv';
|
||||
use Math::Trig;
|
||||
|
||||
use constant EARTH_RADIUS_IN_NAUTICAL_MILES => 6372.8 / 1.852;
|
||||
use constant TAU => 2 * 2 * atan2(1, 0);
|
||||
|
||||
sub degrees ( $rad ) { $rad / TAU * 360 }
|
||||
sub radians ( $deg ) { $deg * TAU / 360 }
|
||||
sub haversine ( $x ) { sin($x / 2)**2 }
|
||||
sub arc_haver ( $x ) { asin(sqrt($x)) * 2 }
|
||||
|
||||
sub great_circle_distance ( $p1, $l1, $p2, $l2 ) {
|
||||
arc_haver(
|
||||
haversine($p2 - $p1)
|
||||
+ haversine($l2 - $l1) * cos($p1) * cos($p2)
|
||||
);
|
||||
}
|
||||
|
||||
sub great_circle_bearing ( $p1, $l1, $p2, $l2 ) {
|
||||
atan2( cos($p2) * sin($l2 - $l1),
|
||||
cos($p1)*sin($p2) - sin($p1) * cos($p2) * cos($l2 - $l1),
|
||||
);
|
||||
}
|
||||
|
||||
sub distance_and_bearing ( $lat1, $lon1, $lat2, $lon2 ) {
|
||||
my @ll = map { radians $_ } $lat1, $lon1, $lat2, $lon2;
|
||||
my $dist = great_circle_distance(@ll);
|
||||
my $theta = great_circle_bearing( @ll);
|
||||
$dist * EARTH_RADIUS_IN_NAUTICAL_MILES, degrees( $theta < 0 ? $theta + TAU : $theta);
|
||||
}
|
||||
|
||||
sub find_nearest_airports ( $latitude, $longitude, $csv_path ) {
|
||||
my $airports = csv(
|
||||
in => $csv_path,
|
||||
headers => [<ID Name City Country IATA ICAO Latitude Longitude>],
|
||||
);
|
||||
|
||||
for my $row (@$airports) {
|
||||
($$row{'Distance'},$$row{'Bearing'}) = distance_and_bearing( $latitude, $longitude, $$row{'Latitude'}, $$row{'Longitude'} );
|
||||
}
|
||||
|
||||
sort { $a->{'Distance'} <=> $b->{'Distance'} } @$airports;
|
||||
}
|
||||
|
||||
my($lat, $lon, $wanted, $csv) = (51.514669, 2.198581, 20, 'ref/airports.dat');
|
||||
printf "%7s\t%7s\t%-7s\t%-15s\t%s\n", <Dist Bear ICAO Country Name>;
|
||||
for my $airport (find_nearest_airports($lat, $lon, $csv)) {
|
||||
printf "%7.1f\t %03d\t%-7s\t%-15s\t%s\n", map { $airport->{$_} } <Distance Bearing ICAO Country Name>;
|
||||
last unless --$wanted
|
||||
}
|
||||
69
Task/Distance-and-Bearing/Phix/distance-and-bearing.phix
Normal file
69
Task/Distance-and-Bearing/Phix/distance-and-bearing.phix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
(notonline)-->
|
||||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- file i/o</span>
|
||||
<span style="color: #008080;">enum</span> <span style="color: #000000;">Airport_ID</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Name</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">City</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Country</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">IATA</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ICAO</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Latitude</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Longitude</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Altitude</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Timezone</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">DST</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Tz_Olson</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Type</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Source</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">tabulate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ri</span> <span style="color: #008080;">in</span> <span style="color: #000000;">s</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">','</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">14</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">","</span><span style="color: #0000FF;">&</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">ri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">..</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span> <span style="color: #008080;">in</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Airport_ID</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Latitude</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Longitude</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Altitude</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">ri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span> <span style="color: #008080;">in</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">City</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Country</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ICAO</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">ri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #008000;">`"`</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ri</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">airports</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tabulate</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"airports.dat"</span><span style="color: #0000FF;">))</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">distance</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon2</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">units</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">dist</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">lat2</span> <span style="color: #008080;">or</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">lon2</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">radlat1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">radlat2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">radtheta</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">lon1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">lon2</span><span style="color: #0000FF;">)*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span>
|
||||
<span style="color: #000000;">dist</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat1</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat2</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat1</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat2</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radtheta</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">dist</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">arccos</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dist</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">))*</span><span style="color: #000000;">180</span><span style="color: #0000FF;">/</span><span style="color: #004600;">PI</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1.1515576</span> <span style="color: #000080;font-style:italic;">-- in Statute Miles</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">units</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'K'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">dist</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">1.609344</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- in Kilometres</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">units</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'N'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">dist</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">0.868976</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- in Nautical Miles</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">dist</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">bearing</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">bear</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">lat2</span> <span style="color: #008080;">or</span> <span style="color: #000000;">lon1</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">lon2</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">radlat1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lat1</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">radlat2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lat2</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">raddlon</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">lon2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">lon1</span><span style="color: #0000FF;">)*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raddlon</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat2</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat1</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat2</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">-</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat1</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radlat2</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raddlon</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">bear</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">atan2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">180</span><span style="color: #0000FF;">/</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">+</span><span style="color: #000000;">360</span><span style="color: #0000FF;">,</span><span style="color: #000000;">360</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">bear</span><span style="color: #0000FF;">;</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">query</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">lat</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lon</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">rows</span><span style="color: #0000FF;">=</span><span style="color: #000000;">20</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">a</span> <span style="color: #008080;">in</span> <span style="color: #000000;">airports</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">lat2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Latitude</span><span style="color: #0000FF;">],</span>
|
||||
<span style="color: #000000;">lon2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Longitude</span><span style="color: #0000FF;">],</span>
|
||||
<span style="color: #000000;">dist</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">distance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lon</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lon2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'N'</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">bear</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bearing</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lat</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lon</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lat2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lon2</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Name</span><span style="color: #0000FF;">],</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Country</span><span style="color: #0000FF;">],</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ICAO</span><span style="color: #0000FF;">],</span><span style="color: #000000;">dist</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bear</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort_columns</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">})[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">rows</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" Name | Country | ICAO | Distance in NM | Bearing in ° \n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-------------------------------------+----------------+------+----------------+--------------\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">" %-36s| %-15s| %4s | %4.1f | %3d"</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(%d rows)\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rows</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #000000;">query</span><span style="color: #0000FF;">(</span><span style="color: #000000;">51.514669</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2.198581</span><span style="color: #0000FF;">)</span>
|
||||
<!--
|
||||
47
Task/Distance-and-Bearing/Python/distance-and-bearing.py
Normal file
47
Task/Distance-and-Bearing/Python/distance-and-bearing.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
''' Rosetta Code task Distance_and_Bearing '''
|
||||
|
||||
from math import radians, degrees, sin, cos, asin, atan2, sqrt
|
||||
from pandas import read_csv
|
||||
|
||||
|
||||
EARTH_RADIUS_KM = 6372.8
|
||||
TASK_CONVERT_NM = 0.0094174
|
||||
AIRPORT_DATA_FILE = 'airports.dat.txt'
|
||||
|
||||
QUERY_LATITUDE, QUERY_LONGITUDE = 51.514669, 2.198581
|
||||
|
||||
|
||||
def haversine(lat1, lon1, lat2, lon2):
|
||||
'''
|
||||
Given two latitude, longitude pairs in degrees for two points on the Earth,
|
||||
get distance (nautical miles) and initial direction of travel (degrees)
|
||||
for travel from lat1, lon1 to lat2, lon2
|
||||
'''
|
||||
rlat1, rlon1, rlat2, rlon2 = [radians(x) for x in [lat1, lon1, lat2, lon2]]
|
||||
dlat = rlat2 - rlat1
|
||||
dlon = rlon2 - rlon1
|
||||
arc = sin(dlat / 2) ** 2 + cos(rlat1) * cos(rlat2) * sin(dlon / 2) ** 2
|
||||
clen = 2.0 * degrees(asin(sqrt(arc)))
|
||||
theta = atan2(sin(dlon) * cos(rlat2),
|
||||
cos(rlat1) * sin(rlat2) - sin(rlat1) * cos(rlat2) * cos(dlon))
|
||||
theta = (degrees(theta) + 360) % 360
|
||||
return EARTH_RADIUS_KM * clen * TASK_CONVERT_NM, theta
|
||||
|
||||
|
||||
def find_nearest_airports(latitude, longitude, wanted=20, csv=AIRPORT_DATA_FILE):
|
||||
''' Given latitude and longitude, find `wanted` closest airports in database file csv. '''
|
||||
airports = read_csv(csv, header=None, usecols=[1, 3, 5, 6, 7], names=[
|
||||
'Name', 'Country', 'ICAO', 'Latitude', 'Longitude'])
|
||||
airports['Distance'] = 0.0
|
||||
airports['Bearing'] = 0
|
||||
for (idx, row) in enumerate(airports.itertuples()):
|
||||
distance, bearing = haversine(
|
||||
latitude, longitude, row.Latitude, row.Longitude)
|
||||
airports.at[idx, 'Distance'] = round(distance, ndigits=1)
|
||||
airports.at[idx, 'Bearing'] = int(round(bearing))
|
||||
|
||||
airports.sort_values(by=['Distance'], ignore_index=True, inplace=True)
|
||||
return airports.loc[0:wanted-1, ['Name', 'Country', 'ICAO', 'Distance', 'Bearing']]
|
||||
|
||||
|
||||
print(find_nearest_airports(QUERY_LATITUDE, QUERY_LONGITUDE))
|
||||
58
Task/Distance-and-Bearing/Raku/distance-and-bearing.raku
Normal file
58
Task/Distance-and-Bearing/Raku/distance-and-bearing.raku
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use Text::CSV;
|
||||
|
||||
constant $EARTH_RADIUS_IN_NAUTICAL_MILES = 6372.8 / 1.852;
|
||||
|
||||
sub degrees ( Real $rad ) { $rad / tau * 360 }
|
||||
sub radians ( Real $deg ) { $deg * tau / 360 }
|
||||
sub haversine ( Real $x ) { ($x / 2).sin.² }
|
||||
sub arc_haver ( Real $x ) { $x.sqrt.asin * 2 }
|
||||
|
||||
sub great_circle_distance ( \φ1, \λ1, \φ2, \λ2 ) {
|
||||
# https://en.wikipedia.org/wiki/Haversine_formula
|
||||
# latitude (represented by φ) and longitude (represented by λ)
|
||||
# hav(θ) = hav(φ₂ − φ₁) + cos(φ₁) cos(φ₂) hav(λ₂ − λ₁)
|
||||
arc_haver(
|
||||
haversine(φ2 - φ1)
|
||||
+ haversine(λ2 - λ1) * cos(φ1) * cos(φ2)
|
||||
);
|
||||
}
|
||||
|
||||
sub great_circle_bearing ( \φ1, \λ1, \φ2, \λ2 ) {
|
||||
atan2( φ2.cos * (λ2 - λ1).sin,
|
||||
φ1.cos * φ2.sin - φ1.sin * φ2.cos * (λ2 - λ1).cos,
|
||||
);
|
||||
}
|
||||
|
||||
sub distance_and_bearing ( $lat1, $lon1, $lat2, $lon2 ) {
|
||||
my @ll = map &radians, $lat1, $lon1, $lat2, $lon2;
|
||||
|
||||
my $dist = great_circle_distance(|@ll);
|
||||
my $theta = great_circle_bearing( |@ll);
|
||||
|
||||
return $dist * $EARTH_RADIUS_IN_NAUTICAL_MILES,
|
||||
degrees( $theta + (tau if $theta < 0) )
|
||||
}
|
||||
|
||||
sub find_nearest_airports ( $latitude, $longitude, $csv_path ) {
|
||||
my &d_and_b_from_here = &distance_and_bearing.assuming($latitude, $longitude);
|
||||
|
||||
my @airports = csv(
|
||||
in => $csv_path,
|
||||
headers => [<ID Name City Country IATA ICAO Latitude Longitude>],
|
||||
);
|
||||
|
||||
for @airports -> %row {
|
||||
%row<Distance Bearing> = d_and_b_from_here( +%row<Latitude>, +%row<Longitude> );
|
||||
}
|
||||
|
||||
return @airports.sort(*.<Distance>);
|
||||
}
|
||||
|
||||
sub MAIN ( $lat = 51.514669, $long = 2.198581, $wanted = 20, $csv = 'airports.dat' ) {
|
||||
printf "%7s\t%7s\t%-7s\t%-15s\t%s\n", <Dist Bear ICAO Country Name>;
|
||||
|
||||
for find_nearest_airports($lat, $long, $csv).head($wanted) {
|
||||
printf "%7.1f\t %03d\t%-7s\t%-15s\t%s\n",
|
||||
.<Distance Bearing ICAO Country Name>;
|
||||
}
|
||||
}
|
||||
48
Task/Distance-and-Bearing/Ruby/distance-and-bearing.rb
Normal file
48
Task/Distance-and-Bearing/Ruby/distance-and-bearing.rb
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
require 'open-uri'
|
||||
require 'csv'
|
||||
include Math
|
||||
|
||||
RADIUS = 6372.8 # rough radius of the Earth, in kilometers
|
||||
|
||||
def spherical_distance(start_coords, end_coords)
|
||||
lat1, long1 = deg2rad(*start_coords)
|
||||
lat2, long2 = deg2rad(*end_coords)
|
||||
2 * RADIUS * asin(sqrt(sin((lat2-lat1)/2)**2 + cos(lat1) * cos(lat2) * sin((long2 - long1)/2)**2))
|
||||
end
|
||||
|
||||
def bearing(start_coords, end_coords)
|
||||
lat1, long1 = deg2rad(*start_coords)
|
||||
lat2, long2 = deg2rad(*end_coords)
|
||||
dlon = long2 - long1
|
||||
atan2(sin(dlon) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon))
|
||||
end
|
||||
|
||||
def deg2rad(lat, long)
|
||||
[lat * PI / 180, long * PI / 180]
|
||||
end
|
||||
|
||||
uri = "https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat"
|
||||
headers = %i(airportID
|
||||
name
|
||||
city
|
||||
country
|
||||
iata
|
||||
icao
|
||||
latitude
|
||||
longitude
|
||||
altitude
|
||||
timezone
|
||||
dst
|
||||
tzOlson
|
||||
type
|
||||
source)
|
||||
data = CSV.parse(URI.open(uri), headers: headers, converters: :numeric)
|
||||
|
||||
position = [51.514669, 2.198581]
|
||||
|
||||
data.each{|r| r[:dist] = (spherical_distance(position, [r[:latitude], r[:longitude]])/1.852).round(1)}
|
||||
closest = data.min_by(20){|row| row[:dist] }
|
||||
closest.each do |r|
|
||||
bearing = (bearing(position,[r[:latitude], r[:longitude]])*180/PI).round % 360
|
||||
puts "%-40s %-25s %-6s %12.1f %15.0f" % (r.values_at(:name, :country, :ICAO, :dist) << bearing)
|
||||
end
|
||||
22
Task/Distance-and-Bearing/SQL/distance-and-bearing-1.sql
Normal file
22
Task/Distance-and-Bearing/SQL/distance-and-bearing-1.sql
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-- create table airports with 14 columns
|
||||
CREATE TABLE airports (
|
||||
Airport_ID serial PRIMARY KEY,
|
||||
Name VARCHAR NOT NULL,
|
||||
City VARCHAR,
|
||||
Country VARCHAR NOT NULL,
|
||||
IATA VARCHAR,
|
||||
ICAO VARCHAR,
|
||||
Latitude double precision NOT NULL,
|
||||
Longitude double precision NOT NULL,
|
||||
Altitude SMALLINT,
|
||||
Timezone VARCHAR,
|
||||
DST VARCHAR,
|
||||
Tz_Olson VARCHAR,
|
||||
Type VARCHAR,
|
||||
Source VARCHAR
|
||||
);
|
||||
|
||||
-- copy CSV airports.dat from URL
|
||||
COPY airports FROM
|
||||
PROGRAM 'curl "https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat"'
|
||||
WITH (FORMAT csv);
|
||||
69
Task/Distance-and-Bearing/SQL/distance-and-bearing-2.sql
Normal file
69
Task/Distance-and-Bearing/SQL/distance-and-bearing-2.sql
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
-- calculate distance
|
||||
CREATE OR REPLACE FUNCTION calculate_distance(lat1 float, lon1 float, lat2 float, lon2 float, units varchar)
|
||||
RETURNS numeric AS $dist$
|
||||
DECLARE
|
||||
dist float = 0;
|
||||
radlat1 float;
|
||||
radlat2 float;
|
||||
theta float;
|
||||
radtheta float;
|
||||
BEGIN
|
||||
IF lat1 = lat2 AND lon1 = lon2
|
||||
THEN RETURN dist;
|
||||
ELSE
|
||||
radlat1 = pi() * lat1 / 180;
|
||||
radlat2 = pi() * lat2 / 180;
|
||||
theta = lon1 - lon2;
|
||||
radtheta = pi() * theta / 180;
|
||||
dist = sin(radlat1) * sin(radlat2) + cos(radlat1) * cos(radlat2) * cos(radtheta);
|
||||
|
||||
IF dist > 1 THEN dist = 1; END IF;
|
||||
|
||||
dist = acos(dist);
|
||||
dist = dist * 180 / pi();
|
||||
|
||||
-- Distance in Statute Miles
|
||||
dist = dist * 60 * 1.1515576;
|
||||
|
||||
-- Distance in Kilometres
|
||||
IF units = 'K' THEN dist = dist * 1.609344; END IF;
|
||||
|
||||
-- Distance in Nautical Miles
|
||||
IF units = 'N' THEN dist = dist * 0.868976; END IF;
|
||||
|
||||
dist = dist::numeric;
|
||||
RETURN dist;
|
||||
END IF;
|
||||
END;
|
||||
$dist$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
-- calculate bearing
|
||||
CREATE OR REPLACE FUNCTION calculate_bearing(lat1 float, lon1 float, lat2 float, lon2 float)
|
||||
RETURNS numeric AS $bear$
|
||||
DECLARE
|
||||
bear float = NULL;
|
||||
radlat1 float;
|
||||
radlat2 float;
|
||||
raddlon float;
|
||||
y float;
|
||||
x float;
|
||||
|
||||
BEGIN
|
||||
IF lat1 = lat2 AND lon1 = lon2
|
||||
THEN RETURN bear;
|
||||
ELSE
|
||||
radlat1 = pi() * lat1 / 180;
|
||||
radlat2 = pi() * lat2 / 180;
|
||||
raddlon = pi() * (lon2 - lon1) / 180;
|
||||
|
||||
y = sin(raddlon) * cos(radlat2);
|
||||
x = cos(radlat1) * sin(radlat2) - sin(radlat1) * cos(radlat2) * cos(raddlon);
|
||||
|
||||
bear = atan2(y, x) * 180 / pi();
|
||||
bear = (bear::numeric + 360) % 360;
|
||||
|
||||
RETURN bear;
|
||||
END IF;
|
||||
END;
|
||||
$bear$ LANGUAGE plpgsql;
|
||||
10
Task/Distance-and-Bearing/SQL/distance-and-bearing-3.sql
Normal file
10
Task/Distance-and-Bearing/SQL/distance-and-bearing-3.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
Select
|
||||
Name "Name",
|
||||
Country "Country",
|
||||
ICAO "ICAO",
|
||||
ROUND(calculate_distance(51.514669, 2.198581, Latitude, Longitude, 'N'), 1) "Distance in NM",
|
||||
ROUND(calculate_bearing(51.514669, 2.198581, Latitude, Longitude), 0) "Bearing in °"
|
||||
From
|
||||
airports
|
||||
ORDER BY "Distance in NM"
|
||||
LIMIT 20;
|
||||
90
Task/Distance-and-Bearing/Wren/distance-and-bearing.wren
Normal file
90
Task/Distance-and-Bearing/Wren/distance-and-bearing.wren
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import "io" for File
|
||||
import "./dynamic" for Tuple
|
||||
import "./str" for Str
|
||||
import "./fmt" for Fmt
|
||||
|
||||
var airportFields = [
|
||||
"airportID",
|
||||
"name",
|
||||
"city",
|
||||
"country",
|
||||
"iata",
|
||||
"icao",
|
||||
"latitude",
|
||||
"longitude",
|
||||
"altitude",
|
||||
"timezone",
|
||||
"dst",
|
||||
"tzOlson",
|
||||
"type",
|
||||
"source"
|
||||
]
|
||||
var Airport = Tuple.create("Airport", airportFields)
|
||||
|
||||
var fileName = "airports.dat" // local copy
|
||||
var lines = File.read(fileName).trimEnd().split("\n")
|
||||
var lc = lines.count
|
||||
var airports = List.filled(lc, null)
|
||||
for (i in 0...lc) {
|
||||
var fields = lines[i].split(",").map { |f| f.replace("\"", "") }.toList
|
||||
if (fields.count > 14) { // there are field(s) with embedded comma(s)
|
||||
fields = Str.splitCsv(lines[i])
|
||||
}
|
||||
var airportID = Num.fromString(fields[0])
|
||||
var name = fields[1]
|
||||
var city = fields[2]
|
||||
var country = fields[3]
|
||||
var iata = fields[4]
|
||||
var icao = fields[5]
|
||||
var latitude = Num.fromString(fields[6])
|
||||
var longitude = Num.fromString(fields[7])
|
||||
var altitude = Num.fromString(fields[8])
|
||||
var timezone = fields[9]
|
||||
var dst = fields[10]
|
||||
var tzOlson = fields[11]
|
||||
var type = fields[12]
|
||||
var source = fields[13]
|
||||
airports[i] = Airport.new(airportID, name, city, country, iata, icao, latitude, longitude,
|
||||
altitude, timezone, dst, tzOlson, type, source)
|
||||
}
|
||||
|
||||
var calculateDistance = Fn.new { |lat1, lon1, lat2, lon2, units|
|
||||
if (lat1 == lat2 && lon1 == lon2) return 0
|
||||
var radlat1 = Num.pi * lat1 / 180
|
||||
var radlat2 = Num.pi * lat2 / 180
|
||||
var theta = lon1 - lon2
|
||||
var radtheta = Num.pi * theta / 180
|
||||
var dist = radlat1.sin * radlat2.sin + radlat1.cos * radlat2.cos * radtheta.cos
|
||||
if (dist > 1) dist = 1
|
||||
dist = dist.acos * 180 / Num.pi * 60 * 1.1515576 // distance in statute miles
|
||||
if (units == "K") dist = dist * 1.609344 // distance in kilometers
|
||||
if (units == "N") dist = dist * 0.868976 // distance in nautical miles
|
||||
return dist
|
||||
}
|
||||
|
||||
var calculateBearing = Fn.new { |lat1, lon1, lat2, lon2|
|
||||
if (lat1 == lat2 && lon1 == lon2) return 0
|
||||
var radlat1 = Num.pi * lat1 / 180
|
||||
var radlat2 = Num.pi * lat2 / 180
|
||||
var raddlon = Num.pi * (lon2 - lon1) / 180
|
||||
var y = raddlon.sin * radlat2.cos
|
||||
var x = radlat1.cos * radlat2.sin - radlat1.sin * radlat2.cos * raddlon.cos
|
||||
var bear = y.atan(x) * 180 / Num.pi
|
||||
return (bear + 360) % 360
|
||||
}
|
||||
|
||||
// request from airplane at position (51.514669, 2.198581)
|
||||
var query = List.filled(airports.count, null)
|
||||
for (i in 0...airports.count) {
|
||||
var a = airports[i]
|
||||
var dist = calculateDistance.call(51.514669, 2.198581, a.latitude, a.longitude, "N")
|
||||
dist = (dist * 10).round / 10
|
||||
var bear = calculateBearing.call(51.514669, 2.198581, a.latitude, a.longitude).round
|
||||
query[i] = [a.name, a.country, a.icao, dist, bear]
|
||||
}
|
||||
query.sort { |q1, q2| q1[3] < q2[3] }
|
||||
System.print(" Name | Country | ICAO | Distance in NM | Bearing in ° ")
|
||||
System.print("-------------------------------------+----------------+------+----------------+--------------")
|
||||
var fmt = " $-36s| $-15s| $4s | $4.1f | $3d"
|
||||
for (i in 0..19) Fmt.lprint(fmt, query[i])
|
||||
System.print("(20 rows)")
|
||||
Loading…
Add table
Add a link
Reference in a new issue