DATA SCIENCE

Airport Connections


Posted on 19 June 2022, by Kevin Mora



3D visualization of airport connections around the world.

Let's start with our pseudoalgorithm:

– Import data (instances of airports and their connections).
– Convert from Lat/Lon to Cartesian (X/Y/Z).
– Connect the IDs and display the flight routes.
– Project the routes on a sphere.
– Create a curvature for the paths between nodes.

The first problem we encountered while coding this in Houdini was the cartesian system of coordinates – as expected, the position was stored as latitute and longitute, but because the built-in functions that allow us to translate these two parameters did not yield the correct results with our IDs, we decided to create a program to translate these two parameters into a cartesian system of coordinates, and a pointwrangle node seemed like the best approach.

vector spherToCart(float lat, lon, rad){
	return rad * set(-cos(lat) * cos(lon), 
	    sin(lat), cos(lat) * sin(lon));
}

v@P = spherToCart(
	radians(@lat),
	radians(@lon),
	1.0
);

v@N = normalize(@P);

The next step was to build the flight routes, so a second pointwrangle node must be added, and connected to the route data (.txt file). The output from pointwrangle-1 node should point to the second input slot of pointwrangle-2 node. We essentially want to search for airport IDs and trace the path between two airport instances, at which point we will notice sets of three or more red edges – we don't need this data and must get rid of it.

int src = findattribval(1, "point", "id", i@src);
int dst = findattribval(1, "point", "id", i@dst);

if (src >= 0 && dst >= 0) {
  int newprim = addprim(0, "polyline");
	setprimgroup (0, "new", newprim, 1);
	vector v1 = point (1, "p", src);
	vector v2 = point (1, "p", dst);
	int p1 = addpoint (0, v1);
	int p2 = addpoint (0, v2);
	float distance = distance (v1, v2);
	setpointattrib(0, "dist", p1, distance);
	setpointattrib(0, "dist", p2, distance);
	addvertex(0, newprim, p1);
	addvertex(0, newprim, p2);
}

In order to fix these red lines, we must connect the output from the last node (i.e., pointwrangle-2) to a new blast node of primitive group type. Finally, all our connections are being represented by a straight line, and it is thus hard to distinguish any path. To fix this last problem, we shall make sure to create Curve-U attribute and have it enabled in the resample node. To create a curvature between the path from the airport source and the airport destination, we will use the following expression:

float scale = chf("Lift_Scale");
float lift = chramp("Lift_Amount", @curveu);
float width = chramp("Width", @curveu);

vector liftpos = v@P +(v@N * lift * scale * @dist);

v@P = liftpos;
f@width = width * .0005;

This was a simple way to illustrate this idea and I think it's an interesting visualization, thought it certainly isn't an effective one and has no meaningful value. As always, I'd strongly suggest you take a look at my code here, and also the data, which was taken from this site.