Ever since the introduction of electronic devices with touch controls, interactive 3D graphics objects have become increasingly popular in multimedia electronic books (ebooks). The Open3D and the Rasterio packages for Python provide the necessary tools for creating and exporting 3D graphics objects for inclusion in documents such as multimedia ebooks, interactive websites, and presentations.
I worked on this for two full days, desperately missing the excellent support MathWorks for Python. The problem was that the 3D model needed not only nodes and edges, but also surfaces colored in a way typical for digital terrain models. My queries to ChatGPT also consistently provided solutions that did not work. Anyway, I managed to get it running after two days, here it is!
The Polygon File Format (PLY) files are text or binary files with the file extension .ply. Suche a file contains vertices, edges, and faces for 3D polygons. The PLY files can be viewed using a browser plugin (many different types of which are available online) or using 3D software, such as the open-source MeshLab software
or the free Blender software available at
These tools (as well as others) can be used to convert the PLY format into other 3D graphics object file formats, such as the Universal 3D (U3D), the Virtual Reality Modeling Language (VRML), the Collada digital asset exchange (DAE) or Filmbox (FBX) formats. As an example, the U3D format is the format required to place a 3D graphics object onto a PDF page with Adobe Acrobat.
The digital terrain models such as the one in file s01_e036_1arc_v3.tif are great examples of such interactive 3D objects. We first import the required packages using
import numpy as np import matplotlib.pyplot as plt import open3d as o3d import open3d.utility as o3du import rasterio as rasterio import rasterio.plot
We use rasterio.open to read the GeoTIFF file using
ginfo = rasterio.open('s01_e036_1arc_v3.tif') SRTM = ginfo.read() SRTM = np.squeeze(SRTM)
which is a generic tool for reading geospatial raster data files. The output arguments are the digital elevation data SRTM. The SRTM dataset actually has a resolution of 1/3600 degrees, but we first reduce it to 1/360 degrees so that our computers can handle a smooth 3D display. We define a coordinate grid lon and lat to match SRTM using
lon = np.linspace(36,37,361) lat = np.linspace(-1,0,361) SRTM = SRTM[::10,::10] SRTM = SRTM/1000 nrows,ncols = SRTM.shape
We then create the vertices of the 3D model using
vertices = [] for i in range(nrows): for j in range(ncols): vertices.append([lon[i],lat[j],-SRTM[i,j]]) vertices = np.array(vertices)
We then define scaling factors for each dimension using
vertices = vertices*np.array([1.0,1.0,0.2])
We then create faces for a regular grid structure and connect vertices within a grid to form triangles. Faces are defined based on vertex indices.
faces = [] for i in range(nrows-1): for j in range(ncols-1): v0 = i*ncols+j v1 = v0+1 v2 = v0+ncols v3 = v2+1
We then define two triangles per grid square (quad)
faces.append([v0,v1,v2]) faces.append([v1,v3,v2]) faces = np.array(faces)
We then create colors from SRTM using the ‘terrain’ colormap.
SRTM = (SRTM-SRTM.min()) \ /(SRTM.max()-SRTM.min()) colormap = plt.get_cmap('terrain') colors = colormap(SRTM) colors = colors.reshape(-1,4) colors = colors[:,:3]
We then create the mesh object using
mesh = o3d.geometry.TriangleMesh() mesh.vertices = o3du.Vector3dVector(vertices) mesh.triangles = o3du.Vector3iVector(faces) mesh.vertex_colors = o3du.Vector3dVector(colors)
We can rotate the mesh object using
R = mesh.get_rotation_matrix_from_xyz((1.5,0,1.5)) mesh.rotate(R,center=(0,0,0))
Finally, we export the mesh to a PLY file using
o3d.io.write_triangle_mesh('srtm_1.ply',mesh)
Importing the resulting PLY file into a PLY client such as MeshLab or Blender reveals that the terrain model does indeed has colors, as defined by demcmap. We can use the file in the PLY format to create an interactive document.
References
Download all files to perform the experiment.
References
Trauth, M.H. (2024) Python Recipes for Earth Sciences – Second Edition. Springer International Publishing, 491 p., https://doi.org/10.1007/978-3-031-56906-7