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.