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

m
 
(9 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
Issues e discussões conceituais, antes de se partir para a implementação.
Issues e discussões conceituais, antes de se partir para a implementação. Ver também [[Discussão:DNGS/Decisões_soberanas#Issues]], relativas a decisões humanas, sem algoritmo previsto.


== Issue 01 - Uso ótimo do hInt64 ==
== Issue 01 - Uso ótimo do hInt64 ==
Linha 132: Linha 132:
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
select hlevel, count(*) n_cells, round(sqrt(max(st_area(geom)))/1000.0) side_km,
select hlevel, count(*) n_cells, round(sqrt(max(st_area(geom)))/1000.0) side_km,
       round(avg(ST_NPoints(geom))) npts_geom, round(avg(ST_NPoints(geom4326))) npts_geom,
       round(avg(ST_NPoints(geom))) geom_npts,
       round(avg(ST_NPoints(st_simplify(geom4326,0.00000005)))) npts_simpl
      round(avg(ST_CharactDiam(geom))) as geom_chdiam, -- relative ref.
      round(avg(ST_NPoints(geom4326))) g4326_npts,
       round(avg(ST_NPoints(st_simplify(geom4326,0.00000005)))) g4326simpl_npts
      -- 0.00000005 is SRID-metric absolute ref
from grid_cm.all_levels
from grid_cm.all_levels
group by 1 order by 1;
group by 1 order by 1;
Linha 160: Linha 163:


Na resposta da questão quebrar em duas,  "general" depois "grids" (exemplificar com níveis inteiros pulando os meios).  Nas grades supor que só um eixo precisa de pontos ... Ver eles no QGIS ou pelo menos nos dados de 11 pontos. O segmentize aplicado a uma só direção é complexo, não vale a pena.
Na resposta da questão quebrar em duas,  "general" depois "grids" (exemplificar com níveis inteiros pulando os meios).  Nas grades supor que só um eixo precisa de pontos ... Ver eles no QGIS ou pelo menos nos dados de 11 pontos. O segmentize aplicado a uma só direção é complexo, não vale a pena.
<syntaxhighlight lang="sql">
DROP FUNCTION IF EXISTS ST_Transform_Resilient
;
CREATE FUNCTION ST_Transform_Resilient(
  g    geometry,    -- the input geometry
  srid integer,      -- target SRID, to transform g
  size_fraction float DEFAULT 0.05,  -- 1/density. Density of points per charactDiam (or negative for absolute fraction).
  tolerance    float DEFAULT 0      -- E.g. on srid=4326 use 0.00000005.
                                    -- ZERO=0.000000001. Smallest=0.000000005. Start cell with 0.00000002.
) RETURNS      geometry
  language SQL IMMUTABLE
AS $f$
SELECT CASE
      WHEN COALESCE(size_fraction,0.0)>0.0 AND COALESCE(tolerance,0)>0 THEN
          ST_SimplifyPreserveTopology(geom,tolerance) -- ST_Simplify enough for grid cells
      ELSE geom
      END
FROM (
  SELECT CASE
    WHEN size>0.0 THEN  ST_Transform(  ST_Segmentize(g,size)  , srid  )
    ELSE  ST_Transform(g,srid)
    END geom, size
  FROM (
    SELECT CASE
        WHEN size_fraction IS NULL THEN 0.0
        WHEN size_fraction<0 THEN -size_fraction
        ELSE ST_CharactDiam(g) * size_fraction
        END
  ) t1(size)
) t2
$f$;
COMMENT ON FUNCTION ST_Transform_Resilient IS
  'Avoid clothesline-effect. See problem/solution discussed at https://gis.stackexchange.com/q/444441/7505'
;
</syntaxhighlight>
Migrar função para o git oficial!
== Issue 04 - Lib de grades  ==
Desenvolvendo em [[osmc:Metodologia/Algoritmo SQL/Issue04]].
== Issue 05 - Cálculo de dígitos base32 ==
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''. Já havíamos notado isso ao apresentar a [[osmc:Metodologia/Algoritmo_SQL/Lib#Core|Lib Core]].
No caso de geocódigo logístico, que requer cobertura municipal, supondo que o nível da grade adotada para cobertura seja ''Lcover'', podemos obter a aproximação ao metro por um múltiplo de 2.5, que é a quantidade de níveis que se sobe a cada 5 bits do dígito da base32. Partindo de  <math>1=2^{Lmax - Lcover - N \cdot 2.5}</math> obtemos por <math>log_2(1)=0</math> a fórmula <math>N= (Lmax-Lcover)/2.5</math>, onde ''N'' é o número de dígitos depois do primeiro para se chegar ao metro.  Num caso típico a cobertura municipal no Brasil (''Lmax''=20) é de nível ''L7.5'', resultando em ''N''=5, ou seja, com 6 dígitos teremos o metro. Para uma cobertura de resolução menor, ''L7'', o valor já não é exato, ''N''=5.2. O número de dígitos para chegar no metro portanto será <math>Ndig1m = 1+\lceil (Lmax-Lcover)/2.5 \rceil</math>.
<syntaxhighlight lang="sql" style="font-size: 80%;">
CREATE FUNCTION grid_br.logistic_Ndig1m(intlevel_cover int) RETURNS real[] AS $f$
    SELECT array[  Lcover, ceil(Ndig1m), ceil(Ndig1m)-Ndig1m,
          2^(Lmax-Lcover-ceil(Ndig1m)*2.5),
          CASE WHEN ceil(Ndig1m)-Ndig1m=0 THEN NULL ELSE 2^(Lmax-Lcover-floor(Ndig1m)*2.5) END  ]
    FROM (
      SELECT *, (Lmax-Lcover)/2.5 as Ndig1m
      FROM (SELECT 20 as Lmax, intlevel_cover/10.0 as Lcover) t1 
    ) t2
$f$ language SQL IMMUTABLE;
-- gerando a tabela do Brasil:
select x[1] as level_cover, x[2] as Ndigits_for_1m, round(x[4],2) as side_size,
      round(x[5],2) as size_before
from (
  select grid_br.logistic_Ndig1m(intLevel) as x
  from generate_series(40,90,5) t1(intLevel)
) t2;
</syntaxhighlight>
A escolha de nivel ''Lcover'' de cada município no caso do Brasil vai ter o seguinte perfil dado pela função <code>logistic_Ndig1m()</code>. Como o metro é a maior resolução significativa, é interesante não permitir resoluções finais inferiores a meio metro: por exemplo quando a cobertura ótima ''Lcover'' for 4 ou 4.5, usar no máximo 6 dígitos ao invés de 7, já que 2 metros e 1.4 metros são resoluções razoáveis para endereços. Idem ''Lcover''6.5 e 7 etc.
{| class="wikitable"
|+ Número de dígitos base32 para se chegar no metro, conforme ''Lcover'' do município
|-
|''Lcover'' || Ndigits for 1m || ''side_size'' || ''size_before''
|-
|        4 ||              7 ||      0.35 ||        2.00
|-
|      4.5 ||              7 ||      0.25 ||        1.41
|-
|        5 ||              6 ||      1.00 ||           
|-
|      5.5 ||              6 ||      0.71 ||        4.00
|-
|        6 ||              6 ||      0.50 ||        2.83
|-
|      6.5 ||              6 ||      0.35 ||        2.00
|-
|        7 ||              6 ||      0.25 ||        1.41
|-
|      7.5 ||              5 ||      1.00 ||           
|-
|        8 ||              5 ||      0.71 ||        4.00
|-
|      8.5 ||              5 ||      0.50 ||        2.83
|-
|        9 ||              5 ||      0.35 ||        2.00
|}
2 384

edições