This work describes Navigare, an application that employs Computer Graphics to present Geomatics concepts to the general public. Its interface is composed of a 3D globe and a 2D map, both of which are synchronized to display the same location. A set of predefined historical sites is presented, and users can select two locations to trace a loxodrome or orthodrome path between them or calculate their distances. The application also provides information about each historical site, including its name, country, longitude, latitude, and a brief description of its significance. A Timeline of historical figures is also available, allowing users to explore the lives and contributions of notable individuals throughout history.
Navigare is open source and offers the following functionalities:- Equirectangular and Mercator projection viewer using lighting combined with texture mapping written in Vanilla JavaScript and WebGL.
- Auto Rotation: intrinsic (around local axes) or extrinsic (around global axes); around X-axis, Y-axis (parallel), Z-axis or q-meridian.
- Arcball Paradigm: natural rotation using the mouse or touch and necessary to display the historical tooltips (globe should stay still).
- Loxodrome and orthodrome tracer: Draw paths on the map and globe when the user selects two points (by clicking either on the map or globe) to get their GCS coordinates (longitude and latitude). The bearing angle (azimuth) is measured from the previous to the current location. Loxodrome checkbox must be checked in the interface.
- Around the World in 500 Historical Figures: presents a summary of each location visited by using the arrow keys or clicking on the bottom right or left of the globe canvas (to advance or recede).
- Dial Earth: type a pair of latitude and longitude coordinates and press enter to go to the selected destination on the map and globe; type a string with more than three characters to get a list of matched sites. Additionally, press the [≈ Site] button to go to the closest historical site.
- Mobile Friendly: responsive interface design for running on phones and tablets.
- Set sail Navigare Application!
- The paper: "Navigare necesse; vivere non est necesse" is available for download, single or double column.
Introduction - for educational purposes only
This is an application called Navigare that employs Computer Graphics to present Geomatics concepts to the general public. As a matter of fact, Navigare implementation became overly complicated, but it is similar to Lighting2, except we define a 3x3 matrix for material properties and a 3x3 matrix for light properties that are passed to the fragment shader as uniforms. Anyone can edit the light and material matrices in the global variables to experiment or startForReal to choose a model and select face or vertex normals. Three.js only uses face normals for polyhedra, indeed.
Texture coordinates can be set in each model or sampled at each pixel in the fragment shader. We can also approximate a sphere by subdividing a convex regular polyhedron and solving Mipmapping artifact issues by using Tarini's method, in this case. These artifacts show up due to the discontinuity in the seam when crossing the line with 0 radians on one side and 2π on the other. Some triangles may have edges that cross this line, causing the wrong mipmap level 0 to be chosen.
Before satellites and the GPS
During the Age of Discoveries (1418-1620), Portuguese cosmographer Pedro Nunes was the first mathematician to propose in 1537 the notion of a loxodrome, or course line routes that intersect all meridians with a constant angle defined by a unique compass direction, thus determining a spiral curve headed towards the poles. However, he did not address the problem of determining the azimuth angle for going from a source location to a destination using a map. The Flemish cartographer Gerardus Mercator has given the answer thirty two years later in 1569.
To locate a ship at sea it is necessary to know its latitude and longitude with a good degree of accuracy. Two tools were used to determine the latitude: the astrolabe and the sextant. The astrolabe measured the altitude of the sun at noon or the altitude of a star at night. The sextant was used to measure the angle between a celestial object and the horizon. Both tools allowed sailors to determine their latitude with reasonable accuracy. However, determining longitude remained a challenge until the development of accurate marine chronometers in the 18th century.
The navigation sextant invented in 1731 independently by John Hadley and Thomas Godfrey was used to measure the angle between a celestial object and the horizon. It was a crucial tool for determining latitude at sea, allowing sailors to calculate their position north or south of the equator. By measuring the angle of the sun at noon or the angle of a star at night, navigators could determine their latitude with reasonable accuracy.The first marine timekeeper to address the longitude problem at sea was John Harrison's H1, completed in 1735. It used a pair of linked balance bars and temperature-compensating parts to keep accurate time on a rocking ship. It allowed sailors to compare local time with home port time (Greenwich Mean Time) to find exact east-west positions.
Prior to the invention of the marine chronometer, sailors relied on dead reckoning and celestial navigation to estimate their longitude. As a consequence, disasters like the Scilly Naval Disaster and diseases like scurvy were common among sailors during long voyages.
Computer Graphics for Tracing Courses
To display a globe on the screen, its initial position should take into account the obliquity of the earth (23.44°) and illumination parameters, such as the Phong highlight position. In Navigare, the highlight projects onto the equator line if the user has not interacted using the Arcball. If PHP is running on the HTTP server, then any image file in directory textures will be available in the menu. Otherwise, sorry GitHub pages, only the images listed in the HTML file.
Chart maps are images laid onto a sphere as textures and should have an aspect ratio of 2:1 for equirectangular projections or 1:1 (squared) for Mercator projections. Finding high-resolution, good-quality, and free cartographic maps is really difficult. As long as a parametrization from ℝ² to ℝ³ is known for a surface, a texture can be georeferenced. This is the case of the quadrics, and Navigare also supports cones and cylinders.
Maps are transformations from 3D space to 2D space, and they can preserve areas (equal-area maps) or angles (conformal maps). In terms of projection invariance, loxodromes appear as straight lines on conformal map projections. Therefore, the success of the Mercator projection lies in its ability to preserve angles, making it ideal for navigation (directions on the map match the directions on the compass). However, it distorts areas, especially near the poles, where landmasses appear much larger than they are in reality. Meridian and parallel scales are the same, meaning that distances along a parallel or meridian (in fact, in all directions) are equally stretched by a factor of sec(φ) = 1/cos(φ), where φ ∈ [-85.051129°, 85.051129°] is its latitude.
At latitude φ, horizontal distances on the chart are magnified by sec(φ) to make the meridians parallel.
So locally, the vertical distances should be magnified by sec(φ) also to make the projection angle-preserving.- φ = latitude
- θ = longitude
- R = radius of the sphere
- C♁ = circumference of the earth
- δθ = δx
- R cos(φ) / R = δx / d ⇒ d = δx / cos(φ) = δx sec(φ) -------- on the Mercator chart --------
- (x,y) = M(R,θ,φ)
- x = R θ, -π ≤ θ ≤ π
- y = R ∫ φ 0 sec(φ) dφ = R ln [tan (π/4 + φ/2)], -π/2 ≤ φ ≤ π/2
- For a square Mercator chart, -π ≤ y ≤ π ⇒ φ ∈ [-85.051129°, 85.051129°]
- φ = 2 tan-1 (ey) - π/2, -π ≤ y ≤ π → -85.051129° ≤ φ ≤ 85.051129° -------- Meridional Parts --------
- Meridional parts quantify vertical chart lengths by scaling them relative to horizontal minute units at the equator
- 1 Nautical Mile = one minute of longitude at the equator
- 1 nm = 2 π earthRadius Km / 21600 = 40030 km / 360 / 60 = 1.8532407 km (1,852 m or 6,076.12 ft )
- C♁ = 21600 nm (C♁/2 = 10800 nm)
- 1 radian on earth ≈ (10800/π) nm
- MP = (10800/π) * ln [tan (π/4 + φ/2)] minutes of arc length (not using the spheroid shape of the earth)
- MP = toDegrees(toMercator(toRadian(φ))) * 60
- The knot is a unit of speed equal to one nautical mile per hour, exactly 1.852 km/h (1.15078 mph)
- Captains in the 1700s tossed ropes overboard with knots spaced out at 50 ft and used a sand glass that measured half of a minute to approximate the speed of a ship in nautical miles per hour
- 50 ft / 0.5 min = 100 ft / 1 min × 1 nm / 6076 ft × 60 min / h = 0.9875 ≈ 1 nm / h -------- loxodromes --------
- φ = latitude
- θ = longitude
- α = bearing angle (measured clockwise in degrees from north)
- tan(90° - α) = cot(α) = 1/tan(α) = dx/dy
- dx = R cos(φ) dθ
- dy = R dφ
- tan(α) = dx/dy = cos(φ) dθ/dφ
- dθ/dφ = tan(α) sec(φ)
- ∫sec(φ) dφ = 1/tan(α) ∫dθ ⇒ tan(α) ∫sec(φ) dφ = (θ - θ0)
- (θ - θ0) = ∫ φ φ0 tan(α) sec(φ) dφ
- θ(φ) = θ0 + tan(α) ln [tan (π/4 + φ/2) / tan (π/4 + φ0/2)] = θ0 + tan(α) * diffMercator(φ, φ0)
- θ(φ) = longitudeOnLoxodrome(φ0, φ, α)
The Web Mercator projection, on the other hand, is a variant of the Mercator projection, which is widely used in web mapping applications. It was designed to work well with the Web Mercator coordinate system, which is based on the WGS 84 datum. The projection is neither strictly ellipsoidal nor strictly spherical, and it uses spherical development of ellipsoidal coordinates. The underlying geographic coordinates are defined using the WGS 84 ellipsoidal model of the Earth's surface but are projected as if defined on a sphere. Misinterpreting Web Mercator for the standard Mercator during coordinate conversion can lead to deviations as much as 43 km on the map (21 km on the ground):
- const Tromsø = gpsCoordinates["Tromsø"]; // Norway
- const { latitude: lat, longitude: lon } = Tromsø;
- const rlat = toRadian(lat);
- const psi1 = toMercator(rlat, true);
- const psi2 = toMercator(rlat);
- const N_ellipsoid = earthMajorAxis * psi1;
- const N_sphere = earthMajorAxis * psi2;
- const ndiff = Math.abs(N_ellipsoid - N_sphere);
- console.log(`Northing difference (${lat}°): ${ndiff.toFixed(2)} km`);
- // Northing difference (69.6517°): 40.11 km
- const latGlobe = toDegrees(toSpherical(psi1));
- const locGlobe = { latitude: latGlobe, longitude: lon };
- const gdiff = haversine(loc, locGlobe).km;
- console.log(`Ground difference (${lat}°): ${gdiff.toFixed(2)} km`);
- // Ground difference (69.6517°): 13.97 km
It is impressive how Gerardus Mercator was able to create such a projection in a time (1569) when there was no calculus (integrals, derivatives — Leibniz in 1674 and Isaac Newton in 1666) or even logarithm tables (John Napier, 1614). This is an example of the need for calculus to solve a navigation technological issue that had an enormous economic impact.
The first application of calculus to solve this map's meridional spacing was by English mathematician Edward Wright in 1599. Wright's "Errors in Navigation" geometric proof conceptually utilized the integral of the secant function. At the time, this closed-form solution was half-century away from being discovered. The actual calculus formulation and logarithmic proofs for Mercator's scaling only emerged in the mid-to-late 1600s, primarily through the works of James Gregory and Isaac Barrow, who provided in 1670 the first intelligible, closed-form mathematical proof for the integral of the secant function, resolving the long-standing problem of the spacing of latitudes for the Mercator map projection.
Mercator texture coordinates can be set in a model directly or in the shader that samples texture coordinates for each pixel. Since a unit sphere fits in the WebGL NDC space, it is possible to go into each fragment from:- cartesian → spherical (equirectangular) → Mercator
- (x, y, z) → (long, lat) → (x, y)
- sample texture at (x, y)
Its meridian scale is 1 meaning that the distance along lines of longitude remains the same across the map, while its parallel scale varies with latitude, which means that the distance along lines of latitude is stretched by a factor of sec(φ). Ptolemy claims that Marinus of Tyre invented the projection in the first century (AD 100). The projection is neither equal area nor conformal. In particular, the plate carrée (flat square) has become a standard for global raster datasets. Loxodromes are no longer straight lines on the equirectangular projection, but possess a sigmoid shape, rendering them unusable for navigation purposes.
in the equirectangular projection
All projection types involve some kind of distortion, which is not a problem per se. The real problem is being tricked by the shape of the chart. The Mercator projection, for instance, stretches land sizes near the poles while keeping compass directions. Country size changes is a problem for school classrooms if students do not understand what causes it. To circumvent the map distortion confusion, the flat chart should always be paired with a synced 3D globe.
The interface we propose to tackle this problem presents a 3D view of the globe all the time so the real sizes are easily seen. Every time a user clicks on the chart, the globe rotates to make the corresponding point on the globe face the viewer. This is accomplished by keeping a forward vector from the origin to the center of the projected sphere, which is the position of the Phong highlight. The position vector from the origin to the clicked point is then just rotated to become the new forward vector. However, the north (Y-axis) also rotates, and the globe can be positioned in a non-conventional way, for example, "upside-down." A second rotation around the new forward vector can reset the north vector appropriately. It is amazing what we can do with a few cross and dot product operations.
As a final remark, I thought it would be easier to deal with map images as textures, but I was mistaken. I tried, as long as I could, not to rewrite third-party code. Unfortunately, this was impossible. The main issue was that the prime meridian is at the center of a map image and not at its border, which corresponds to its antimeridian.
Initially, I used the basic-object-models-IFS package, but the models had their z-axis pointing up as the zenith, and I wanted the y-axis to be the north pole (up). Therefore, I switched to Three.js, and almost everything worked just fine. Nonetheless, a sphere created by subdividing a polyhedron had its texture coordinates rotated by 180° and a cylinder or cone by 90°. In fact, there is a poorly documented parameter, thetaStart, that does fix just that.
Nevertheless, I decided to adapt the hws software to my needs by introducing a global hook, yNorth, and rotating the models accordingly. Furthermore, I added the parameter stacks to uvCone and uvCylinder, to improve interpolation and fixed the number of triangles generated in uvCone. This way, the set of models in hws and three.js became quite similar, although I kept the "zig-zag" mesh for cones and cylinders in hws (I have no idea whether it provides any practical advantage). A user can switch between hws and three.js models by pressing a single key (Alt, ❖ or ⌘) in the interface.
There is a lot of redundancy in the form of vertex duplication in all of these models that precludes mipmapping artifacts. The theoretical number of vertices, 𝑣, for a manifold model and the actual number of vertices (🔴) are displayed in the interface. The number of edges, e, is simply three times the number of triangles, t, divided by two.
For any triangulation of a compact surface, the following holds (page 31, page 34):- 2e = 3t,
- e = 3(𝑣 - χ), χ(S²)=2,
- 𝑣 ≥ 1/2 (7 + √(49 - 24χ)).
As a proof of concept, I implemented a sphere model without any vertex duplication. Besides being much harder to code, its last slice (e.g., slices = 48) goes from 6.152285613280011 (2π/48 * 47) to 0.0 and not 2π (if there was an extra duplicate vertex), which generates texture coordinates going from 0.9791666666666666 (47/48) to 0.0 and not 1.0. Although this discontinuity is what causes the mipmapping artifacts, it has nothing to do with the topology of the model but how mipmapping is implemented on the GPU. However, since an entire line is mapped onto the vextex at the north or south pole, and a vertex can have only one pair of texture coordinates (u,v), no matter what value we use for the "u" coordinate (e.g., 0 or 0.5), the interpolation will produce an awkward swirl effect at the poles.
Of course, these are just polygon meshes suitable for visualization and not valid topological B-rep models that enforce the Euler characteristic by using the winged-edge, quad-edge, or radial-edge data structures required in solid modeling.The Navigare application: Around The World in 500 historical figures.
When a child has to study history, he/she is generally not able to visualize the actual location of an event. For instance, where were the locations of Thrace, Anatolia, Troy, the Parthian Empire, the Inca Empire, and Rapa Nui?
Therefore, it is important to present in a graphical way, the connection between historical events in time and space, and Navigare is an adequate application for accomplishing this goal. However, how Navigare is implemented is not the main point. For not using any npm packages or bundlers, Navigare sticks only with HTML, CSS, JavaScript, and WebGL, plus some packages, including three.js.
The concepts applied in the implementation rely on Linear Algebra for spatial transformations, Computer Graphics for rendering theory and pipelines, and Web Development frameworks to display and run the interactive visual content in a browser. However, Computer Graphics has become a commodity, much like database management; everyone utilizes it, yet very few people are interested in understanding the underlying mechanics. This trend poses a challenge for educators, as it becomes increasingly important to inspire curiosity and a deeper appreciation for the artistic and technical aspects of graphics programming. By focusing on foundational principles, we encourage students to explore beyond the surface and engage with the creative possibilities that computer graphics offers.
Of course, everything could have been implemented using a package such as three.js only, although OrbitControls does not provide the flexibility needed to build the interface. Nonetheless, exploring alternative libraries and frameworks could provide additional tools and features that enhance the user experience and streamline development. Ultimately, the goal is to create an environment where students feel empowered to experiment and innovate, pushing the boundaries of what they can achieve in graphics programming.
Navigare used no AI and each event was researched one by one about its history for dating the occurrences associated with a site. All sites are hold in a JSON file called “locations.json” and it is possible to cycle through the historical figures by country when choosing a two letter ISO country code in the interface. For example, selecting "BR" will display all the figures from Brazil, while "CA" will show those from Canada and "US" from the United States of America. The sorting of dates uses the day, month and year of the last date of the last entry in the remarkable list field. E.g., "Battle of Britain, 10 July 1940 - 31 October 1940" is sorted using "10 July 1940".
"Moffat": {
"country": "⚔ Scotland (United Kingdom)",
"remarkable": [
"Hugh Dowding (Air Chief Marshal), 1882-1970",
"Battle of Britain, 10 July 1940 - 31 October 1940"
],
"latitude": 55.333814,
"longitude": -3.444884
},
"San Francisco": {
"country": "⚔ California (United States)",
"remarkable": [
"Golden Gate Bridge (1.6 km), 5 January 1933 - 27 May 1937",
"William Halsey Jr. (Fleet Admiral), 1882-1959",
"Doolittle Raid departure, 2 April 1942"
],
"latitude": 37.77493,
"longitude": -122.41942
},
Dates should be preceded by a comma in the remarkable list field to be considered for sorting (no error checking is done). Examples:
, 324 (1 0 324) , 657 BC (1 0 -657) , 330-1453 (1 0 330) , 10 July 1940 - 31 October 1940 (10 6 1940) , 2 April 1942 (2 3 1942)Note:
- ☠ means Caribbean,
- 🐇 means Bad Bunny,
- ⚔ (WW) means World War II,
- ✝ means Crusade,
- ☢ means Radiation,
- 🧪 means Laboratory,
- 🏆 means Nobel Prize,
- 🔬 means Science,
- ⛵ means Age of Discovery,
- ⚓ means Columbus's voyages,
- 🎶 means Music,
- 🔎 means Search,
- BC means Before Christ and
- AD means Anno Domini.
Picking Locations
Navigare displays the location of a city as the intersection of its line of latitude (parallel) and line of longitude (meridian).When a user picks a point in the chart map, using the mouse or any pointer device, Navigare displays its location on the chart map and on the globe by executing the following steps:
- Convert the screen coordinates of the mouse pointer into texture coordinates (u, v), then into GCS coordinates (longitude, latitude) using the currentLocation, and optionally transforming them to Mercator coordinates.
- Draw meridian and parallel lines: use the lineTo() from HTML5 by placing an element <canvas> on top of the element <img>.
- This is simple to accomplish by nesting the <canvas> element with position absolute in a <div> element with position relative and the same size as the image element.
- The <canvas> element should have a higher z-index than the image element and ignore pointer events.
- Define a pointerdown event handler to set the currentLocation as the gpsCoordinates "Unknown" and draw the lines by calling drawLinesOnImage in draw.
- Shoot the ray from the mouse position and intersect it against the surface of an implicit sphere by solving a second-degree equation.
- Alternatively, intersect the ray against each face of the polygonal surface by testing if the ray intersects the plane of a face and then checking if the intersection point is inside the corresponding triangle.
- Select a position on the globe by clicking or pointing directly in the WebGL canvas.
- Display the GCS coordinates of the pointer: If the globe is spinning, keep track of the cursor position and then shoot a ray through this position to find its intersection on the globe.
- Use the Phong highlight position on the globe as a cursor for touch devices, since they do not have a cursor position: Get its initial position in world coordinates (0, 0, 1)—or in GCS coordinates (-90°, 0°)—and transforms it into screen coordinates.
- Exhibit the current location name in 3D: Transform its GCS coordinates into screen coordinates (pixels) and use the position HTML properties "top" and "left" of the WebGL <canvas> element (plus a tooltip element) to display the text.
Homework
- To determine a ship's latitude at sea without a GPS, it is necessary to have a sextant. What is necessary to get the ship's longitude? What calculation should be done (it is simpler than you might think)?
- What does the obliquity of the earth have to do with the glacial periods?
- The minimum distance between two points on a sphere is along the minor arc of a great circle or formally a geodesics. However, although this is the route airplanes follow for saving fuel, sailboats and ships usually follow a rhumb line (loxodrome). Why is that?
- Implement cylindrical coordinates, line-cylinder intersection and line-plane intersection to project maps and locations onto cylinders appropriately.
- Implement conical coordinates, line-cone intersection and line-plane intersection to project maps and locations onto cones appropriately.
Conclusions
Since elementary school, people learn Geography through planar maps. Nonetheless, the earth is an oblate spheroid, and shortest distances are geodesics and not straight lines on a piece of paper. Therefore, it is important to realize the difference between distance measurements on the plane and on a sphere.The interface we propose presents a three-dimensional view of the earth to enhance the perception of the spherical shape of our planet. Furthermore, we discussed the effect of projections in shape distortion and the need of mathematical integration for the development of the Mercator projection and its importance for navigation in the past. The ability of associating historical events with their geographical locations sorted by dates is a powerful mechanism for learning and understanding history in a more engaging and interactive way.
The code is open source and hopefully it will be useful for teachers and students alike to enhance their map literacy. Navigare was implemented in a peculiar way, which took advantage of JavaScript's dynamic typing and the flexibility of WebGL to create an interactive and engaging learning experience. The interface runs on any modern web browser, and it is responsive to different screen sizes and resolutions thus allowing users to access the application from various devices, including tablets and smartphones. In certain cases this may be the only way to access the application, and it is important to make it as accessible as possible.
And thtat's all I had to say about that.- Since:
- 30/01/2016
- Copyright:
- © 2024-2026 Paulo R Cavalcanti.
- License:
- Licensed under the LGPLv3.
- Source:
- See:
-
- link - Texture coordinates sampled at each pixel in the fragment shader
- link2 - Texture coordinates sampled at each vertex in the vertex shader
- css - CSS file for the interface
- source
- textures
- Mapping the Sphere
- A Fresh Look at the Method of Archimedes
- From Archimedes to statistics: the area of the sphere
- Archimedes and the area of sphere
- On some information geometric structures concerning Mercator projections
- The Mathematics of Maps
- Map projections
- "Distortion", the incorrect and correct usage of the word
- The Mercator Projections
- The Mercator Projection from a Historic Point of View
- Thomas Harriot and the Mercator Map
- How Big is a Degree?
- The Mercator Saga (part 1)
- Loxodromic navigation
- Globe 3D
- Earth's circumference
- The True Size of ...
- The True Size of Countries
- leaflet-truesize plugin
- Navigational Sextant
- CasualNavigationAcademy
- Why Ships and Planes Use 'Knots' Instead of Miles per Hour
- American Practical Navigator
North Pole (y-axis)
Equirectangular projection
Mercator Projection
(not a cylindrical radial projection)
Wrong (left) x Correct (right)
Real Country Sizes Shown on Mercator Projection
Rhumb Line (magenta) and Great Circle (cyan)
Amsterdan - Hong Kong (9281 km, 109.55°)
Spherical (Equirectangular) Projection
Subdivision Sphere Seam - Mipmapping Artifact
Sphere No Duplication Seam - north and south pole swirling

Texture Sampled in Fragment Shader









