Ir para o conteúdo

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

m
de volta para XY cartesiana da escola
m (→‎Sistemas de coordenadas: revisao de texto)
m (de volta para XY cartesiana da escola)
Linha 1: Linha 1:
Biblioteca para simplificar a geração do sistema de grades de um país. Exemplificando implementação dentro do ''schema'' <code>grid_br</code> das grades do Brasil.
Biblioteca para simplificar a geração do sistema de grades de um país. Exemplificando implementação dentro do ''schema'' <code>grid_br</code> das grades do Brasil.
Lembretes:
* Convencionou-se em GGeohash usar YX no lugar de XY.
* ...


A seguir avaliando o uso ''default'' de XYref no lugar de XYcenter, para o desenho da célula. Algumas funções de flexibilização precisam ser agrupadas como "helper functions", enquanto as demais como "core functions". Por exemplo as convenções de array de inteiros baseadas em nível (xyL e ijL) são ''core'', enquanto as baseadas em size-side (xyS e ijS) são ''helper''.  
A seguir avaliando o uso ''default'' de XYref no lugar de XYcenter, para o desenho da célula. Algumas funções de flexibilização precisam ser agrupadas como "helper functions", enquanto as demais como "core functions". Por exemplo as convenções de array de inteiros baseadas em nível (xyL e ijL) são ''core'', enquanto as baseadas em size-side (xyS e ijS) são ''helper''.  
Linha 41: Linha 37:
Tanto o padrão DGGS como o DNGS são relativos a "Discrete Grid Systems", ou seja, um conjunto hierárquico de grades, cada qual no seu nível ''L'', e assumindo apenas valores discretizados de posição. As "funções ''core''" do padrão DNGS garantem a ida e volta entre os diversos sistemas de coordenadas necessários à manipulação dos dados, antes e depois da discritização.
Tanto o padrão DGGS como o DNGS são relativos a "Discrete Grid Systems", ou seja, um conjunto hierárquico de grades, cada qual no seu nível ''L'', e assumindo apenas valores discretizados de posição. As "funções ''core''" do padrão DNGS garantem a ida e volta entre os diversos sistemas de coordenadas necessários à manipulação dos dados, antes e depois da discritização.
   
   
'''Discretizadores''': transformam as coordenadas contínuas YX, de posição no plano projetado,  em coordenadas discretas IJ, de localização na grade hierárquica.  Quem amarra a posição hierárquica &mdash; ''grid hierarchical level'' do sistema de grades &mdash; com localização YX é o tamanho de lado ''S'' (''side size'') da célula de nível ''L''.  
'''Discretizadores''': transformam as coordenadas contínuas XY, de posição no plano projetado,  em coordenadas discretas IJ, de localização na grade hierárquica.  Quem amarra a posição hierárquica &mdash; ''grid hierarchical level'' do sistema de grades &mdash; com localização XY é o tamanho de lado ''S'' (''side size'') da célula de nível ''L''.  


Por imposição do [[Discrete National Grid Systems/pt|padrão DNGS]] temos <math>S_{L}=2^{Lmax-L}</math>. No caso do Brasil ''Lmax''=20, no caso de Camarões ''Lmax=18''.  
Por imposição do [[Discrete National Grid Systems/pt|padrão DNGS]] temos <math>S_{L}=2^{Lmax-L}</math>. No caso do Brasil ''Lmax''=20, no caso de Camarões ''Lmax=18''.  
Linha 47: Linha 43:
:Nota. A fórmula de ''S'' funciona também para níveis-meio, por exemplo ''L''=1.5. Isso se deve à suposição de que o "tamanho do lado genérico ''S'' de um retângulo" seja a raiz quadrada da área do retângulo; e pela [[Generalized_Geohash/pt#Representação_geométrica|construção geométrica dos níveis-meio]], cujas células (necessariamente de áreas iguais) são a união de 2 células do próximo nível inteiro: <br /> <math>S_{Lhalf}=\sqrt{2\cdot{Area_{\lceil Lhalf\rceil}}} = \sqrt{2} \cdot \sqrt{{{S_{\lceil Lhalf\rceil}}^2}}  =    2^{Lmax-\lceil Lhalf\rceil + 0.5}</math> onde <math>Lhalf = \forall L | L = \lceil L \rceil - 0.5</math>. <br />A mesma fórmula de ''S'' também nos permite calcular, conforme  [[osmc:Metodologia/Algoritmo_SQL/Issues#Issue_05_-_Cálculo_de_dígitos_base32|issue 05]], o número de dígitos base32 para se chegar no metro, a partir do nível ''Lcover'' do município: <math>Ndig1m = 1+\lceil (Lmax-Lcover)/2.5 \rceil</math>.
:Nota. A fórmula de ''S'' funciona também para níveis-meio, por exemplo ''L''=1.5. Isso se deve à suposição de que o "tamanho do lado genérico ''S'' de um retângulo" seja a raiz quadrada da área do retângulo; e pela [[Generalized_Geohash/pt#Representação_geométrica|construção geométrica dos níveis-meio]], cujas células (necessariamente de áreas iguais) são a união de 2 células do próximo nível inteiro: <br /> <math>S_{Lhalf}=\sqrt{2\cdot{Area_{\lceil Lhalf\rceil}}} = \sqrt{2} \cdot \sqrt{{{S_{\lceil Lhalf\rceil}}^2}}  =    2^{Lmax-\lceil Lhalf\rceil + 0.5}</math> onde <math>Lhalf = \forall L | L = \lceil L \rceil - 0.5</math>. <br />A mesma fórmula de ''S'' também nos permite calcular, conforme  [[osmc:Metodologia/Algoritmo_SQL/Issues#Issue_05_-_Cálculo_de_dígitos_base32|issue 05]], o número de dígitos base32 para se chegar no metro, a partir do nível ''Lcover'' do município: <math>Ndig1m = 1+\lceil (Lmax-Lcover)/2.5 \rceil</math>.


A decisão de usar a sequência YX e não XY precisa talvez ser revista. Na cultura escolar brasileira XY é horizontal-vertical. Na cultura das imagens de satélite e geoprocessamento XY é vertical-horizontal. Adotamos a "cultura PostGIS", das funções ''standard spatial type'' (aquelas com prefixo "ST_").
A decisão de usar a sequência XY e não XY precisa talvez ser revista. Na cultura escolar brasileira XY é horizontal-vertical. Na cultura das imagens de satélite e geoprocessamento XY é vertical-horizontal. Adotamos a "cultura PostGIS", das funções ''standard spatial type'' (aquelas com prefixo "ST_").


<syntaxhighlight lang="sql" style="font-size: 80%;">
<syntaxhighlight lang="sql" style="font-size: 80%;">
-- Core functions:
-- Core functions:
drop FUNCTION if exists grid_br.yxS_collapseTo_ijS(int,int,int,boolean);
drop FUNCTION if exists grid_br.xyS_collapseTo_ijS(int,int,int,boolean);
drop FUNCTION if exists grid_br.yxL_collapseTo_ijL(int[]);
drop FUNCTION if exists grid_br.xyL_collapseTo_ijL(int[]);


CREATE FUNCTION grid_br.yxS_collapseTo_ijS(y int, x int, s int default 1048576, is_half boolean default false) RETURNS int[] AS $f$
CREATE FUNCTION grid_br.xyS_collapseTo_ijS(y int, x int, s int default 1048576, is_half boolean default false) RETURNS int[] AS $f$
   SELECT array[ (y-6727000)/CASE WHEN is_half AND s>=2 THEN s/2 ELSE s END, (x-2715000)/s, s ]
   SELECT array[ (y-6727000)/CASE WHEN is_half AND s>=2 THEN s/2 ELSE s END, (x-2715000)/s, s ]
$f$ language SQL IMMUTABLE;
$f$ language SQL IMMUTABLE;


CREATE FUNCTION grid_br.yxL_collapseTo_ijL(yxL int[]) RETURNS int[] AS $f$
CREATE FUNCTION grid_br.xyL_collapseTo_ijL(xyL int[]) RETURNS int[] AS $f$
   SELECT array[ $ijS[1], $ijS[2], intlevel ]
   SELECT array[ $ijS[1], $ijS[2], intlevel ]
   FROM (  
   FROM (  
Linha 73: Linha 69:
DROP  FUNCTION if exists grid_br.xyS_draw_anycell(int,int,int)
DROP  FUNCTION if exists grid_br.xyS_draw_anycell(int,int,int)
;
;
CREATE FUNCTION grid_br.yxS_draw_anycell(
CREATE FUNCTION grid_br.xyS_draw_anycell(
   y int,  -- Yref
   y int,  -- Yref
   x int,  -- Xref  (XY=canto inferior esquerdo)
   x int,  -- Xref  (XY=canto inferior esquerdo)
Linha 143: Linha 139:
Cada célula da cobertura ''L0'' já tem seu código de 4 bits (dígito hexadecimal), em seguida qualquer outra célula de qualquer nível hierárquico terá um código ''cbits'' do nível ''L'' com ''L*2'' bits obtidos das coordenadas IJ  através da função <code>ints_to_interleavedbits(i,j)</code>. O tamanho de lado da célula do nível ''L'', no caso do Brasil, será <math>2^{20-L}</math> metros. A célula de 1 m é justamente a célula do nível ''L20'', portanto terá <math>20*2=40</math> bits de comprimento, concatenados aos 4 bits de L0 e ao prefixo do país.
Cada célula da cobertura ''L0'' já tem seu código de 4 bits (dígito hexadecimal), em seguida qualquer outra célula de qualquer nível hierárquico terá um código ''cbits'' do nível ''L'' com ''L*2'' bits obtidos das coordenadas IJ  através da função <code>ints_to_interleavedbits(i,j)</code>. O tamanho de lado da célula do nível ''L'', no caso do Brasil, será <math>2^{20-L}</math> metros. A célula de 1 m é justamente a célula do nível ''L20'', portanto terá <math>20*2=40</math> bits de comprimento, concatenados aos 4 bits de L0 e ao prefixo do país.


A degeneração geométrica, de quadrado para retângulo, é relativa ao segundo argumento de <code>vbit_interleave(x,y)</code>. Como a função é sempre chamada com a mesma ordem dos argumentos, sempre teremos ou só retangulos orizontais (XY) ou só verticais (YX).
A degeneração geométrica, de quadrado para retângulo, é relativa ao segundo argumento de <code>vbit_interleave(x,y)</code>. Como a função é sempre chamada com a mesma ordem dos argumentos, sempre teremos ou só retangulos orizontais (XY) ou só verticais (XY).


=== Otimização do cálculo de cobertura===
=== Otimização do cálculo de cobertura===
Linha 197: Linha 193:
drop FUNCTION if exists grid_br.xyS_to_cbits(int,int,int,boolean)
drop FUNCTION if exists grid_br.xyS_to_cbits(int,int,int,boolean)
;
;
-- revisar se é YX!
-- revisar se é XY!
CREATE FUNCTION grid_br.xyS_to_cbits(
CREATE FUNCTION grid_br.xyS_to_cbits(
   y int,
   y int,
Linha 302: Linha 298:
$wrap$ LANGUAGE SQL IMMUTABLE
$wrap$ LANGUAGE SQL IMMUTABLE
;
;
CREATE FUNCTION grid_br.xyL_collapseTo_ijS(yxl int[]) RETURNS int[] AS $wrap$
CREATE FUNCTION grid_br.xyL_collapseTo_ijS(xyl int[]) RETURNS int[] AS $wrap$
   SELECT grid_br.xyS_collapseTo_ijS(yxl[1], yxl[2], yxl[3])
   SELECT grid_br.xyS_collapseTo_ijS(xyl[1], xyl[2], xyl[3])
$wrap$ LANGUAGE SQL IMMUTABLE
$wrap$ LANGUAGE SQL IMMUTABLE
;
;
Linha 314: Linha 310:
$f$ LANGUAGE SQL IMMUTABLE;
$f$ LANGUAGE SQL IMMUTABLE;


CREATE FUNCTION grid_br.ijS_to_xySref(yxl int[], is_half boolean default false) RETURNS int[] AS $wrap$
CREATE FUNCTION grid_br.ijS_to_xySref(xyl int[], is_half boolean default false) RETURNS int[] AS $wrap$
   SELECT grid_br.ijS_to_xySref(yxl[1], yxl[2], yxl[3],is_half)
   SELECT grid_br.ijS_to_xySref(xyl[1], xyl[2], xyl[3],is_half)
$wrap$ LANGUAGE SQL IMMUTABLE;
$wrap$ LANGUAGE SQL IMMUTABLE;
</syntaxhighlight>
</syntaxhighlight>
Linha 359: Linha 355:
drop view test_l0_refpoint;
drop view test_l0_refpoint;
create view test_l0_refpoint as  
create view test_l0_refpoint as  
select *, ST_SetSRID(ST_POINT(yxs[2], yxs[1]), 952019) as geom
select *, ST_SetSRID(ST_POINT(xys[2], xys[1]), 952019) as geom
from (
from (
  select code_b16h, ijs[1] i, ijs[2] j, grid_br.ijS_to_xySref(ijs) as yxs, count(*) n   
  select code_b16h, ijs[1] i, ijs[2] j, grid_br.ijS_to_xySref(ijs) as xys, count(*) n   
  from (
  from (
   select  a.code_b16h, grid_br.xylevel_collapseTo_ijS(st_y(pt.geom)::int,st_x(pt.geom)::int,hlevel::int) as ijs
   select  a.code_b16h, grid_br.xylevel_collapseTo_ijS(st_y(pt.geom)::int,st_x(pt.geom)::int,hlevel::int) as ijs
2 583

edições