osmc:Metodologia/Algoritmo SQL: mudanças entre as edições

Linha 16: Linha 16:
   grid_xy_origin: 3678500 970000
   grid_xy_origin: 3678500 970000
   grid_cell_side: 524288
   grid_cell_side: 524288
   grid_l0_cell: 02 03 10 11 12 13 20 21 22 23 30 31 32 40 41 42
   grid_l0_cell_ij:   02 03 10 11 12 13 20 21 22 23 30 31 32 40 41 42
   grid_l0_cell_sci_base: 8 a 1 3 9 b 4 6 c e 5 7 d 0 2 f
   grid_l0_cell_idxb16: 8 a 1 3 9 b 4 6 c e 5 7 d 0 2 f
</pre>
</pre>
onde [https://postgis.net/docs/using_postgis_dbmanagement.html#spatial_ref_sys ''srid''] é a projeção igual-area do país; ''grid_xy_origin'' é a origem no plano projetado; ''grid_cell_side'' é o tamanho (potência de 2) da célula ''L0'' adotada; ''grid_l0_cell'' a lista de coordenadas ''ij'' da matriz de células, indicando aquelas selecionados para a cobertura; e ''grid_l0_cell_sci_base'' a sua correspondente indexação, já expressa em base16.
onde [https://postgis.net/docs/using_postgis_dbmanagement.html#spatial_ref_sys ''srid''] é a projeção igual-area do país; ''grid_xy_origin'' é a origem no plano projetado; ''grid_cell_side'' é o tamanho (potência de 2) da célula ''L0'' adotada; ''grid_l0_cell'' a lista de coordenadas ''ij'' da matriz de células, indicando aquelas selecionados para a cobertura; e ''grid_l0_cell_sci_base'' a sua correspondente indexação, já expressa em base16.
Linha 77: Linha 77:
|}
|}


A coluna ''cbits'' é composta de duas partes, o código do país e o código da sua célula ''L0''. O código é traduzido em hexadecimal (base16) na coluna ''b16'', e suas células formam a cobertura do país, ou seja, a grade de nível zero. Nos  [[osmc:Convenções/Grade científica multifinalitária|geocódigos de notação científica]] aparecerão sempre como primeiro dígito.  
A coluna ''cbits'' é composta de duas partes, o código do país e o código da sua célula ''L0''. O código é traduzido em hexadecimal (base16) na coluna ''b16'', e suas células formam a cobertura do país, ou seja, a grade de nível zero. Nos  [[osmc:Convenções/Grade científica multifinalitária|geocódigos de notação científica]] apare cerão sempre como primeiro dígito.
 
Os códigos de país nessa versão ainda eram códigos ISO ocupando 10 bits. Por exemplo Brasil <code>0001001100</code> é 76. Na versão mais atual são códigos internos (sem compromisso com ISO) de 8 bits, garantindo melhor ocupação nos 57 bits (56 bits para acomodar 14 dígitos hexadecimais) disponíveis de geocódigo [[Código_Natural/Representação_interna#hInt|hInt64]] (essa representação alternativa é mais eficiente e versátil do que o tipo de dado ''varbit'' (bit string) do PostgreSQL.


A interseção da geometria da célula com o polígono do país tem a sua área indicada pela coluna ''area_km2''. A coluna ''is_contained'' é um flag, verdadeiro quando a célula tem interseção com as bordas do país. Ver  [[osmc:Metodologia/Algoritmo_SQL/Issues#Issue_02_-_Função_estimadora_de_cobertura_interior_e_quadrado_envolvente|Issue 02 para detalhes sobre a dedução do caso cheio pela área]].  
A interseção da geometria da célula com o polígono do país tem a sua área indicada pela coluna ''area_km2''. A coluna ''is_contained'' é um flag, verdadeiro quando a célula tem interseção com as bordas do país. Ver  [[osmc:Metodologia/Algoritmo_SQL/Issues#Issue_02_-_Função_estimadora_de_cobertura_interior_e_quadrado_envolvente|Issue 02 para detalhes sobre a dedução do caso cheio pela área]].  
Linha 94: Linha 96:
;
;
</syntaxhighlight>
</syntaxhighlight>
=== Seletor de projeção ===
[[Arquivo:DNGS-BBOXes-exemplo2.png|thumb|380px|BBOX WGS84 sobre o globo, quando apenas Brasil e Colômbia adotavam o padrão DNGS. A BBOX original de cada país é decomposta em BBOXes "puras" e "de fronteira". As puras permitem rápida decisão (alta performance), enquanto as de fronteira, ''border boxes'' em rosa, requerem avaliação de pertinência ao polígono de fronteira.]]
O padrão DNGS, conforme seu [[Discrete_National_Grid_Systems/pt#Seletor_de_jurisdição|algoritmo seletor de jurisdição]], requer que qualquer ponto sobre o globo, expresso em WGS84 sem projeção, tenha seu geocódigo resolvido conforme a jurisdição da sua posição. O algoritmo decide qual projeção usar. A verificação em grandes BBOXes, sem bordas, tem alta performance, enquanto que a decisão sobre polígonos de borda tem menor performance.
A grade ''L0'' serve de referência para a criação de recortes BBOX WGS84 sobre o globo, onde as escolhas de projeção são reproduzidas de forma mais grosseira que o mosaico ''L0'', e, nas bordas, recortadas. Supondo ''pt'' a geometria de um ponto:
: <code>SELECT srid FROM osmc.coverage_srid <br/>WHERE pt && geom<br/>  AND (is_not_border OR ST_Intersects(pt,geom))</code>
: indexação prévia com <br/><code>CREATE INDEX osmc_coverage_srid_idx1<br/>ON osmc.coverage_srid(is_not_border,geom) <br/>USING GIST (geom)</code>
: a performance pode ser avaliada por <br/><code>VACUUM ANALYZE osmc_coverage_srid_idx1</code>


O conhecimento prévio do SRID (pode ser por contexto) permite por fim fazer a busca na tabela <code>osmc.coverage</code>.
=== Seletor de jurisdição e L0 ===
=== Seletor de jurisdição e L0 ===
Em aplicações que partem de um cenário global, ou de pontos que precisam ser selecionados como interiores ou não ao território nacional, é importante detectar não só a célula ''L0'' mas também o polígono territorial. Situações:
Uma vez selecionada a projeção, o ponto é transformado conforme SRID e confrontado apenas contra as BBOXes de células L0 daquela projeção. No caso especial de ser uma projeção adotada por mais de um país (por exemplo Itália e Vaticano), e o ponto cair em uma interseção de BBOXes, a seleção do recorte de ''L0'' correto dependerá do ponto estar contido no polígono do recorte.
 
Justamente para contemplar os casos especiais a seleção de jurisdição acaba usando uma condição e indexação mais complexa, similar à seletora de projeção:
: <code>SELECT cbits as cbits_l0 FROM osmc.coverage <br/>WHERE srid=$srid AND pt && geom<br/>  AND (is_not_border OR ST_Intersects(pt,geom))</code>
: indexação prévia com <br/><code>CREATE INDEX osmc_coverage_idx1<br/>ON osmc.coverage(is_not_border,geom) <br/>USING GIST (geom)</code>
O valor ''cbits_l0'' é o identificador de célula ''L0'' do país correto, e o identificador de país é seu prefixo. A partir do ponto ''pt'' (com geometria já no SRID do país) e ''cbits_l0'' obtemos por algoritmo  GGeohash o valor ''cbits_pt'' da célula pontual, <code>cbits_pt=encode(pt,cbits_l0)</code>.
 
Em aplicações que partem de um cenário global, ou de pontos que precisam ser selecionados como interiores ou não ao território nacional, é importante detectar não só a célula ''L0'' mas também o polígono territorial. Em outras aplicações maior performance pode ser conseguida desprezando-se o risco de ponto externo aos limites nacionais.
 
<!--
Situações:


* mais geral, sem nação definida: ponto sem projeção, dado em latitude-longitude. O [[osmc:Metodologia#Seletor_de_jurisdição|seletor de jurisdição baseado em BBOX WGS84]] que determina a projeção a usar.  
* mais geral, sem nação definida: ponto sem projeção, dado em latitude-longitude. O [[osmc:Metodologia#Seletor_de_jurisdição|seletor de jurisdição baseado em BBOX WGS84]] que determina a projeção a usar.  
* menos exigente, com ponto já na projeção nacional porém sem exigência de saber se fora ou dentro do território: aplicativos dedicados não esperam receber pontos exteriores, portanto não carece conferir se, mesmo em células ''L0'' de borda, é ou não interior. O seletor de célula se reduz ao BBOX da projeção, dispensa uso do polígono.
* menos exigente, com ponto já na projeção nacional porém sem exigência de saber se fora ou dentro do território: aplicativos dedicados não esperam receber pontos exteriores, portanto não carece conferir se, mesmo em células ''L0'' de borda, é ou não interior. O seletor de célula se reduz ao BBOX da projeção, dispensa uso do polígono.
* mais exigente: em aplicações onde certeza de ser ponto interior é necessária. Aí entra o uso do flag, pois se for selecionada uma célula ''L0'' com flag de borda, o seu contorno poligonal também precisará ser verificado. Tipicamente 3 passos na comparação do ponto ''pt'' com a célula ''cell'': <code>pt && cell AND (not_border OR ST_Contains(pt,cell))</code>. A otimização desse tipo de query requer de indexador específico.
* mais exigente: em aplicações onde certeza de ser ponto interior é necessária. Aí entra o uso do flag, pois se for selecionada uma célula ''L0'' com flag de borda, o seu contorno poligonal também precisará ser verificado. Tipicamente 3 passos na comparação do ponto ''pt'' com a célula ''cell'': <code>pt && cell AND (not_border OR ST_Contains(pt,cell))</code>. A otimização desse tipo de query requer de indexador específico.


São esperadas [[osmc:Metodologia#Projeção_e_cobertura_nacionais|potências de 2]] nas células cheias de ''is_contained''. Para o Brasil é esperada a potência 20 no tamanho de lado do quadrado: <math>\sqrt{1099512\ km^2} = 1048576 \ m = 2^{20}</math>. Para Camarões (CM) potência 18: <math>\sqrt{68719\ km^2} = 262143.1 \ m \approx 262144 \ m = 2^{18}</math>.
São esperadas [[osmc:Metodologia#Projeção_e_cobertura_nacionais|potências de 2]] nas células cheias de ''is_contained''. Para o Brasil é esperada a potência 20 no tamanho de lado do quadrado: <math>\sqrt{1099512\ km^2} = 1048576 \ m = 2^{20}</math>. Para Camarões (CM) potência 18: <math>\sqrt{68719\ km^2} = 262143.1 \ m \approx 262144 \ m = 2^{18}</math>.
 
-->
Os códigos de país nessa versão ainda eram códigos ISO ocupando 10 bits. Por exemplo Brasil <code>0001001100</code> é 76. Na versão corrente são códigos internos (sem compromisso com ISO) de 8 bits, garantindo melhor ocupação nos 57 bits (56 bits para acomodar 14 dígitos hexadecimais) disponíveis de geocódigo [[Código_Natural/Representação_interna#hInt|hInt64]].


== Gerando a grade L0 de cobertura do país ==
== Gerando a grade L0 de cobertura do país ==
2 364

edições