Surface plots visualize 3D data as a mesh surface over a 2D coordinate grid. This guide covers dimension requirements, validation behavior, and best practices.
use fortplot
type(figure_t) :: fig
! Create coordinate arrays
real(wp), dimension(5) :: x = [0.0, 1.0, 2.0, 3.0, 4.0]
real(wp), dimension(3) :: y = [0.0, 1.0, 2.0]
! Create surface data - CRITICAL: dimensions must match coordinates
real(wp), dimension(5,3) :: z ! size(z,1) must equal size(x)
! size(z,2) must equal size(y)
! Calculate surface values
do i = 1, 5
do j = 1, 3
z(i,j) = x(i) * y(j) ! Simple product surface
end do
end do
call fig%initialize(800, 600)
call fig%add_surface(x, y, z, label="Product Surface")
call fig%savefig("surface.png")
CRITICAL RULE: For add_surface(x, y, z)
:
- z
must be a 2D array with dimensions (m, n)
- x
must be a 1D array with m
elements
- y
must be a 1D array with n
elements
- Validation: size(z,1) == size(x)
AND size(z,2) == size(y)
! Square grid
real(wp), dimension(10) :: x, y
real(wp), dimension(10,10) :: z ! ✓ Correct
! Rectangular grid
real(wp), dimension(20) :: x_coords
real(wp), dimension(15) :: y_coords
real(wp), dimension(20,15) :: z_surface ! ✓ Correct
! Single point
real(wp), dimension(1) :: x_single = [0.0]
real(wp), dimension(1) :: y_single = [0.0]
real(wp), dimension(1,1) :: z_single = reshape([1.0], [1,1]) ! ✓ Correct
! Wrong z dimensions
real(wp), dimension(5) :: x
real(wp), dimension(3) :: y
real(wp), dimension(3,5) :: z_wrong ! ✗ Wrong: should be (5,3), not (3,5)
! Mismatched x dimension
real(wp), dimension(4) :: x_wrong ! ✗ Should be size 5
real(wp), dimension(3) :: y
real(wp), dimension(5,3) :: z
! Mismatched y dimension
real(wp), dimension(5) :: x
real(wp), dimension(4) :: y_wrong ! ✗ Should be size 3
real(wp), dimension(5,3) :: z
When dimension validation fails, add_surface
will:
1. Display clear error message showing expected vs actual dimensions
2. Return without adding the plot to prevent runtime errors
3. Continue execution (non-fatal error)
Error: Surface z dimensions (3,5) must match x size (5) and y size (3)
Error: Surface z dimensions (4,3) must match x size (5) and y size (3)
! Empty arrays pass validation but create empty plot
real(wp), dimension(0) :: x_empty, y_empty
real(wp), dimension(0,0) :: z_empty
call fig%add_surface(x_empty, y_empty, z_empty) ! ✓ Valid but empty
! Single point surfaces are valid
real(wp), dimension(1) :: x = [1.0]
real(wp), dimension(1) :: y = [2.0]
real(wp), dimension(1,1) :: z = reshape([3.0], [1,1])
call fig%add_surface(x, y, z) ! ✓ Creates single-point surface
! Large grids work with correct dimensions
real(wp), dimension(1000) :: x_large
real(wp), dimension(500) :: y_large
real(wp), dimension(1000,500) :: z_large ! ✓ Correct dimensions
! Good: Clear coordinate initialization
do i = 1, size(x)
x(i) = x_min + (i-1) * (x_max - x_min) / (size(x) - 1)
end do
! Concise for small arrays
real(wp), dimension(3) :: x = [0.0, 0.5, 1.0]
real(wp), dimension(4) :: y = [0.0, 0.33, 0.67, 1.0]
! Document critical dimension relationships
real(wp), dimension(nx) :: x_coords ! nx points
real(wp), dimension(ny) :: y_coords ! ny points
real(wp), dimension(nx, ny) :: z_data ! surface data: z(i,j) = f(x_coords(i), y_coords(j))
! Optional: validate dimensions in your code
if (size(z,1) /= size(x) .or. size(z,2) /= size(y)) then
error stop "Dimension mismatch in surface data"
end if
call fig%add_surface(x, y, z)
! WRONG - common mistake
real(wp), dimension(nx, ny) :: z_wrong
z_wrong = transpose(correct_z_data) ! Don't do this
! CORRECT - match coordinate order
real(wp), dimension(nx, ny) :: z_correct ! z(i,j) corresponds to x(i), y(j)
! WRONG - size mismatch
x = linspace(0.0, 1.0, 10) ! 10 points
y = linspace(0.0, 1.0, 11) ! 11 points
allocate(z(10, 10)) ! Wrong size for y
! CORRECT - consistent sizes
nx = 10; ny = 11
allocate(x(nx), y(ny), z(nx, ny))
! Surface plotting uses grid interpretation:
! z(i,j) = value at coordinate (x(i), y(j))
! NOT matrix multiplication or linear algebra interpretation
! Generate mathematical surface
do i = 1, nx
do j = 1, ny
r = sqrt(x(i)**2 + y(j)**2)
z(i,j) = sin(r) * exp(-0.1*r) ! Ripple function
end do
end do
call fig%add_surface(x, y, z1, label="Surface 1")
call fig%add_surface(x, y, z2, label="Surface 2") ! Same grid, different data
! Mix surface with contour plots
call fig%add_surface(x, y, z, label="3D Surface")
call fig%contour(x, y, z, levels=10) ! Same data, different visualization
This guide ensures users understand surface plot dimension requirements and can avoid validation errors while creating effective 3D visualizations.