Create a surface plot of xyz altitude data in Python

sfluck picture sfluck · Aug 17, 2018 · Viewed 13.8k times · Source

I am trying to create a surface plot of a mountain in python, of which I have some xyz data. The end result should look something like that. The file is formatted as follows:

616000.0 90500.0 3096.712
616000.0 90525.0 3123.415
616000.0 90550.0 3158.902
616000.0 90575.0 3182.109
616000.0 90600.0 3192.991
616025.0 90500.0 3082.684
616025.0 90525.0 3116.597
616025.0 90550.0 3149.812
616025.0 90575.0 3177.607
616025.0 90600.0 3191.986

and so on. The first column represents the x coordinate, the middle one the y coordinate, and z the altitude that belongs to the xy coordinate.

I read in the data using pandas and then convert the columns to individual x, y, z NumPy 1D arrays. So far I managed to create a simple 3D scatter plot with a for loop iterating over each index of each 1D array, but that takes ages and makes the appearance of being quite inefficient.

I've tried to work with scipy.interpolate.griddata and plt.plot_surface, but for z data I always get the error that data should be in a 2D array, but I cannot figure out why or how it should be 2D data. I assume that given I have xyz data, there should be a way to simply create a surface from it. Is there a simple way?

Answer

programmer picture programmer · Mar 8, 2019

Using functions plot_trisurf and scatter from matplotlib, given X Y Z data can be plotted similar to given plot.

import sys
import csv
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d

# Read CSV
csvFileName = sys.argv[1]
csvData = []
with open(csvFileName, 'r') as csvFile:
    csvReader = csv.reader(csvFile, delimiter=' ')
    for csvRow in csvReader:
        csvData.append(csvRow)

# Get X, Y, Z
csvData = np.array(csvData)
csvData = csvData.astype(np.float)
X, Y, Z = csvData[:,0], csvData[:,1], csvData[:,2]

# Plot X,Y,Z
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(X, Y, Z, color='white', edgecolors='grey', alpha=0.5)
ax.scatter(X, Y, Z, c='red')
plt.show()

Here,

  • file containing X Y Z data provided as argument to above script
  • in plot_trisurf, parameters used to control appearance. e.g. alpha used to control opacity of surface
  • in scatter, c parameter specifies color of points plotted on surface

For given data file, following plot is generated

enter image description here

Note: Here, the terrain is formed by triangulation of given set of 3D points. Hence, contours along surface in plot are not aligned to X- and Y- axes