-
Notifications
You must be signed in to change notification settings - Fork 5
lixo, teste de reversibilidade do Geohash
Ver também:
- (demonstra que o limite para 64bits são Geohashes de 13 dígitos apelidado de geoint) https://github.com/hkwi/python-geohash/wiki/GeohashReference
- Curiosidades: coberturas https://github.com/ashwin711/proximityhash e funções https://godoc.org/github.com/mmcloughlin/geohash
- Perguntas abertas: geohash-length-to-be-reversible-to-latlong-using-postgis
Se, por questões de legibilidade e organização dos dados, adotarmos o Geohash nas listagens CSV de pontos, ao invés de coordenadas usuais, importante saber qual o tamanho mínimo do Geohash para que seja reversível.
A precisão adotada na preservação digital GeoJSON foi 6 casas demais de latitude e longitude.
geohash_len | sum_x | sum_y | avg_diffs | avg_diffs_not0 |
---|---|---|---|---|
9 | 19.687000 | 19.667004 | 0.0000107330 | ? |
10 | 5.011913 | 2.459694 | 0.0000020377 | 0.0000020912 |
13 | 0.088912 | 0.090457 | 0.0000000489 | ? |
14 | 0.090775 | 0.090080 | 0.0000000493 | 0.0000005 |
Rodou com n=1833326 para todos.
Uma forma aproximada de avaliar a demanda de precisão é pela conversão em base32 de todos os dígitos da LatLong: 8+8, um número com 16 dígitos decimais, por exemplo 9876543210123456
, que em base32 é 8OML7KQBS60
,ou seja, tem 11 dígitos. Se convertermos separadamente Lat e Long, por exemplo 98765432
em base32 é 2U62JO
(6 dígitos), teremos ao todo 12 dígitos base32.
Assim, é de se esperar um Geohash com algo em torno de 10 a 12 dígitos como "de mesma precisão" que as coordenadas LatLong originais. De fato, conferindo pelo simples percentual de taxa de erros, vemos que só começa a baixar depois dos 10 dígitos de Geohash, e dá um salto de 60% para 15% quando chegamos nos 12 dígitos. Em 13 não muda muito: tem aspecto de uma curva S com inflexão no 12.
geohash_len | avg_diffs | n_diffs_not0 | perc | avg_diffs_not0 |
---|---|---|---|---|
10 | 0.0000020377 | 1786453 | 97.4% | 0.0000020912 |
11 | 0.0000003716 | 1111317 | 60.6% | 0.0000006130 |
12 | 0.0000000756 | 267843 | 14.6% | 0.0000005173 |
13 | 0.0000000489 | 174916 | 9.5% | 0.0000005127 |
14 | 0.0000000493 | 176324 | 9.6% | 0.0000005128 |
É de se esperar também a interferência de erros de ponto flutuante quando passamos dos 13, pois são diversas conversões acumulando erros no processo. Fiquemos portanto com os 12 dígitos de Geohash como equivalentes a coordenadas LatLong de 6 decimais.
PS: com 14 já teríamos o inverso, um excesso de acúmulos de erro de ponto flutuante, interferindo ao invés de ajudar.
AMOSTRA: exagerando nos casos de erro,
orig_x | x | orig_y | y | diff_x | diff_y |
---|---|---|---|---|---|
-41.024779 | -41.024779 | -11.538081 | -11.538081 | 0.000000 | 0.000000 |
-40.595411 | -40.595411 | -11.604709 | -11.604708 | 0.000000 | 0.000001 |
-40.599088 | -40.599088 | -11.557004 | -11.557004 | 0.000000 | 0.000000 |
-39.159981 | -39.159980 | -16.557182 | -16.557182 | 0.000001 | 0.000000 |
-39.223874 | -39.223874 | -16.382529 | -16.382529 | 0.000000 | 0.000000 |
-38.529300 | -38.529300 | -13.007637 | -13.007636 | 0.000000 | 0.000001 |
-41.983470 | -41.983470 | -11.582078 | -11.582078 | 0.000000 | 0.000000 |
-41.965792 | -41.965792 | -11.523515 | -11.523515 | 0.000000 | 0.000000 |
-41.961747 | -41.961746 | -11.513828 | -11.513828 | 0.000001 | 0.000000 |
-41.835954 | -41.835954 | -11.273666 | -11.273666 | 0.000000 | 0.000000 |
-41.648883 | -41.648883 | -11.510430 | -11.510430 | 0.000000 | 0.000000 |
A título de verificação, se mudamos a precisão de LatLong para 5 decimais,
geohash_len | avg_diffs | n_diffs_not0 | perc | avg_diffs_not0 |
---|---|---|---|---|
9 | 0.0000107338 | 1733044 | 94.53% | 0.0000113549 |
10 | 0.0000020370 | 679864 | 37.08% | 0.0000054930 |
11 | 0.0000003749 | 134963 | 7.36% | 0.0000050926 |
12 | 0.0000000836 | 30480 | 1.66% | 0.0000050300 |
13 | 0.0000000563 | 20502 | 1.12% | 0.0000050332 |
14 | 0.0000000570 | 20792 | 1.13% | 0.0000050293 |
O que mostra que a análise é consistente, e a comparação com simples conversão para base32 (~10 dígitos na coordenada monolítica) continua sendo válida. Com este grau de precisão na LatLong parece não haver mais interferência dos erros de ponto flutuante: há uma a convergência mais consistente percentual para zero. O ponto flutuante passa a interferir no Geohash de 14 dígitos (13 portanto seria o mais preciso), que pode ser tomado como limite de usabilidade do Geohash na precisão default do PostGIS.
CREATE or replace VIEW vw_point_geohash_diffs AS
SELECT *, abs(orig_x-x) diff_x, abs(orig_y-y) diff_y
FROM (
SELECT orig_x, round(st_x(pt),6) x, orig_y, round(st_y(pt),6) y
FROM (
SELECT osm_id, st_centroid(ST_GeomFromGeoHash( st_geohash(way,14) )) pt,
round(st_x(way),6) orig_x, round(st_y(way),6) orig_y
FROM planet_osm_point -- where osm_id=5916601782
) t1
) t2;
-- amostra, se vw_point_geohash_diffs for materialized view
SELECT * FROM vw_point_geohash_diffs
tablesample BERNOULLI(1);
-- estimativa de erro e precisão:
SELECT n, sum_x, sum_y, round(avg_diffs/2.0,10) as avg_diffs, n_diffs_not0,
round(100.0*n_diffs_not0/n,2)||'%' as perc,
round(avg_diffs_not0/2.0,10) as avg_diffs_not0
FROM (
SELECT count(*) n, sum(diff_x) sum_x, sum(diff_y) sum_y,
avg(diff_x+diff_y) avg_diffs,
count(*) FILTER (WHERE diff_x>0 OR diff_y>0) n_diffs_not0,
avg(diff_x+diff_y) FILTER (WHERE diff_x>0 OR diff_y>0) avg_diffs_not0
FROM vw_point_geohash_diffs
) t;
-- ... repetir para cada st_geohash(way,R) com R={9,10,11,12,13,14}: