Uma maneira de abordar esse problema interessante é vê-lo como um estimador robusto do centro de uma distribuição de pontos bivariados. Uma solução (bem conhecida) é descascar cascos convexos até que não sobrar nada . O centróide do último casco não vazio localiza o centro.
(Isso está relacionado ao bagplot . Para obter mais informações, pesquise na Web "outlier multivariado de casca convexa de casco").
O resultado para os 16 pontos ilustrados é mostrado como o triângulo central neste mapa. Os três polígonos circundantes mostram os cascos convexos sucessivos. Os cinco pontos periféricos (30% do total!) Foram removidos nos dois primeiros passos.
O exemplo foi computado R
. O próprio algoritmo é implementado no bloco do meio, "peeling convexo". Ele usa a chull
rotina interna, que retorna os índices de pontos no casco. Esses pontos são removidos por meio da expressão de indexação negativa xy[-hull, ]
. Isso é repetido até que os últimos pontos sejam removidos. Na última etapa, o centróide é calculado calculando a média das coordenadas.
Observe que, em muitos casos, a projeção dos dados nem é necessária: os cascos convexos não serão alterados, a menos que os recursos originais abranjam o antimeridiano (longitude de +/- 180 graus), seja um polo ou sejam tão extensos que a curvatura dos segmentos entre eles ocorrerá. faça a diferença. (Mesmo assim, a curvatura será de pouca preocupação, porque o descascamento ainda convergirá para um ponto central.)
#
# Project the data.
#
dy <- c(8,7,5,10,7,17,19,19,21,22,22,22,24,24,26,26)
dx <- c(66,67,66,89,89,79,78,76,75,81,78,77,75,80,77,83)
lat <- (28.702 + dy/1e5) / 180 * pi
lon <- (77.103 + dx/1e5) / 180 * pi
y <- dy
x <- cos(mean(lat)) * dx
#
# Convex peeling.
#
xy <- cbind(x, y)
while(TRUE) {
hull <- chull(xy)
if (length(hull) < nrow(xy)) {
xy <- xy[-hull, ]
} else {
xy.0 <- matrix(apply(xy, 2, mean), 1, 2)
break
}
}
#
# Plot the data `xy` and the solution `xy.0`.
#
plot(range(x), range(y), type="n", asp=1)
points(x, y, pch=21, bg="#a01010")
points(xy.0, pch=24, cex=1.2, bg="#404080")