I thought you could just find the location of the maximum and add it using the points()
function, but that doesn't work because the axis coordinates displayed in the plot are not the same as the internal coordinates the plot uses to place the plot elements (see here for details).
Instead, you can use the plot.axes
argument of filled.contour
to get the maximum in the right place, as explained here. We also need to use the axis
function to draw the axis ticks and labels, because the plot.axes
argument overrides the default axes.
# Get coordinates of maximum
max.point = (which(volcano==max(volcano), arr.ind=TRUE) - 1)/(dim(volcano) - 1)
# Use plot.axes argument to plot maximum point
filled.contour(volcano, color.palette = terrain.colors, asp = 0.5,
plot.axes={
points(max.point, col="red", pch=16)
axis(side=1)
axis(side=2)
}
)

For reference, here's what happens when you try adding the point after the plot is created:
filled.contour(volcano, color.palette = terrain.colors, asp = 0.5)
points(max.point, col="red", pch=17)

Here's a ggplot2 version:
library(tidyverse)
cols = terrain.colors(3)
as.data.frame(t(volcano)) %>%
rownames_to_column(var="row") %>%
gather(col, value, -row) %>%
mutate(col=(as.numeric(gsub("V","",col)) - 1)/(nrow(volcano) - 1),
row=(as.numeric(row) - 1)/(ncol(volcano) - 1)) %>%
ggplot(aes(col, row, z=value)) +
geom_raster(aes(fill=value)) +
geom_contour(colour="grey50", size=0.2) +
geom_point(data=. %>% filter(value==max(value)),
colour="red", shape=16, size=2) +
coord_fixed(ratio = ncol(volcano)/nrow(volcano), expand=FALSE) +
scale_fill_gradient2(low=cols[1], mid=cols[2], high=cols[3],
midpoint=mean(volcano)) +
theme_minimal()
