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

(→‎Lib de Grades: add grid_br.xylevel_collapseTo_ijS e sua inversa)
Linha 87: Linha 87:
</syntaxhighlight>
</syntaxhighlight>


Portanto <code>grid_br.ijS_to_xySref(grid_br.xylevel_collapseTo_ijS(ponto,nivel))</code> fornece automaticamente a célula ''L0'' de referência onde será aplicado algoritmo GGeohash.
=== Construtor de geometria ===
Como vimos a referência é o ponto inferior esquerdo do contorno da célula, basta criar os demais 3 pontos de um quadrado. Na função abaixo a menor célula tem 1 metro pois necessitaria fração para menos que 1 m.
<syntaxhighlight lang="sql" style="font-size: 80%;">
DROP  FUNCTION if exists grid_br.xyS_draw_anycell(int,int,int)
;
DROP  FUNCTION if exists grid_br.xyS_draw_anycell(int[])
;
CREATE FUNCTION grid_br.xyS_draw_anycell(
  y int,  -- Yref
  x int,  -- Xref  (XY=canto inferior esquerdo)
  s int  -- side size
) RETURNS geometry AS $f$
  SELECT CASE WHEN s=0 THEN NULL ELSE ST_GeomFromText( format(
    'POLYGON((%s %s,%s %s,%s %s,%s %s,%s %s))',
    x,y,  x+s,y,  x+s,y+s,  x,y+s,  x,y
  ), 952019) END
$f$ LANGUAGE SQL IMMUTABLE;
COMMENT ON FUNCTION grid_br.xyS_draw_anycell(int,int,int)
  IS 'Draws a square-cell using the requested ref-point, with the requested side size.'
;
CREATE FUNCTION grid_br.xyS_draw_anycell(int[]) RETURNS geometry AS $wrap$
  SELECT grid_br.xyS_draw_anycell($1[1],$1[2],$1[3])
$wrap$ LANGUAGE SQL IMMUTABLE;
</syntaxhighlight>


=== Construtor do identificador cbits ===
[[File:Zcurve45bits.png|thumb|280px|A curva de Morton emerge do entrelaçamento dos bits. Exemplo: <br> <code> ints_to_interleavedbits(47,19,6)</code>.]]
Existem várias formas de obter o identificador baseado em curva de morton. O identificador IJ da célula, como vimos, é fácil de ser obtido no GGeohash.
<syntaxhighlight lang="sql" style="font-size: 80%;">
drop function if exists vbit_to_int(varbit);
drop function if exists vbit_to_int(varbit[]);
drop function if exists vbit_interleave;
drop function if exists ints_to_interleavedbits;
drop function if exists vbit_DeInterleave;


Depois entender os pontos de borda:
;
<pre>
CREATE FUNCTION vbit_to_int(x varbit) returns int as $f$
select a.gid_vbit, a.code_b16h, grid_br.xylevel_collapseTo_ijS(st_y(pt.geom)::int,st_x(pt.geom)::int,hlevel::int) as ijs
  SELECT ( substring(0::bit(32),bit_length(x)+1) || x )::bit(32)::int
from grid_br.all_levels a, lateral ST_DumpPoints( a.geom ) as pt
$f$ LANGUAGE SQL IMMUTABLE;
where hlevel=0 or hlevel=1 order by hlevel, 1;
</pre>


CREATE FUNCTION vbit_to_bigint(x varbit) returns int as $f$
  SELECT ( substring(0::bit(64),bit_length(x)+1) || x )::bit(64)::bigint
$f$ LANGUAGE SQL IMMUTABLE;
CREATE FUNCTION vbit_to_int(x varbit[]) returns int[] as $f$
  SELECT  array_agg( vbit_to_int(x_i) ORDER BY i) FROM unnest(x) WITH ORDINALITY t(x_i,i)
$f$ LANGUAGE SQL IMMUTABLE;
CREATE FUNCTION vbit_interleave(x varbit, y varbit) returns varbit as $f$
  SELECT  string_agg(( substring(x,i,1)||substring(y,i,1) )::text,'')::varbit
  FROM generate_series(1,bit_length(x)) t(i)
$f$ LANGUAGE SQL IMMUTABLE;
CREATE FUNCTION ints_to_interleavedbits(x int, y int, len int default 32) returns varbit as $f$
  SELECT vbit_interleave( substring(x::bit(32),33-len), substring(y::bit(32),33-len) )
$f$ LANGUAGE SQL IMMUTABLE;
-- SELECT ints_to_interleavedbits(47,19,6); -- 100110101111
CREATE FUNCTION vbit_DeInterleave(x varbit) returns varbit[] as $f$
  SELECT  array[  string_agg(substring(x,i,1)::text,'')::varbit,
                string_agg(substring(x,i+1,1)::text,'')::varbit
          ]
  FROM generate_series(1,bit_length(x),2) t(i)
$f$ LANGUAGE SQL IMMUTABLE;
-- SELECT vbit_to_int(vbit_DeInterleave(b'100110101111')); -- 47, 19
CREATE FUNCTION vbit_DeInterleave_to_int(x varbit) returns int[] as $wrap$
  SELECT vbit_to_int( vbit_DeInterleave(x) )
$wrap$ LANGUAGE SQL IMMUTABLE;
</syntaxhighlight>
Os indexadores IJ são a forma mais compacta (normalizada) de representação da grade, e independente da projeção ou métrica usadas. A função <code>ints_to_interleavedbits(i,j)</code> nos fornece exatamente o indexador desejado.
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.


==teste==
==teste==
2 366

edições