I am currently working on a number of animal teeth stored as surface meshes in R. Some of the variables I am looking at may be influenced by the number of cusps on the tooth and I would like to try and find a way to dynamically and (relatively) non-subjectively calculate the approximate number of cusps on each mesh.
It occurred to me that it should be possible to roughly estimate the number of cusps by identifying the number of local maxima on each tooth, particularly on the z-axis. Each local maxima in three-dimensional space should correspond to the apex of a cusp.
For example, let's take the Hills sample file from the molaR package.
library(molaR)
DNE3d(DNE(Hills))
Based on this mesh, approximately four distinct peaks are present.
From this, it should be possible to identify the n (4) local minima present on the mesh using the matrix of vertices from Hills$vb, which shows the location of points on the surface of the mesh in the x, y, and z axes. The desired output would be a vector with the positions of the four three-dimensional points a, b, c, and d (or something like this). From there I can take the length of this vector to return the number of local maxima.
However, when I've tried identifying the number of peaks using ggpmisc::find_peaks or pracma::findpeaks, it does not work. I've also tried using the find_peaks function presented here, but the results are also highly variable.
What it looks like is these functions are tailored for finding local optima in a time series or 2D array, but not a 3D array/matrix. Perhaps there is some way to calculate maxima by treating x and y as positional information and z as height, but I am not sure.
Trying to look up this question in Google produced the following code.
find_local_maxima <- function(matrix) {
local_maxima <- array(FALSE, dim = dim(matrix))
for (i in 1:dim(matrix)[1]) {
for (j in 1:dim(matrix)[2]) {
for (k in 1:dim(matrix)[3]) {
# Get the current value
current_value <- matrix[i, j, k]
# Get neighbors (adjust neighborhood as needed)
neighbors <- c(
matrix[i-1, j, k], matrix[i+1, j, k],
matrix[i, j-1, k], matrix[i, j+1, k],
matrix[i, j, k-1], matrix[i, j, k+1]
)
# Check if current value is a local maximum
if (all(current_value >= neighbors)) {
local_maxima[i, j, k] <- TRUE
}
}
}
}
return(local_maxima)
}
Perhaps there is something of value in this code, but I am very skeptical of any result provided by generative AI. When I try applying it to Hills$vb, I get the following error message, even if I restrict the matrix to the first three vectors (Hills$vb[1:3,]).
Error in 1:dim(matrix)[3] : NA/NaN argument
Is there any way to identify the number of maxima in this type of data using R?

