基于多边形坐标对3D振幅矩阵进行子集化的技术求助
Hey there! Let's sort out this amplitude matrix subsetting problem for your bioacoustics work. Here's a straightforward, step-by-step solution that should get you the result you need:
Step 1: Create a grid of all time-frequency points
First, we need to map every point in your s$amp matrix to its corresponding time and frequency coordinates. We'll use expand.grid to generate all combinations of the time and frequency vectors from your spectro object:
# Generate all time-frequency coordinate pairs grid_points <- expand.grid(time = s$time, freq = s$freq)
Step 2: Identify points inside the polygon
Next, we'll check which of these grid points fall inside (or on the boundary of) your con.max polygon. The base R function grDevices::point.in.polygon does this perfectly—it returns 1 for points inside the polygon, 2 for points on the boundary, and 3 for points outside. We'll use this to create a logical vector marking valid points:
# Check each point's position relative to the polygon inside_status <- point.in.polygon( x = grid_points$time, y = grid_points$freq, pol.x = con.max$x, pol.y = con.max$y ) # Flag points that are inside or on the polygon boundary is_inside <- inside_status %in% c(1, 2)
Step 3: Reshape the logical vector to match your amplitude matrix
The is_inside vector is a 1D list, but we need it to match the 2D structure of s$amp. Since s$amp has rows corresponding to frequencies and columns corresponding to times (the default from seewave::spectro), we'll reshape the vector into a matrix with the same dimensions:
# Convert the logical vector to a matrix matching s$amp's dimensions inside_matrix <- matrix(is_inside, nrow = length(s$freq), ncol = length(s$time))
Step 4: Subset the amplitude matrix
Finally, we'll create your new amplitude matrix by keeping only the values inside the polygon and setting everything else to NA (which acts as "blank" for plotting):
# Create the subset matrix: keep inside values, set outside to NA amp_subset <- s$amp amp_subset[!inside_matrix] <- NA
Verify the result
You can confirm this works by overlaying the subset matrix on your original spectrogram:
# Plot the original spectrogram spectro(tico, grid=F, osc=F, scale=F) # Add the subset amplitude data image(x = s$time, y = s$freq, z = amp_subset, add = TRUE, col = seewave::spectro.colors(100)) # Redraw the polygon to check alignment polygon(x = con.max$x, y = con.max$y, lwd = 2)
A quick check: If you're unsure about the dimensions of s$amp, run dim(s$amp) to confirm rows correspond to frequencies and columns to times. If your setup differs, adjust the nrow/ncol arguments in the matrix() call accordingly.
内容的提问来源于stack exchange,提问作者Pedro Rocha

