Giter Site home page Giter Site logo

ws's People

Contributors

0e1 avatar ppkrauss avatar

Watchers

 avatar  avatar

ws's Issues

Implementar as extencoes de geocodigo para geo URI

Conforme previsto em https://osm.codes/_foundations/2sbide_poster-GeoURI-v2.pdf o protocolo GeoURI foi extendido para comportar geocódigos. Na raiz, geo:{geocodigo}, seriam os geocódigos iniciados por jurisdição, no geo:{tipo}:{geocodigo} os demais tipos.

Agora temos geo:ghs:{codigo} para Geohash e geo:olc:{codigo} para PlusCodes, com todas as funções em https://github.com/osm-codes/WS/blob/main/src/lib-geoUriExt.sql


Consolidando solicitação semelhante em #36:

Usando a Expansão do protocolo GeoURI.
Por exemplo para a resolução de Geohash, https://osm.codes/geo:ghs:d2g69pmx
mas precisa decidir se resolve em célula da grade postal ou se mantém em Geohash. O natural por hora seria grade postal, como já faz com Geo URI.

Reuso das bibliotecas de GGeohash nos diferentes países

O passo-a-passo da implantação de um geocódigo para o país é o seguinte:

  1. Se área do país não for pequena, e for solicitada projeção de área-constante, implementar a projeção adequada.
  2. A partir da projeção e sistema de coordenadas XY adotado, definir a menor caixa contendo o páis.
  3. Se o país vai adotar "Z curve" ok, senão precisa implementar no PostgreSQL o algoritmo de "U curve". Avaliar as duas opções. Ambas satisfazem a demanda por hierarquia espacial. Apenas Hilbert satisfaz requisito de intervalos sempre válidos (os intervalos Z são truncados).
  4. Se o país vai adotar as bases 16h ou 32 ok. No caso da base 32 pode escolher o alfabeto.

As opções que surgem nesse conjunto de decisões deve ser contemplada pela nova biblioteca, ou seja, ela precisa ser generalizada para dar conta das alternativas.

PS: até o momento todos os países preferiram ficar com a curva-Z, não há demanda por Hilbert.

Resolver códigos ISO de 3 letras

Em breve precisaremos resolver códigos ISO de 3 letras: alguns países pequenos, com "código de 2 letras nada haver", já adotam como canônico o de 3 letras, e alguns mais raros ainda não possuem representação de 2 letras. Incluir issue para conferir a situação do ISO 3 letras com https://datahub.io/core/country-codes

Decisão de arquitetura, evitando FDW

Conforme discussão votada e outras fontes, o PostgreSQL vai perder performance com FDW: se estão na mesma máquina, o melhor é uma base só com tudo.

(...) if you are setting up two databases on the same machine you probably want to make two schemas instead - in that case you don't need anything special to query across them.

O uso de optim.vw01full_jurisdiction_geom em modo FDW mostrou o quanto a performance é comprometida.

Correções e adaptações na interface de teste

(aguardar juntar mais requisitos)

  1. Ampliar as opções de base: além de base32 e base16h, incluir base16 (pura) e base16h-int (só níves inteiros).
    image
  2. Caixa de texto (HTML textarea) para acumular todos os geocódigos solicitados, ou cobertura solicitada pela URL.

PS: esta issue é continuação de #13

Performance NGINX comprometida por falsa responsabilidade

Exemplo: BR-SP-SaoPaulo~CD existe e é resolvido pelo endpoint depois de ser validado pelo NGINX, nas BR-SP-SaoPaulo~CE nem sequer foi resolvido, o próprio NGINX descartou: sem maiores explicações, o usuário nem sabe que foi erro de sintaxe.

O retorno de código de erro, sempre que possível, deve ser delegado ao resolvedor de nomes, apenas o "alto nível do endpoint" fica a cargo do NGINX. Com isso, além de ser mais correto para a mensagem de erro, reduzimos a carga de CPU (por complexidade de regex) no NGINX... Portanto a "falsa responsabilidade" será considerado bug.

Três níveis de análise sintática

Analisando src/config.nginx temos:

  1. location: faz apenas o roteamento, delega a responsabilidade dos prefixos.
    Exemplo errado location ~* "^/(urn|geo):lex:([a-z]{2}(;[a-z\.]+)?(;[a-z\.]+)?)\.json(/cover/base16h(1c)?)?$"
    Exemplo certo location ~* "^/(?:urn|geo):lex:[^/]+\.json(?:/cover/base16h(1c)?)?$"
  2. rewrite: implementa apenas a sintaxe necessária e suficiente para a chamada de função.
  3. função: convencionamos que funções de resolução, api.f(), demandam balanço entre a resolução genérica (com CASE para demais funções) e especializada. Novamente, o ideal é não sobrecarregar nem a performance nem a manutenção do NGINX.
    Em casos de funções muito simples e com demanda por alta performance, todavia, pode ser útil "reusar a CPU já gasta pelo NGINX processar a regex", mas são casos raros a serem devidamente justificados através de benchmark da performance.
    PS: O usual em syntatic parsing é essa segmentação passo a passo, daquilo que é 100% certo segmentar.

Sugestão de correção

Casos mais graves:

  • location ~* "^/geo:osmcodes:([A-Z]{2})~([0123456789BCDFGHJKLMNPQRSTUVWXYZ]+)(,[0123456789BCDFGHJKLMNPQRSTUVWXYZ]+){0,}\.json$" para simples location ~* "(?i)^/geo:osmcodes:.+\.json$", e respectivo rewrite "(?i)^/geo:osmcodes:([A-Z]{2})~(.+)\.json$"... Testar diversos casos porque o \.+ pode não se comportar conforme esperado.
  • ... cuidado, se (?i) é ignore-case, não adianta nada no rewrite sem usar ~* antes no location.

Dá issue osm-codes/BR_new#11:

Levar as issues específicas para cada país, por exemplo osm-codes/gridMap-draftPages#82 é exclusiva do Brasil.. Mas antes precisamos de NGINX enxuto como diretiva geral, e algum script de verificação de não-conflito. Ideal os scripts NGINX serem gerados por template Mustache e então o mesmo JSON que alimenta o Mustache-NGINX alimenta também um python de teste.

Dá issue #50:

Definir regrexes em CSV ou JSON. As regexes podem ser de dois tipos: genérica-global (no WS), e específica por sobrescrita (no país).

Cada país precisa do eu próprio gerador de NGINX a partir de CSV ou JSON (local!) que alimentará Mustaches.

Em outra issue já comentamos também que o ideal é cada país ter seu make_conf.yaml para configuração do AFAcodes da jurisdição (incluindo projeção etc.), independente de ter sido automatizada ou não, permite gerar a documentação automatizamente e oferecer maior transparência quanto à definição do AFAcode.

Criar projeto GGeohash

É importante desmembrar ou simplesmente não trazer tudo para WS (WebService), visto que a temática é outra. Podemos manter tudo numa biblioteca só, Generalized-Geohash, ou quebrar em duas, uma só para grade e outra só para geocódigos (hcode). Os geocódigos nominais (prefixo de geocódigo postal) ficam cada qual na sua jurisdição.

Já podemos supor que em todos países a denominação "geocódigo científico" será associada à base16h e sua grade, sem outra opção... E que, quando usada, a base32 será relacionada apenas ao sistema misto (nominal+grade) de geocódigo postal.

Trazer para o novo projeto as respectivas PubLibs, que serão agora libs de um Schema, e demais libs:

Fechar versão 1 da interface interna de GGeohash

A interface funcionava, mas alguns bugs foram introduzidos, precisam ser corrigidos antes de fecharem como v1.0.0.

Proposta do ecossistema v1

Publicar HTML e Javascript mínimos que funcionem em harmonia com os webservices v1.0.0. Isso requer fechamento simultâneo dos padrões e dos repositórios que os implementam.

  1. Fechar a documentação, que expressa os requisitos v1.0.0
  2. fechar WS e GGeohash
  3. fechar o HTML de http://osm.codes/view/

Bugs

  • Botão de "Decode lista", em particular BR, por exemplo HZD,HZF,HZH,HZS,HZ7.
  • Coberturas funcionando e mensagem de erro quando não existem, por exemplo BR-SP-SaoPaulo só cobre metade.
  • Incluir option na URL para carregar municipio WithCover.
  • ... realizar testes de HTML em http://osm.codes/view_beta e ofertar maiores mudanças em http://osm.codes/view2

Requisitos finais da v1.0.x

Atributos a apresentar na popup da célula ou na sua descrição lateral:

  • Jurisdição: base16 separando "jurisdição da grade" e "demais jurisdições cobertas pela célula" (), base32 sempre terá bem definida uma jusdição municipal.
  • População residente sob a célula conforme último censo.

Diferença entre OSM e Natural Earth

Conferir qual está certo e solicitar correções se necessário.

SELECT wikidataid, wikidata_id, iso_a2, j.isolabel_ext, c.iso_n3 
FROM countries c INNER jOIN optim.jurisdiction j ON j.osm_id=c.osm_id
where substr(wikidataid,2)::bigint!=wikidata_id;
wikidataid wikidata_id iso_a2 isolabel_ext iso_n3
Q145 419 PE PE 604
Q23792 219060 PS PS 275
Q34497 192184 SH SH 654
Q133888 408 -99 AU 036

Geometrias sem indice

CREATE INDEX optim_jurisdiction_geom_idx1 ON optim.jurisdiction_geom USING gist (geom);
CREATE INDEX osm_coverage_geom_idx1 ON libosmcodes.coverage USING gist (geom);
CREATE INDEX osm_coverage_geom4326_idx1 ON libosmcodes.coverage USING gist (geom_srid4326);

Conferir todas as demais: todas as geometrias de optim precisam ser otimizadas com indices.


CUIDADO, DROP INDEX tem pegadinha em tabela com schema! Precisa desse SET mágico que o Guia não fala, e deixa totalmente não-amigável o SQL.

SET search_path ="optim";
  DROP INDEX optim_jurisdiction_geom_idx1; -- demora!
SET search_path ="libosmcodes";
  drop index osm_jurisdiction_geom4326;
  drop index osm_jurisdiction_geom;

Revisar e refatorar osm_city

A tabela osm_city da base DL03t_main pode ser renomeada para optim.jurisdiction_geom para integrar os cores A4A e OSMC.

Agora possui tanto cidades como países (dados da tabela countries do Natural Earth).

Aplicar acrescimo de info na optim.jurisdiction

Algumas decisões sobre escolha de grade dependem de parâmetros métricos da geometria da jurisdição, e estes podem ficar em cache (info), tanto para reuso nesses cálculos como por seu valor informativo para o usuário final.

As grandezas relevantes são descritas pelos comments (ver com \d+ no pgsql):

Column Type Storage Description
area_km2 integer plain Area in square quilometers.
area_sr double precision plain Area in spheroradians.
side_estim_km double precision plain Estimating the side size of an equivalent-area square, in quilometers.
side_estim_deg double precision plain Estimating the side size of an equivalent-area square, in degrees.
fat_deg_m numeric main Average degree per meter convertion factor at the points of this area.
elongation_factor numeric main Factor between sides of an estimated rectangular box fitting the simplified geometry.

Implementação

O script abaixo precisa ser incluso nos procedimentos padrão de ingestão.

DROP VIEW IF EXISTS optim.vw03prepare_jurisdiction_metrics1;
CREATE VIEW optim.vw03prepare_jurisdiction_metrics1 AS
 SELECT osm_id, isolabel_ext,   round(area_m/1000000.0)::int as area_km2,
       round( area_sr, 5)::float as area_sr,
       round( SQRT(area_m)/1000.0, 1)::float as side_estim_km,
       round( SQRT(area_sr), 4)::float       as side_estim_deg,
       round( SQRT(area_sr)/SQRT(area_m), 7 ) as fat_deg_m
 FROM (
   SELECT *, st_area(geom,true) area_m,
                 st_area(geom) area_sr
   FROM optim.vw01full_jurisdiction_geom
   WHERE geom IS NOT NULL
 ) t0
;
comment on view optim.vw03prepare_jurisdiction_metrics1 IS 'Prepare the standard geometry metrics.';
comment on column optim.vw03prepare_jurisdiction_metrics1.area_sr IS 'Area in spheroradians.';
comment on column optim.vw03prepare_jurisdiction_metrics1.side_estim_km IS 'Estimating the side size of an equivalent-area square, in quilometers.';
comment on column optim.vw03prepare_jurisdiction_metrics1.side_estim_deg IS 'Estimating the side size of an equivalent-area square, in degrees.';
comment on column optim.vw03prepare_jurisdiction_metrics1.fat_deg_m IS 'Average degree per meter convertion factor at the points of this area.';

-- Perigo!
UPDATE  optim.jurisdiction
SET info = COALESCE (info,'{}'::JSONB) || (to_jsonb(t) - 'osm_id')
FROM   ( 
  SELECT osm_id, area_km2, area_sr, side_estim_km, side_estim_deg, fat_deg_m
   FROM optim.vw03prepare_jurisdiction_metrics1 
) t
WHERE t.osm_id=jurisdiction.osm_id
;  -- UPDATE 7133

Shape sizes

Tradicionalmente usamos uma "BBOX livre" (independente grade ou do sistema de coordenadas) para avaliar se a box será mais quadrada ou retangular. Todavia a BBOX será muito sensivel a geometrias "com braços" ou pequenos trechos alingados, não-representativos da área total do polígono. Um forma menos sensível de estimar o tamanho dos lados de um retângulo de área equivalente é através da função shapedescr_sizes, definida em https://gist.github.com/ppKrauss/3810651

As aplicações são diveras, por exemplo para avaliar o formato de quadras retangulares, ou estimar o grau de "alongamento" de polígonos em geral, Nos algoritmos de grade usaremos o fator de alongamento como recurso para decidir se a jurisdição precisa ou não fazer uso de gecódigos indexados.

DROP VIEW IF EXISTS optim.vw04prepare_jurisdiction_shapemetrics;
CREATE VIEW optim.vw04prepare_jurisdiction_shapemetrics AS
SELECT *, round( (rectang_factor_deg + 1.5*elongation_factor_deg)/2.5 , 2)::float AS elong_deg_mixfactor
FROM (
 SELECT osm_id, isolabel_ext,
       round(s[1]/fat_deg_m)/1000 as rectang_L_km,
       round(s[2]/fat_deg_m)/1000 as rectang_H_km,
       CASE 
          WHEN s[6]=0 THEN (round( ((s[1]-s[2])/side_estim_deg)/fat_deg_m )/1000.0)::int
          ELSE -1
       END AS elongation_factor_km,
      CASE
          WHEN s[6]=0 THEN round( (s[1]-s[2]) / side_estim_deg , 2)::float
          ELSE -1
       END AS elongation_factor_deg,
      round( 0.95 + (diaglen_deg - side_estim_deg)/side_estim_deg , 3)::float as rectang_factor_deg
 FROM (
   SELECT  *, (info->'side_estim_deg')::float AS side_estim_deg,
            (info->'side_estim_km')::float  AS side_estim_km,
             (info->'fat_deg_m')::float AS fat_deg_m,
             shapedescr_sizes( ST_SimplifyPreserveTopology(geom, (info->'side_estim_deg')::float/350.0) ) AS s,
                   -- ideal usar ao inves de side_estim a media (diaglen_deg+side_estim_deg)/2.0 
             ST_Length( ST_BoundingDiagonal(geom,true) ) as diaglen_deg
  FROM optim.vw01full_jurisdiction_geom
  WHERE geom is not null  AND info?'side_estim_deg'
 ) t1
) t2;

-- check:
SELECT percentile_disc( array[0.2, 0.5, 0.8] ) WITHIN GROUP (ORDER BY elongation_factor_deg) as pctl_elongation_factor_deg ,
       percentile_disc( array[0.2, 0.5, 0.8] ) WITHIN GROUP (ORDER BY rectang_factor_deg) as pctl_rectang_factor_deg,
       percentile_disc( array[0.2, 0.5, 0.8] ) WITHIN GROUP (ORDER BY elong_deg_mixfactor) as pctl_mix
FROM optim.vw04prepare_jurisdiction_shapemetrics
WHERE isolabel_ext LIKE 'CO-%-%' AND  elongation_factor_deg>0
;  --  shape={1.5,2.02,2.63}      |    pctl_rectang={1.858,2.017,2.255}     |   pctl_mix={1.65,2.02,2.47}
-- Estamos adotando o mix, deu mais certo.

----- Perigo!
UPDATE  optim.jurisdiction
SET info = COALESCE (info,'{}'::JSONB) || jsonb_build_object('elongation_factor',t.elong_deg_mixfactor)
FROM  optim.vw04prepare_jurisdiction_shapemetrics t
WHERE t.osm_id=jurisdiction.osm_id  AND t.elongation_factor_deg>0
;  -- UPDATE 7115

Sugestão a testar:

  • Encaixar jurisdições pequenas na grade sempre que (info->'elongation_factor')::float < 1.7
  • Usar geocódigo indexado nas jurisdições com (info->'elongation_factor')::float >=2.5, exceto se for muito pequena
  • Nas demais avaliar melhor qual o caso (indexar ou encaixar). Talvez visulizando no QGIS com o seu nome ou ID, e colorindo com elongation_factor.

image

image

image

image

Identificador de célula na sua representação interna 64 bits

Identificadores de célula são universais, valem para qualquer país, pois justamente iniciam com os bits do código do país... Existe além da representação universal de células, a representação de "prefixos de cobertura", que não são identficadores de célula exatamente, mas indexadores para o algoritmo de encode/decode de códigos curtos e coberturas L0.

Identificador de célula universal

Como todo sistema de Generalized Geohash se base em dividir quadrados em quatro, todos os "blocos de bit" da célula precisam ser compatíveis com base4... Com algumas exceções. Blocos do identificafor de 64 bits, concatenados 3 blocos: <$lixo', $pais, $L0, $celula_from_L0`>

  • `$lixo': sinal ou coisa do tipo.
  • $pais: código ISO, supondo 1 a 999, mas codificados em 8 bits, tudo bem.
  • $L0$celula_from_L0: 4 bits (dígito base16) ou 5 bits (país optou priorizar base32) de L0 com o resto... Sim, não precisa L0 ser múltiplo de 4 mas precisa encaixar certo com o restante, já que só completam 10 bits a cada 2 dígitos base32 (e 10 é multiplo de 2 tudo bem).

prefixos de cobertura

Ver issue já resolvida.

São apenas dois

WS for OSM

OSM ID of relations, ways and nodes. Examples:

osm.codes can redirect from abbreviated 1-letter form: relation/296621=r/296621; way/498698840=w/498698840; node/4900702088=n/4900702088.

Proposed endpoint: https://osm.codes/{letter}{digits}.

NGINX locations expressions:

  • [rR]?([0-9]+) to https://www.openstreetmap.org/relation/$1
  • [wW]([0-9]+) to https://www.openstreetmap.org/way/$1
  • [nN]([0-9]+) to https://www.openstreetmap.org/node/$1

See https://stackoverflow.com/q/27406188/287948 for non-redundant. Alternative:

        location ~ ^/?([RrWwNn]?)([0-9]+)$ {
                set $totype relation;
                set $ck $1;
                if ($ck = 'w') { set $totype way; }
                if ($ck = 'W') { set $totype way; }
                if ($ck = 'n') { set $totype node; }
                if ($ck = 'N') { set $totype node; }
                return 301  https://www.openstreetmap.org/$totype/$2;
        }

Typical use: as alternative URL for https://www.wikidata.org/wiki/Property:P402 and others that need one-code (with no / or - separator). Default (with no letter) redirects to relation.


Tests:

Pending NGINX problem, see https://stackoverflow.com/q/75430954/287948

Mar territorial na cobertura L0

Na interface e nos recortes se faz necessária a adição do mar territorial. O polígono do "jurisdição marítima" pode ser obtido da subtração da jurisdição completa pela jurisdição continental. É importante que os polígonos recortados da grade L0 façam uso desse recorte. Sem isso a representação da grade recortada ainda estará errada (bug).

Exemplo na Colômbia:

image

NOTA: em geral o mar territorial está sob jurisdição da Marinha, portanto seria federal... Mas cada país pode ter a sua norma e resultar em jurisdições municipais de mar territorial. **Em caso de jurisdição federal não deve entrar no código postal (que é inerentente municipal), apenas na grade completa.

Operaçoes de vizinhança

[Futuro] Além das funções de encode/decode as bibliotecas de geocódigos em geral são munidas de operações de vizinhanha. No caso da curva de Morton, uma das mais importantes é a checagem do entorno.

Entorno imediato

Na biblioteca Javascript de movable-type.co.uk/scripts/geohash temos a função neighbours(geohash) que retorna os 8 vizinhos doi Geohash do centro.

image

Tipicamente no SQL faremos SELECT * FROM t WHERE geocode IN neighbours(ref_geocode)

Outras operações

Existem desde as bibliotecas mais simples às mais refinadas. Exemplos extremos:

Defaults dinâmicos

Documentar o complemento: em uma outra tabela (a de-para) existe uma extensão OsmCodes (convenção ainda arbitrária já que não é oficial do país) para isoLabel_ext, que são os quadrantes da cidade, C, N, S, etc. Em muitos casos vamos incluir esse 4o nivel de jurisdição isoLabel

Outra questão: o que o usuário quer dizer com "CO-ANT-Itagui", seria o polígono da cidade inteira ou o default, "CO-ANT-Itagui-C" ?
SOLUCAO: quando houver algo mais, como "CO-ANT-Itagui~123" ou apenas "CO-ANT-Itagui~", o canônico assoaciado será "CO-ANT-Itagui-C". Quando for só o nome, "CO-ANT-Itagui", então é a própria jurisdição.

E aí passamos a uma nova issue: os "defaults dinâmicos". Não precisa ser o "-C", cada jurisdição subdividida terá seu flag no banco de dados, coluna "is_subdiv_default boolean", indicando quem é default.

Tratamento de jurisdições e NGINX enxuto

Levar as issues específicas para cada país, por exemplo osm-codes/gridMap-draftPages#82 é exclusiva do Brasil.. Mas antes precisamos de NGINX enxuto como diretiva geral, e algum script de verificação de não-conflito. Ideal os scripts NGINX serem gerados por template Mustache e então o mesmo JSON que alimenta o Mustache-NGINX alimenta também um python de teste.

Dá issue osm-codes/BR_new#11:

Definir regrexes em CSV ou JSON. As regexes podem ser de dois tipos: genérica-global (no WS), e específica por sobrescrita (no país).

Cada país precisa do eu próprio gerador de NGINX a partir de CSV ou JSON (local!) que alimentará Mustaches.

Número mínimo de digitos que podem ser substituidos

Automatizar o cálculo de número mínimo de dígitos que o nome da jurisdição pode substituir (ex. Medelin só 1), e o número de dígitos da subdivisão direcional (Norte/Sul/etc), e encontrar quais são elas.

rodar info update nas novas jurisdições

Por exemplo está com info NULL, enquanto Campinas está completo:

select isolabel_ext, info->'elongation_factor' e
from optim.jurisdiction where isolabel_ext IN ('UY-RV-Masoller','BR-SP-Campinas') ;
-- isolabel_ext  | e
-- --------------+----------
-- BR-SP-Campinas | 2.42
-- UY-RV-Masoller | 

URGENTE documentar o workflow e não fazer ingestão sem garantir o processo completo.

PS: isso compromete a amostragem de teste e as heurísticas de geração de SVG.

Novo sistema de definição de cobertura

É necessário generalizar e otimizar o sistema que estamos introduzindo com a tabela libgrid_co.de_para:

https://github.com/osm-codes/CO_new/blob/main/src/gridLib.sql#L303

  1. Separar dados terminológicos dos dados essenciais, já está previsto o uso de https://github.com/AddressForAll/geoterm

  2. Usar bigint positivo composto de 4 partes:

    2.1. Prefixo jurisd_base_id com 10 ou mais bits.

    2.2. Bits (3) para distinção de tipo de cobertura (00X cobertura do país, 01X cobertura municipal principal, 10X cobertura municipal com overlap na primária, X 0 para cobertura full e 1 para cobertura parcial demandando geometria de exclusão).

    2.3. Bits (14) para o contador de jurisdições municipais (adaptado ou direto do jurisd_local_id oficial)

    2.4. Bits válidos restantes para o sufixo com a representação bitstring da célula de cobertura conforme fixada pelo país.

  3. Avaliar se muda performance deixando geometrias na mesma tabela ou em tabela separada. Seriam 2 geometrias, a de baixa (ex. submetida a ST_Simplify) e a de alta resolução, lembrando que "tipo full" dispensa geometria.

Resta esboçar os algoritmos de resolução (decisão de qual jurisdição usar) e endode/decode, para confirmar se a estrutura de dados proposta garante maior performance.

Discriminação da jurisdição nas coberturas L0

Exemplo da fronteira Brasil-Colômbia:
image

Alternativas para o algoritmo de discriminação, ou seja, para decidir se o encode será através da grade de um país ou outro.

Discriminação de país por força bruta

Faz uso da geometria do país inteiro: dado um ponto, determina em qual país está contido. Usa simples WHERE country_geom && pt_geom AND ST_CONTAINS(country_geom,pt_geom).

Vantagens:

  • mais simples de implementar;
  • funciona sem maior impacto de performance enquanto poucos países e poucas operações.

Força bruta distribuiída

A busca é feita por coberturas, cada uma delas contém a interseção entre país e a célula L0, de modo que podemos fazer a mesma busca WHERE country_geom && pt_geom AND ST_CONTAINS(country_geom,pt_geom). Neste caso o PostgreSQL pode de fato ter menos trabalho, fica só com a BBOX da primeira comparação quando é totalmente distinto dos demais... Como as grades L0 possuem origem em uma geometria do espaço projetado, não possuirá uma representação tão simples. Por isso a performance ainda será baixa e precisa ser comparada com o caso anterior, talvez não compense.

PS: células de cobertura menores reduzem o índice de sobreposição. A sugestão é que, tal como nas coberturas municipais, as de nível zero também ofereçam discriminação... Se isso realmente representa otimização, há que se levar em conta nas decisões individuais de cada país, não seria mais uma decisão totalmente neutra.

Algoritmo da busca por prefixo Geohash

A conversão de coordenadas LatLong em Geohash de 1 ou 2 bytes é rápida, e é tudo o que precisamos para montar um algoritmo similar ao "força bruta distribuída", porém agora orientado a uma grade independente da projeção. Requer duas partes:

  1. idenxar os países por suas coberturas máximas, distinguindo as coberturas totalmente interiores de goberturas contendo fronteira.
  2. indexar o ponto (candidato a encode) e realizar a busca por geohash que o contem: se for interior, está resolvido, se for fronteira vai exigir a representação geométrica e comparação vetorial, mas usando geometrias recortadas e menores.

Idealmente pode seria otimizado para indicar a célula L0 onde se de o match, mas com probabilidade não muito maior do que 50%.

Testar ou adaptar o SP-Gist

Existe alguma implementação de Quadree, https://doxygen.postgresql.org/spgquadtreeproc_8c.html
aparentemente aquela descrita em https://www.cs.purdue.edu/spgist/publications.xml

Conversão de grades e outros mosaicos do país

Criar um método geral para levar informações para a grade, ou seja, para oferecer na grade 1 Kim de cada país um resumo de informações úteis da célula: população estimada, temperatura média anual, insolação média anual, número de endereços no addressForAll, número de vias que cruzam a célula, rótulos das cidades, etc.

Conforme #23 podemos usar RT_ST_AsRaster no nosso servidor.
A forma mais simples e "leve" para levar os atributos de um layer para a grade cienífica, aparentemente, é usando os recursos raster do PostGIS.

Esboço metodológico da conversão

Testar e aprimorar, ou oferecer alternativas para comparar performance.

  1. Eleger "tamanho de bloco", pois a conversão se dará por blocos, não dá para rodar o país inteiro de uma vez.

  2. Projeta num raster de alta resolução ... https://postgis.net/docs/RT_ST_AsRaster.html

  3. Devolve o raster para um polígono obtendo o valor por célula ... http://www.postgis.net/docs/RT_ST_SummaryStats.html

Esboço metodológico otimização

A cada layer (por exemplo mosaico de jurisdições) ao invés de armazenar sistematicamente cada valor em cada célula, agregar valores iguais (cobertura uniforme) na célula-mãe. NULLs ou grandes areas homogêneas se beneficiarão desse recurso. O valor da célula-mãe continua sendo tão exato quanto a união das filhas. É a estratégia quadtree.

Convenção:

CREATE TABLE osmc.jurisdiction_grid_info (
gid bigint NOT NULL PRIMARY KEY,  -- célula iniciada pelo ID de 16 bits da jurisdição, sobram 48 bits para a célula
info JSONb NOT NULL,   -- key-value onde key é um rótulo curto iniciado por "_" quando for cache das filhas
is_info_root boolean         -- indica que info contém alguma informação bruta, não-cache.
);

o gid perde 1 bit de sinal e 1 bit de "hidden bit" para garantir a hierarquia, mas como a jurisdição só necessita da ordem de 10 bits, podemos incluir esses dois como valores constantes da máscara. Em seguida todos os bits são da célula.

No caso do Brasil são 40 níveis, de modo que 40 bits são efetivamente utilizáveis, mas na prática nos limitaremos ao nível 10, ou seja, 20 bits, correspondendo às células de 1024 metros de lado.

Os valores info precisam ser baseados em rótulos curtos para não ocupar muito espaço, por exemplo a população contida na célula seria pop, ou, em caso de sumarização das filhas, _pop. Quando uma célula menor não tem o valor deve-se exaurir a busca pelas células mães: essa "economia de espaço em disco" pode ser inúfil quando a célula já existe, mas pode economizar milhares de registros quando o número de layers com informação homogênea for grande. Aos poucos, se houver recurso em disco, a estratégia poderá ser dispensada... Ou não, otimizamos a busca por células-mãe. Uma das estratégias para reduzir esse custo é armazenar dados apenas em níveis válidos da base 16, reduzindo para 1/4 o número de verificações. No caso de 1 kim, que tem 7 dígitos (mas o primeiro é degenerado em 2) seriam 5 buscas até a grade de cobertura, que em geral não é root.

Implementar algoritmo de cobertura otimizada do município

Com essa estratégia alguns municípios, tipicamente os alongados, terão o "primeiro dígito recodificado" depois do prefixo nominal. Exemplificando com Bogotá, que de outro modo não gastaria 1 ou dígitos a mais.

image

A "cobertura Bogotá" é fornada pelo conjunto de todas as células de um certo nível L (ou número de dígitos D) com interseção na geometria da cidade. Na ilustração elas correspondem às células com alguma parte em rosa.

O algoritmo que decide quais níveis D e D+1 usar para a cobertura, todavia, pode não ser tão simples. Aqui uma sugestão:

  1. Conferir a cobertura da grade maior ou igual side_estim (Bogota tem 40.6 km), que nesse caso é a cobertura com células com lado médio de 46.3 km. O resultado é uma cobertura de 6 células, ajustável para 4: HX, HW, HT e HS.
    Então podemos dizer que existe uma cobertura em D dígitos, e, como todas as células possuem prefixo H, podemos dizer que "no nível D o nome seria traduzido para H", se nada de melhor for conseguido.
    PS1: pode acontecer de serem necessárias mais células de cobertura, o limite sempre será 32.
    PS2: uma alternativa à análise geométrica da cobertura (ver funções geohash_cover_list() e outras) é obter uma amostragem de pontos e identificar o prefixo comum com hcodes_common_prefix... A desvantagem é que o risco de falhar quando a grade está em ponto de descontinuidade e só uma pequena porção passa por lá (e não seria amostrada). O algoritmo de cobertura por outro lado já foi bem testado e é confiável.

  2. Como 4 é muito pouco (a checagem heurística pode ser 4 < 10), buscamos recodificar: quais células da cobertura de D dígitos devem ter sua subgrade adotada como cobertura?
    A célula que contém o o ponto fornecido pela Wikidata como referência para o centro urbano da cidade é um bom ponto de partida (outra opção é a contagem de endereços em cada célula). A célula é HX, e sua subgrade HX* apresenta como cobertura HX1, HX4, HX5, HXJ, HX6, HX7, HXL, ... HXU, totalizando 12 células com interseção em Bogotá.
    Das 4 células H*, uma, HX, foi expandida para 12 células, totalizando 12+3=15 células... Ainda é pouco.

    2.1. Repetimos o processo enquanto o total na cobertura não exceder 31 (32 menos um de reserva). Claro, se terminar, como já passou dos 10 diremos que "está bom". Se não terminar significa que algumas células da cobertura H* vão ficar: é o que ocorreu, depois de incluirmos HW ainda sombrou, mas com HT já não daria. Foram adicionadas HW1, HW3, HW4, HW5, HW6, HW7, ..., HWU, ou seja mais 12 células. Agora o total é 15-1+12 = 26 células de cobertura.
    PS: esse total de 26 células poderia ser "ajustado" para 22 ou 24... Uma das decisões de projeto é permitir ou não esse segundo nível de ajuste. Como dois já foram comprometidos no ajuste de HT e HS não seria probelma. Com essa decisão em mãos saberemos se dá ou não para recodificar HT (e avaliar HMP para ser ajustado para grade menor).

Lembrete:

  • Cidades pequenas (no exemplo da Colômbia cidades até 5 Km de diâmetro) dispensam análise e cobertura, precisam eventualmente ajuste.
  • Cidades maiores (e/ou alongadas) podem ter pelo menos a sua área urbana com compressão otimizada através do algortimo da cobertura.

O ajuste e a recodificação em mais detalhes:

  • Ajustar: criam-se entradas na "tabela de-para" das células órfans (ilustradas em amarelo).
    Por exemplo a posição real HMP vai ser simbolizada por HTP, ou seja, conversão HTPHMP contextualizado; da mesma forma as outras 5 células, HSNHLN, HSPHLP, HSQHLQ, HSRHLR, HSXHLX.
    O ajuste não reduz o número de dígitos, mas reduz a quantidade de geocódigos consumidos, permitindo ou o encaixe direto (ver Sabaneta abaixo) ou a economia necessária para mais itens serem recodificados.

  • Recodificar: Por exemplo HS=0, HT=1, HW5=3, HW4=4, HW1=5, HW7=6, HW6=7, HW3=8`, ... Mas seguindo a ordem dos IDs, de modo a ser facilmente reprodutivel. No exemplo a cobertura de Bogotá requer 25 células, restando ainda uma reserva de 7 células para eventuais modificações territoriais.

PS: reparar que tanto no geocódigo curto ajustado como no curto recodificado perdemos a compatibilidade com o geocódigo absoluto nesse primeiro dígito depois do ~.


Ilustrando a recodificação

Ilustrando o algoritmo com Geohashes e usando BR-SP-SaoPaulo:

image

Ilustrando o ajuste

Ilustrando o "ajuste" com CO-ANT-Sabaneta, mas nesse caso não há necessidade de recodificar a cobertura.

Por exemplo CO-ANT-Sabaneta~4 é um primeiro dígito natural, equivalente ao geocódigo absoluto CO~8UR4. Foi escolhido entre os demais por ter maior área de interseção. Por outro lado CO-ANT-Sabaneta~Q precisa ser ajustado para CO~8UPQ, o prefixo ajustado muda.

Nota sobre a sintaxe do código. Por haver essa perda de compatibilidade podemos convencionar que o primeiro dígíto depois do ~ no geocódigo curto é especial, e separa-lo sempre por um ponto. Exemplos CO-Sabaneta~4.123, CO-Sabaneta~Q.456. Outra estratégia seria isolar com outra sintaxe, já que pontos seriam livres. Ex. CO-Sabaneta~4~123, CO-Sabaneta~Q~456. A rigor não queremos juntar à parte nominal (ex. CO-Sabaneta-4~123) pois não é uma subjurisdição.

image

image

Quanto menor o polígono maior a probabilidade de encaixe na célula... Mas qual o limite de ocupação do polígono? Vale a pena testar por exemplo com um polígono que ocupa 80% da área da célula?

A experiência abaixo mostra que talvez 90% seja realmente inútil, mas a área de CO-CAU-Florencia, de 57 km2, cobriria 85% dos 67 km2 da célula, e foi por pouco que não deu certo:

image

Comparando com Sabaneta, percebemos outro aspecto, sobre os pedaços (subcélulas) ajustados:

  • no caso de Sabaneta cada pedaço ajustado tem sua própria subcélula.
    Exemplo: a subgrade de CO-Sabaneta~P conteria apenas CO-8UPP*, assim como CO-Sabaneta~R apenas CO-8UPR*. A exclusão também funciona, o absoluto CO-8UPRM não faz parte de Sabaneta, assim como CO-Sabaneta~RM não é válido.

  • no caso de Florencia alguns pedaços ajustados compartilhariam sua subcélula com outros... Isso não criaria um conflito de referência?
    Vejamos a célula Florencia~P que estaria mapeando CO-NM5P e CO-NM4P para o mesmo P... E as subcélulas, como por exemplo, Florencia~P2, não teriam mais garantia de correspondência com o código absoluto. A exclusão deixa de funcionar.

Trata-se de uma decisão de projeto: permitir "apenas cada pedaço ajustado a sua própria subcélula" ou não. Quando não, o algoritmo será mais complexo e exclusão (e portanto a sua correspondência com código absoluto) deixa de funcionar.

Subdominio em A ou CNAME? fazer consciente

Segundo https://support.dnsimple.com/articles/differences-between-a-cname-alias-url/

General rules: Use an A record if you manage which IP addresses are assigned to a particular machine, or if the IP are fixed (this is the most common case). Use a CNAME record if you want to alias one name to another name, and you don't need other records (such as MX records for emails) for the same name.

Temos usado a maioria como CNAME, mas o default da Digital Ocean é A, e alguns casos fizemos com A. Parece que a performance vai ser (desprezivelmente) melhor com A, mas supondo que o IP é de fato o ultimo passo.

Homologar resultados do novo algoritmo de cobertura-base

Está disponível para o ambiente de teste, https://wiki.addressforall.org/doc/osmc:Conven%C3%A7%C3%B5es/Coberturas_municipais/Algoritmos

  1. Conferir do "L 1 km" ao "L 185 km"
  2. Conferir se os geocódigos do ''click 1 m'' resulta no número de dígitos esperados, e se isso para o ser humano está bom (para área rual que na prática usa células de 10m a 30 m de lado).
  3. Avaliar se caberia um overlay urbano (em cidades onde o urbano representa 50% ou mais da área total pode não fazer sentido overlay), e indicar se sim ou não. Se sim testar na amostra de overlay oferecida, que precisa estar sobre o centro urbano.
  4. Valem mais uns 3 ou 4 municípios de amostra
  5. acrescentar mais alguma observação sobre os resultados (geocódigos logísticos e seu tamanho em número de dígitos)

Se homologado, passaremos do Teste para a Produção.

Relatórios de suspeita de falha nos novos core-datasets

Os core-datasets do OSMcodes são aqueles que configuram cada jurisdição e estruturam os demais dados. Atualmente residem no schema optim.

Cada vez que atualizamos, reconfiguramos ou inserimos uma nova jurisdição, precisamos conferir se não fizemos alguma bobagem, ou seja, precisamos validar os novos core-datasets. Certos algorimos de validação ajudam a filtrar dados incorretos, outros ajudam apenas a destacar suspeitas de falha:

  • filtros de validação: depois de carregados os dados em tabela intermediária, o próprio INSERT pode fazer essa validação. Um bom exemplo é o INSERT de novas geometrias no Digital-guard, através da função any_load(), que armazena em separado os registros rejeitados e indica o erro detectado.

  • relatórios de validação: heurísticas que permitem destacar suspeitas de falha, e alertar sobre erros menores.

Implementação

Criar uma VIEW para cada tipo de "relatório de validação" e, no caso de filtros, uma função de teste para cada tipo.

Validação das abrevuações de jurisdição

.. reduzir o nome a um nome Lex, as letras da abreviação precisam ser letras do nome Lex, e estar na mesma ordem...

Validação dos conjuntos-cobertura de municípios

... o número de células não pode exceder a base (32 ou 16); a interseção entre município e células precisa ter mesma área que o municíooo. Ver também #33

Validação das geometrias de jurisdições

.. No caso do Uruguai não é obrigatório que todo estado seja um mosaico de municípios...

Tabelas Jurisdiction e códigos associados

Originalmente as jurisdições vinham de datasets controlados como http://datasets.ok.org.br/city-codes
Agora cabe o controle em OSM-codes (não seria Digital-guard pois fazemos uso de multiplas fontes - aí sim cada fonte com seu guard).

Os datasets de jurisdiction podem ser construídos com base em

  • Consultas padronizadas Wikidata: retorna o primeiro esqueleto dos dados.
  • Consultas overpass OSM: retorna dados de confirmação e complementos.
  • Datasets oficiais de cada país: IBGE no caso BR e seus equivalentes a cada país
  • Datasets ISO.

A consolidação das fontes é feita pelo PostgreSQL conforme heurística de confiabilidade. Relatórios estatísticos podem sugerir demandas por revisão humana.

Problema das abreviações

Não existem fontes para a maior parte das abreviações, serão construídas por iniciativa da OSMcodes. Requer amadurecimento com a comunidade e legitimação com órgãos governamentais, longo processo, por isso demanda por tabelas de controle. Ver também https://github.com/AddressForAll/geoterm

CREATE TABLE optim.jurisdiction_abbrev_ref (
 abbrevref_id int PRIMARY KEY,
 name text not null,
 info jsonb not null
);

CREATE TABLE optim.jurisdiction_abbrev_option (
 selected boolean not null default false,
 abbrevref_id int not null REFERENCES optim.jurisdiction_abbrev_ref,
 isolabel_ext text not null,
 abbrev text not null,
 insert_date date not null default now(),
 PRIMARY KEY (abbrevref_id,isolabel_ext,insert_date)
);

Servindo imagens

Podemos gerar imagens pesadas no filesystem do server e realizar processamento on-the-fly, de imagens leves. O caso típico seria utilizando PNG com transparência, que pode ser mais simples e mais leve do que GeoJSON em aplicações que não exisgem maior precisão. O problema em geral vai ser a escolha de um fundo adequado... Em ilustrações didáticas mostrando as variações de uso pode ser útil, pois o fundo é fixo.

Implementação

Conforme guia PostgREST e dicas PostGIS e guia RT_ST_AsRaster, podemos servir imagens!

CREATE EXTENSION IF NOT EXISTS postgis_raster;
SET postgis.gdal_enabled_drivers = 'ENABLE_ALL'; -- para PNG e JPG outputs

create table api.lixo as 
SELECT 1 as gid, ST_AsPNG( ST_AsRaster(
  ST_Buffer(ST_GeomFromText('POLYGON((-30 40, -20 30, -25 20, -23 10, -30 40))', 4326), 50),
   100,       -- width 
   100,       -- height
   '8BUI',    -- pixeltype
   118        -- value
)  );
curl "http://osm.codes/_sql/lixo?select=st_aspng" -H "Accept: application/octet-stream" > lixo.png
# Opcional: sobrepor imagem geográfica com fundo branco ou tile system
convert background_tile.png lixo.png -append /tmp/result-tileLixo.png

NGINX and HTML

        location /_sql.img {
          rewrite /_sql.bin/(.*) /$1 break;

          proxy_set_header Accept 'application/octet-stream';
          proxy_pass http://127.0.0.1:3103;
        }

Falta decidir se queremos _sql.bin ou _sql.img.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>title</title>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>
  <body>
    <h1>Imagem gerada on-fly!</h1>
     <p>Gerado por <tt>http://osm.codes/_sql.img/lixo?select=st_aspng</tt>.</p>
     <img src="http://osm.codes/_sql.img/lixo?select=st_aspng">
  </body>
</html>

Resolução de geocódigos oficiais de CV e EI

Dois casos emblemáticos

Cabo Verde (CV) oferece dados abertos em seu https://codigopostal.cv de modo que, apesar de não oferecerem resolução por grade, por ser um país pequeno pode ter seu polígonos incorporados ao nosso banco de dados. Historicamente foi o primeiro país a pleitear e quase oficializar o uso do PlusCodes, posteriormente desistindo por considerar a resolução dos nomes de local fechada, e sem respeitar os padrões governamentais.

A Irlanda (EI) foi talvez o primeiro país a oferecer um "código postal de grão-fino", que leva até a porta de casa (código do lote). Ver Eircode na Wikipedia. Infelizmente não é um algoritmo ou banco de dados aberto. Durante a "licitação pública" várias alternativas foram ofertadas, mas nenhuma delas parecia plenamente eficiente e bem fundamentada. O histórico tumultuado sugere a necessidade prévia de um padrão de referência, como o DNGS.

Resolução

  • Endponts /CV-$code, ex. CV-5116-002; e /EI-$code, ex. EI-D02.AF30.
  • Página de esclarecimento: por hora página PHP com esclarecimentos e iframe ou link para a resolução final, dentro da infraestrutura oficial de resolução. No caso de CV podemos vir a oferecer os polígonos. No caso de EI, parece que não recebem links, a busca precisa partir da interface própria.
  • Redirecionamento: em ambos os casos, instruir, ilustrar e oferecer o link para a página oficial.

Resolução dos polígonos

Apenas os polígonos podem ser resolvidos, em ambos os casos não há como "chegar na porta de casa". Resolução parcial ou total do geocódigo:

  • parcial no caso do Eircode, onde os 3 primeiros dígitos podem ser resolvidos e/ou validados. Ver List of Eircode routing areas in Ireland, talvez já definidos no OSM.
  • total no caso de CV. Aparentemente são dados abertos, então pode-se manter em banco de dados OSMcodes.

Referências

CV, evidências da tentativa de usar PlusCodes:

CV, evidências da data de inicio do Novo Código Postal:

EI, evidências do uso vigente:

EI, críticas:


Fonte da box de busca de Eircode:

<form role="form" ng-submit="searchForm.$valid &amp;&amp; searchEircode()" name="searchForm" novalidate="" class="ng-pristine ng-invalid ng-invalid-required ng-valid-minlength">
      <div class="input-group">
        <input placeholder="Enter a full address or Eircode" class="form-control ng-pristine ng-invalid ng-invalid-required ng-valid-minlength ng-touched" ng-class="{formcontrolRequired:searchForm.$submitted &amp;&amp; !searchForm.$valid || InvalidEircode}" ng-model="searchQuery" name="searchQuery" required="" autocomplete="off" spellcheck="false" typeahead="options.displayName for options in getAutoCompleteAddresses($viewValue)" typeahead-on-select="onSelect($item, $model, $label)" typeahead-focus-first="true" focus="" ng-minlength="3" search-bar="" aria-autocomplete="list" aria-expanded="false" aria-owns="typeahead-76-2900"><ul class="dropdown-menu ng-isolate-scope ng-hide" ng-show="isOpen()" ng-style="{top: position.top+'px', left: position.left+'px'}" style="display: block;;display: block;" role="listbox" aria-hidden="true" typeahead-popup="" id="typeahead-76-2900" matches="matches" active="activeIdx" select="select(activeIdx)" query="query" position="position">
    <!-- ngRepeat: match in matches track by $index -->
</ul>
          <span class="input-group-btn" ng-class="{current:loading}">
          <input type="submit" value="Search" class="btn btn-default btn-search-bar" ng-disabled="loading">
            <div id="floatingCirclesG">...            </div>
          </span> </div>
        <!-- ngIf: searchForm.$submitted -->
        <div class="error-message ng-binding ng-hide" ng-show="InvalidEircode">
        </div>
</form>

Compatibilizar level com cobertura

Na interface de testes, selecionar o level conforme a quantidade de dígitos do menor prefixo de cobertura mais um. Lever em conta a diferença na quantidade de dígitos e a correspondência com o level em cada uma das bases: postal e cientifica.

Funções universais de cobertura

O tema é tratado entre os matemáticos como subpavimentação... Dada uma geometria X, temos duas aproximações, X⁻ e X⁺, tais que  X⁻ ⊂ X ⊂ X⁺.

Precisamos de duas funções neste projeto:

  1. A cobertura interior, ou seja, X⁻, e portanto uma aproximação de subpavimentação conforme os limites de grade ou de número de células imposto. Na ilustração é a parte vermelha.

  2. A cobertura com borda, ou seja, X⁺. Na ilustração a união da parte vermelha com a amarela, onde a parte amarela é a aproximação de borda.

Outra abordagem, a Morfologia Matemática, trata sempre da aproximação de X como ponto de partida: X⁺ é a sua dilatação e X⁻ a sua erosão, mas existem centenas de maneiras diferentes para se erodir ou dilatar, ver livro em portugues. No PostGIS temos ST_Buffer positivo e negativo como recurso para depois discretizar na grade, quando um controle métrico for necessário.

Implementação

Ver "region cover" (de fato esse é o nome mais popular para a funcionalidade) em s2.sidewalklabs.com/regioncoverer ou S2 Covering Examples.

A interseção pode ser uma boa referência:

  • interseção da borda com grade fixa de maior resolução: pode depois ser otimizada com substituição das células interiores por grades de menor resolução. Pode retornar a borda, o interior X⁻ ou X⁺.

  • interseção da borda com espeçura fixa: tomando-se um buffer métrico da linha de borda podemos medir a área de interseção de modo a selecionar mais corretamente a resolução mais grosseira, minimizando a quantidade de células que comporá a aproximação de borda.

  • interseção com tamanhos variávies: usar o número de células como parâmetro. A função buscaria a menor área de não-interseção, resultando em X⁺.

Trazer mais dados para Jurisdiction

Listagem das pendências em vw_lixo_summary_jurisdiction, conforme https://github.com/osm-codes/WS/blob/main/src/country_sample_function.sql Falta ajustar ao esquema optim.

A listagem atual que nos fornece a situação atual e pendências. Alguns países já possuem git no Digital-Guard, portanto podemos iniciar:

isolabel jurisd_base_id n_level2 n_level3
BR 76 27 5570
CL 152 16 0
CO 170 32 1115
EC 218 24 0
PE 604 26 1
VE 862 25 0

Ver também AR, Uruguai, etc.

Avaliar como tratar nomes de vilas rurais

Para simular PlusCodes também registraremos nomes de vilas rurais, por exemplo CO-ANT-Medelin-Morritos, com mais de uma letra. Não são canônicos, são sempre traduzidos para um prefixo, traduzindo-se por ex. para CO-ANT-Medelin~12 , mas será um overhead na resolução de nomes que precisaremos avaliar como tratar.

Correções menores na interface de teste

Nesta issue listar na forma de checklist as pendências que vão sendo resolvidas conforme possível

  • checkboxes para remover "pin icons"
  • checkboxes para remover rótulos
  • Resolver problemas de zoom inicial: usar o fit geojson somando ou subtraindo um (ou mais) para não ficar tão perto.
  • Resolver problemas de zoom máximo: existem plugins para manter uma "versão pixelizada" do fundo no zoom maior.
  • jurisdições em vermelho

Interfaces de teste e produção e gestão dos endpoints antes do lançamento

O desenvolvimento do back-end depende de algum front-end para que testes e visualização humana possam ser realizados. Por isso acabaram sendo projetados dois back-ends:

  1. interface de teste: também apelidada ou interface Leaflet. por ser mais simples e do conhecimento da equipe back-end, foi a primeira a ser desenvolvida.
    terá uso secundário, sua principal função é a prototipação (prova de conceito) e o preparo de imagens ilustrativas.

  2. interface de produção: também apelidada ou interface ReactJS. É a definitiva, aguarda implementação do site-v2. Deve atender a todos os requisitos de visualização pública. Simplicidade, leveza e eficiência serão solicitados.

As issues deste git, sobre interface, devem especificar se teste ou produção, pois terão requisitos distintos.

Antes do lançamento oficial do site

A interface teste vai permanecer na raiz do domínio osm.codes até que a interface de produção seja entregue em condições de substituir.

A interface teste deverá migrar para o domínio test.osm.codes depois do lançamento (enquanto isso não acontece, redireciona para osm.codes). Permanecerá lá ainda por um tempo, até que se tenha fôlego para investir em "visualizações extra" (controle complexos para gerar ilustrações) no React.

Abordagem para a interface final de códigos postais

A finalidade principal dos geocódigos curtos é suprir a demanda nacional por códigos postais eficientes. A grade base32 em si não é um objetivo, inclusive a recomendação para uso científico e a base 16h.

Em ambos os casos, código postal e científico, o foco não é o desenho ou navegação arbirários, mas o uso de um contexto como ponto de partida: a interface de generalized-geohash explorer não precisa partir do globo, mas sim de um país ou um prefixo dentro de um país.

O prefixo e o tipo de geocódigo (postal ou científico) é que estabelecem a interface, antes do usuário definir o prefixo não faz sentido mostrar algo, ele precisa escolher o que quer... E sempre será contextual. Todas as interfaces precisam ser orientadas ao contexto e não ao globo.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.