2 585
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; | |||
; | |||
CREATE FUNCTION vbit_to_int(x varbit) returns int as $f$ | |||
SELECT ( substring(0::bit(32),bit_length(x)+1) || x )::bit(32)::int | |||
$f$ LANGUAGE SQL IMMUTABLE; | |||
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== |
edições