Maps & globes
Latitude and longitude on a globe or a flat map, distances and circles on the Earth, GeoJSON (countries, earthquakes, routes) from a file or a URL, and a 3D point cloud to draw tens of thousands of dots at once. Angles are in degrees, distances in km.
On this page · 8 entries
Geo.ToSphere · Geo.FromSphere
Geo.ToSphere(lat, lon, radius) → PVectorGeo.FromSphere(p) → (Lat, Lon)
A place as a point on a ball centered on the origin, and back. x points east, y north (up), and longitude 0 faces -z, so a camera on the -z axis looks at Africa and Europe.
Geo.DistanceKm · Geo.Destination · Geo.Circle
Geo.DistanceKm(lat1, lon1, lat2, lon2)Geo.Destination(lat, lon, bearing, km)Geo.Circle(lat, lon, km, segments)
The great-circle distance between two places; where you end up going km along a compass bearing (0 north, 90 east); and the ring of places km away from a point — an earthquake's reach, a city's radius — ready to draw with ToSphere() or Equirectangular().
Geo.Equirectangular · Geo.FromEquirectangular
Geo.Equirectangular(lat, lon, w, h) → (X, Y)Geo.FromEquirectangular(x, y, w, h)
The simplest flat world map: longitude -180..180 left to right, latitude 90..-90 top to bottom. Most world textures (elevation, night lights, clouds) use it, so it's also how to read one of those images at a place.
Geo.FibonacciSphere
Geo.FibonacciSphere(count) → PVector[]
count points spread evenly over a unit sphere — the classic dotted globe. FromSphere() gives each one's latitude and longitude.
LoadGeoJSON · RequestGeoJSON
LoadGeoJSON(pathOrUrl)RequestGeoJSON(pathOrUrl, cacheFor) → GeoMap
A GeoJSON file (a FeatureCollection, a Feature or a bare geometry) as GeoFeatures. Each has its Points (lat, lon and the third value: altitude, or depth for earthquakes), its Rings (polygon outlines, holes marked, and lines), its properties through Text("key") and Number("key"), and Contains(lat, lon). map.FeatureAt(lat, lon) says which one a place is in — which country, with a countries file.
class View3D · View3D.Orbit · view.Project
class View3DView3D.Orbit(yaw, pitch, distance)view.Project(p, w, h) → (X, Y, Depth)
A camera for 3D on the 2D canvas: where it is, what it looks at, how wide it sees. Project() gives a point's screen position and depth (0 or less: behind the camera) — for drawing anything there, placing a label or hit-testing the mouse. x right, y up, z away from you, the same axes as Geo.ToSphere().
class PointCloud · cloud.Add · Points
class PointCloudcloud.Add(x, y, z, color, size)Points(cloud, view)
Many colored points drawn in a single batch: tens of thousands at the cost of a few hundred Circle() calls. Sorted far to near by default; set OccluderCenter/OccluderRadius to hide the ones behind a ball (the far side of a globe). Sizes are in world units unless SizeInWorld = false.
Runnable example
A complete sketch using this section. Test in Dana opens it in the IDE, or paste it into a new tab and press Run.
// A dotted globe: 20,000 points in one batch, a few cities, and the // 1,000 km around the one under the mouse. Drag to turn it. public class Globe : Sketch { readonly PointCloud cloud = new(); readonly PVector[] dots = Geo.FibonacciSphere(20000); float yaw = -0.3f, pitch = 0.4f; (string Name, float Lat, float Lon)[] cities = { ("Havana", 23.1f, -82.4f), ("Madrid", 40.4f, -3.7f), ("Lagos", 6.5f, 3.4f), ("Cairo", 30.0f, 31.2f) }; public override void Setup() { Size(700, 500); cloud.OccluderRadius = 9.9f; // hide the far side of the ball } public override void Draw() { Background(8, 12, 24); var view = View3D.Orbit(yaw, pitch, 28); cloud.Clear(); foreach (var d in dots) { var (lat, lon) = Geo.FromSphere(d); bool grid = Abs(lat % 30) < 1 || Abs(lon % 30) < 1; cloud.Add(PVector.Mult(d, 10), grid ? Color(90, 160, 220) : Color(40, 60, 100), 0.08f); } Points(cloud, view); foreach (var c in cities) { var (x, y, depth) = view.Project(Geo.ToSphere(c.Lat, c.Lon, 10), Width, Height); if (depth > 28) continue; // behind the globe bool near = Dist(MouseX, MouseY, x, y) < 12; if (near) { NoFill(); Stroke(255, 200, 80); BeginShape(); foreach (var (la, lo) in Geo.Circle(c.Lat, c.Lon, 1000)) { var p = view.Project(Geo.ToSphere(la, lo, 10.02f), Width, Height); Vertex(p.X, p.Y); } EndShape(); } NoStroke(); Fill(255, 200, 80); Circle(x, y, 8); Fill(255); Text($"{c.Name} ({Geo.DistanceKm(c.Lat, c.Lon, 23.1f, -82.4f):N0} km from Havana)", x + 8, y - 8); } } public override void MouseDragged() { yaw -= (MouseX - PMouseX) * 0.01f; pitch = Constrain(pitch + (MouseY - PMouseY) * 0.01f, -1.4f, 1.4f); } }