OpenStreetMap

Jorge Gustavo Rocha's Diary

Recent diary entries

A rede de postos de carregamento do OpenStreetMap está bastante completa, pelo que me tenho apercebido.

Hoje quis ver que postos havia em Esposende e no OpenStreetMap não estava nenhum registado. Nem um :-(

Por isso, fui sacar os postos da rede MOBI.E para comparar e ver o que poderia estar em falta.

Sacar Postos da rede MOBI.E

Abrir o site da rede MOBI.E.

Abrir as ferramentas de desenvolvimento e selecionar o separador Rede. Eventualmente por um filtro para só apanhar os pedidos que tenham ‘location’. Fazer um refresh da página para apanhar os pedidos feitos ao servidor. O pedido que é apanhado está no seguinte print screen.

Pode-se fazer copy e paste do JSON retornado e guardar num ficheiro. Ou, como se faz no passo seguinte, fazer o mesmo pedido na linha de comando.

Guardar o resultado num arquivo JSON

Com o botão do lado direito, emcima do pedido, pode-se copiar o pedido como “Copy as cURL”. Depois, na linha de comando, faz-se o poste do mesmo, acrescentando duas coisas: a opção -k para não se ter problemas com o certificado e a opção -o mobi-e.json.

O comando será algo do género:

curl 'https://ocpi.mobinteli.com/2.2/locations' -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Origin: https://www.mobie.pt' -H 'Connection: keep-alive' -H 'Referer: https://www.mobie.pt/' -H 'If-Modified-Since: Fri, 30 Apr 2021 15:46:14 GMT' -H 'If-None-Match: "1c097b-5c13283049500"' -k -o mobi-e.json

Transformar o JSON em CSV

O arquivo sacado está em JSON. É um enorme array com todos os postos elétricos. Pode-se transformar em CSV em Python, e aproveita-se para transformar coluna coordinates que está em JSON em duas colunas separadas. Fica assim supor fácil ler o CSV no QGIS ou noutra ferramenta. Também se conta (com a função len) o número de conetores em cada posto.

import pandas as pd
df = pd.read_json("mobi-e.json")
df['latitude'] = pd.io.json.json_normalize(df.coordinates)['latitude']
df['longitude'] = pd.io.json.json_normalize(df.coordinates)['longitude']
df['conetores'] = df.evses.apply(len)
df.to_csv("mobi-e.csv")

O mobi-e.csv pode-se adicionar ao QGIS.

Abrir o CSV no QGIS e comparar com os postos do OSM

No QGIS, adicionar uma camada de texto delimitada.

No QGIS, usando o plugin Quick OSM, fazer uma query com:

  • amenity
  • charging_station
  • Portugal

Acrescentar o mapa OSM como fundo e visualizar no EPSG:3857.

Conclusão

Não há nenhum posto de carregamento em Esposende.

Nota para quem quiser ajudar a verificar as diferenças entre o OSM e a MOBI.E

Deixei um arquivo mobi-e.osm e mobi-e.shp (em zip) numa pasta do Nextcloud.

Location: Costa Nova, Gafanha da Encarnação, Ílhavo, Aveiro, Portugal

Converti as moradas da Madeira e dos Açores para *.shp, *.osm e *.json. São dados importados do INE e referem-se a alojamentos. Não incluem o comércio e indústria.

Para editar transformações de coordenadas, criei já tudo em EPSG:4326 (WGS84).

Estão disponíveis na nextcloud em:

Estão por lá também as scripts de importação.

Se preferirem trabalhar só com os pontos de entrega do correio, em vez de terem o mesmo ponto repetido para cada endereço, como acontece nos prédios, criei uma tabela entregas.

A tabela entregas mantém toda a informação, pois estou a agregar a informação das diferentes moradas num único ponto.

Criei uma pasta Pontos de Entrega Continente onde têm uma exportação por concelho.

Para quem usar o QGIS, criei nessa pasta um geopackage continente.gpkg que tem as duas tabelas: moradase entregas.

Também fiz um dump do Postgresql, que está nessa pasta em enderecos-202103291045.backup.

Atenção: as shapefiles têm limitações no comprimento dos atributos. Algumas agregações estão truncadas (pelo limite de 255 carateres do formato shapefile.

Criação de uma tabela só com os pontos de entrega

CREATE TABLE entregas (
	fid INT generated BY default AS identity primary key,
	geom geometry(POINT, 3763) NULL,
	numeros text NULL,
	pisos text NULL,
	fracoes text NULL,
	toponimos text NULL,
	tipos text NULL,
	edificios varchar NULL,
	codpostais varchar NULL
);

CREATE INDEX entregas_geom_idx ON entregas USING gist (geom);

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(SELECT unnest($1) ORDER BY 1)
$$;

insert into entregas (geom, numeros, pisos, fracoes, toponimos, tipos, edificios, codpostais)
with unicas as (
	select geom, ARRAY_AGG(DISTINCT numero) as numeros, ARRAY_AGG(DISTINCT piso) as pisos, ARRAY_AGG(DISTINCT fracao) as fracoes,
	ARRAY_AGG(DISTINCT toponimo) as toponimos, ARRAY_AGG(DISTINCT tipo) as tipos, ARRAY_AGG(DISTINCT edificio) as edificios, ARRAY_AGG(DISTINCT postcode) as postcodes
	from moradas group by geom)
select geom, array_to_string(array_sort(numeros), ', ') as numeros, 
array_to_string(array_sort(pisos), ', ') as pisos, 
array_to_string(array_sort(fracoes), ', ') as fracoes, 
array_to_string(array_sort(toponimos), ', ') as toponimos, 
array_to_string(array_sort(tipos), ', ') as tipos, 
array_to_string(array_sort(edificios), ', ') as edificios, 
array_to_string(array_sort(postcodes), ', ') as codpostais
from unicas;

Com isto, passamos de 5 669 971 moradas, para 3 372 945 pontos de entrega.

Para sistematizar a importação do continente, podem-se usar as seguintes scripts:

Sacar índices, gerar uma script para sacar os zips e sacar os zips:

#!/bin/bash

wget https://inspire.ine.pt/AD/atom/CDG_AD_BNM_pc_Norte_Atom.xml
wget https://inspire.ine.pt/AD/atom/CDG_AD_BNM_pc_Centro_Atom.xml
wget https://inspire.ine.pt/AD/atom/CDG_AD_BNM_pc_AML_Atom.xml
wget https://inspire.ine.pt/AD/atom/CDG_AD_BNM_pc_Alentejo_Atom.xml
wget https://inspire.ine.pt/AD/atom/CDG_AD_BNM_pc_Algarve_Atom.xml

awk '/Addresses_[0-9]+_EPSG3763.zip/ {print $3}' *.xml | sed 's/href=/wget /' > saca.sh

mkdir zips; cd zips; bash ../saca.sh

A script cria uma pasta zips com 278 zips (um para cada concelho do continente).

Para o restante processamento, usa-se o GDAL e uma base de dados PostgreSQL, onde é criada uma tabela moradas.

Nessa pasta, corre-se a seguinte script que processa concelho a concelho. Para cada concelho, são acrescentados os respetivos endereços à tabela moradas.

Script processa.sh:

#!/bin/bash

for filename in *.zip
do
    base="${filename%.*}"
    unzip $filename
    echo "${filename%.*}"
    GML_ATTRIBUTES_TO_OGR_FIELDS=YES GML_SKIP_RESOLVE_ELEMS=NONE ogr2ogr -f PostgreSQL PG:'service=osm' GMLAS:$base.gml -nlt CONVERT_TO_LINEAR
    psql service=osm -f insere.sql
    rm $base.gml    
done

A script processa.sh recorre a uma script SQL insere.sql, que é a seguinte:

insert into moradas (ogr_pkid, geom, numero , piso , fracao , toponimo , tipo , edificio , postcode)
with designator as ( 
	select al.parent_ogr_pkid, json_object_agg(regexp_replace(ld.locatordesignator_type_href, 'http://inspire.ec.europa.eu/codelist/LocatorDesignatorTypeValue/(.*)Identifier', '\1'), 
	ld.locatordesignator_designator) as designator 
	from address_locator al, address_locator_addresslocator_designator ld 
	where al.ogr_pkid = ld.parent_ogr_pkid 
	group by al.parent_ogr_pkid, ld.parent_ogr_pkid), 
buidname as (
	select al.parent_ogr_pkid, gns.spellingofname_text
	from address_locator al, address_locator_addresslocator_name alan, address_locator_addresslocator_name_locatorname_name alanln, geographicalname gn, geographicalname_spelling gns 
	where al.ogr_pkid = alan.parent_ogr_pkid and
	alan.ogr_pkid =alanln.parent_ogr_pkid and
	alanln.geographicalname_pkid = gn.ogr_pkid and 
	gn.ogr_pkid = gns.parent_ogr_pkid),
position as (
	select ap.parent_ogr_pkid, ap.geographicposition_geometry 
	from address_position ap), 
postcode as (
	select parent_ogr_pkid, pd.postcode 
	from address_component ac left join postaldescriptor pd on ac.href_postaldescriptor_pkid = pd.ogr_pkid 
	where href_postaldescriptor_pkid is not null), 
toponimo as (
	with tfnp as (
		select parent_ogr_pkid, json_object_agg( regexp_replace(partofname_type_href , 'http://inspire.ec.europa.eu/codelist/PartTypeValue/(.*)', '\1'), partofname_part) as partofname 
		from thoroughfarename_ad_name_thoroughfarenamevalue_nameparts 
		group by parent_ogr_pkid) 
	select ac.parent_ogr_pkid, tfnp.partofname 
		from address_component ac left join thoroughfarename tf on ac.href_thoroughfarename_pkid = tf.ogr_pkid 
		left join thoroughfarename_ad_name tfn on tf.ogr_pkid = tfn.parent_ogr_pkid 
		left join tfnp on tfnp.parent_ogr_pkid = tfn.ogr_pkid where href_thoroughfarename_pkid is not null) 
select a.ogr_pkid, p.geographicposition_geometry as geom, d.designator->>'building' as numero, d.designator->>'floor' as piso, d.designator->>'unit' as fracao, 
	t.partofname->>'name' as toponimo, t.partofname->>'type' as tipo, buidname.spellingofname_text as edificio, pc.postcode 
	from address a, position p, designator d, toponimo t, postcode pc, buidname
where a.ogr_pkid = p.parent_ogr_pkid and a.ogr_pkid = d.parent_ogr_pkid and a.ogr_pkid = pc.parent_ogr_pkid and a.ogr_pkid = t.parent_ogr_pkid and a.ogr_pkid = buidname.parent_ogr_pkid;

drop table address;
drop table address_building;
drop table address_component;
drop table address_locator;
drop table address_locator_addresslocator_designator;
drop table address_locator_addresslocator_name;
drop table address_locator_addresslocator_name_locatorname_name;
drop table address_metadataproperty;
drop table address_name;
drop table address_parcel;
drop table address_position;
drop table addressareaname;
drop table addressareaname_ad_name;
drop table addressareaname_gml_name;
drop table addressareaname_metadataproperty;
drop table addressareaname_situatedwithin;
drop table administrativeboundary;
drop table administrativeboundary_admunit;
drop table administrativeboundary_metadataproperty;
drop table administrativeboundary_name;
drop table administrativeboundary_nationallevel;
drop table administrativeunit;
drop table administrativeunit_administeredby;
drop table administrativeunit_au_name;
drop table administrativeunit_boundary;
drop table administrativeunit_coadminister;
drop table administrativeunit_condominium;
drop table administrativeunit_gml_name;
drop table administrativeunit_lowerlevelunit;
drop table administrativeunit_metadataproperty;
drop table administrativeunit_nationallevelname;
drop table administrativeunit_residenceofauthority;
drop table adminunitname;
drop table adminunitname_ad_name;
drop table adminunitname_gml_name;
drop table adminunitname_metadataproperty;
drop table adminunitname_situatedwithin;
drop table basicpropertyunit;
drop table basicpropertyunit_metadataproperty;
drop table basicpropertyunit_name;
drop table cadastralparcel;
drop table cadastralparcel_basicpropertyunit;
drop table cadastralparcel_metadataproperty;
drop table cadastralparcel_name;
drop table cadastralzoning;
drop table cadastralzoning_cp_name;
drop table cadastralzoning_gml_name;
drop table cadastralzoning_levelname;
drop table cadastralzoning_metadataproperty;
drop table condominium;
drop table condominium_admunit;
drop table condominium_au_name;
drop table condominium_gml_name;
drop table condominium_metadataproperty;
drop table geographicalname;
drop table geographicalname_spelling;
drop table inspireid;
drop table location;
drop table md_resolution;
drop table namedplace;
drop table namedplace_gml_name;
drop table namedplace_gn_name;
drop table namedplace_localtype;
drop table namedplace_metadataproperty;
drop table namedplace_relatedspatialobject;
drop table namedplace_type;
drop table postaldescriptor;
drop table postaldescriptor_metadataproperty;
drop table postaldescriptor_name;
drop table postaldescriptor_postname;
drop table postaldescriptor_situatedwithin;
drop table thoroughfarename;
drop table thoroughfarename_ad_name;
drop table thoroughfarename_ad_name_thoroughfarenamevalue_nameparts;
drop table thoroughfarename_gml_name;
drop table thoroughfarename_metadataproperty;
drop table thoroughfarename_situatedwithin;
drop table thoroughfarename_transportlink;

Depois deste processamento, na tabela moradas têm-se os endereços do INE para o continente, no sistema de coordenadas ETRS89/Portugal TM06.

Para exportar os endereços por concelhos, carrega-se a tabela dos concelhos do continente (gerada a partir da CAOP) na base dados. Com base nessa tabela, gera-se uma script com a exportação concelho a concelho.

Cada linha da script de exportação é gerada com (continente.sql):

select 'mkdir "' || concelho || '"; ogr2ogr -f "ESRI Shapefile" "' || concelho || '/' || dicofre || '.shp" PG:"service=osm" -sql "select m.* from moradas m, concelhos c where st_contains(c.geom, m.geom) and c.concelho = ' || '''' || concelho || '''"' from concelhos;
psql service=osm -t -f continente.sql > continente.sh
mkdir continente; cd continente
bash ../continente.sh

Finalmente, para se poder usar a tabela moradas no QGIS ou para a publicar através de serviços WMS ou WFS/QFS3, dá jeito ter uma chave primária e um índice espacial.

ALTER TABLE moradas ADD CONSTRAINT moradas_pk PRIMARY KEY (ogr_pkid);
CREATE INDEX moradas_geom_idx ON moradas USING gist (geom);

O resultado são 278 pastas, uma por concelho, e em cada pasta está a shapefile com os endereços desse concelho.

As pastas podem ser acedidas a partir uma nextcloud experimental para a comunidade OpenStreetMap PT, em importação dos endereços do continente. As shapefiles por concelhos estão nas pasta continente. Partilhei outras pastas, para incluir as scripts.

O backup no formato PostgrSQL das tabelas usadas (moradas e concelhos, derivada da CAOP 2020) está também nessa pasta, em enderecos-202103282354.backup.

Essas mesmas duas tabelas estão em continente.gpkg, que pode ser aberto no QGIS. Foi exportado com:

ogr2ogr -f GPKG continente.gpkg PG:'service=osm tables=moradas,concelhos'

Querem uma shapefile com as moradas todas? Eu criei uma, mas tem mais de 2Gb. Está em continente.shp.zip. Não tem índice espacial, para não ocupar mais espaço. Vai dar cabo de alguns softwares foleiros a correr em sistemas operativos duvidosos.

Para o continente, ficam assim disponíveis 5 669 971 endereços. Vou dizer por extenso: cinco milhões, seiscentos e sessenta e nove mil, novecentos e setenta e um endereços.

Bom trabalho!

Na importação das moradas do INE, estava a perder o “nome do edifício”, que é importante. Nalguns casos, os endereços não têm número, mas têm “nome do edifício”, como é ilustrado na imagem seguinte (em Beja).

Assim sendo, a query para passar das múltiplas tabelas criadas a partir do GML para uma única tabela passa a ser:

create table moradas as 
with designator as ( 
	select al.parent_ogr_pkid, json_object_agg(regexp_replace(ld.locatordesignator_type_href, 'http://inspire.ec.europa.eu/codelist/LocatorDesignatorTypeValue/(.*)Identifier', '\1'), 
	ld.locatordesignator_designator) as designator 
	from address_locator al, address_locator_addresslocator_designator ld 
	where al.ogr_pkid = ld.parent_ogr_pkid 
	group by al.parent_ogr_pkid, ld.parent_ogr_pkid), 
buidname as (
	select al.parent_ogr_pkid, gns.spellingofname_text
	from address_locator al, address_locator_addresslocator_name alan, address_locator_addresslocator_name_locatorname_name alanln, geographicalname gn, geographicalname_spelling gns 
	where al.ogr_pkid = alan.parent_ogr_pkid and
	alan.ogr_pkid =alanln.parent_ogr_pkid and
	alanln.geographicalname_pkid = gn.ogr_pkid and 
	gn.ogr_pkid = gns.parent_ogr_pkid),
position as (
	select ap.parent_ogr_pkid, ap.geographicposition_geometry 
	from address_position ap), 
postcode as (
	select parent_ogr_pkid, pd.postcode 
	from address_component ac left join postaldescriptor pd on ac.href_postaldescriptor_pkid = pd.ogr_pkid 
	where href_postaldescriptor_pkid is not null), 
toponimo as (
	with tfnp as (
		select parent_ogr_pkid, json_object_agg( regexp_replace(partofname_type_href , 'http://inspire.ec.europa.eu/codelist/PartTypeValue/(.*)', '\1'), partofname_part) as partofname 
		from thoroughfarename_ad_name_thoroughfarenamevalue_nameparts 
		group by parent_ogr_pkid) 
	select ac.parent_ogr_pkid, tfnp.partofname 
		from address_component ac left join thoroughfarename tf on ac.href_thoroughfarename_pkid = tf.ogr_pkid 
		left join thoroughfarename_ad_name tfn on tf.ogr_pkid = tfn.parent_ogr_pkid 
		left join tfnp on tfnp.parent_ogr_pkid = tfn.ogr_pkid where href_thoroughfarename_pkid is not null) 
select a.ogr_pkid, p.geographicposition_geometry, d.designator->>'building' as numero, d.designator->>'floor' as piso, d.designator->>'unit' as fracao, 
	t.partofname->>'name' as toponimo, t.partofname->>'type' as tipo, buidname.spellingofname_text as edificio, pc.postcode 
	from address a, position p, designator d, toponimo t, postcode pc, buidname
where a.ogr_pkid = p.parent_ogr_pkid and a.ogr_pkid = d.parent_ogr_pkid and a.ogr_pkid = pc.parent_ogr_pkid and a.ogr_pkid = t.parent_ogr_pkid and a.ogr_pkid = buidname.parent_ogr_pkid;

Importar moradas no INE

Posted by Jorge Gustavo Rocha on 7 March 2021 in Portuguese (Português). Last updated on 8 March 2021.

O INE disponibiliza um conjunto de moradas relativas a alojamentos, no formato ATOM

O serviço é apenas um índice. O serviço em si divide-se em partes:

Dentro de cada índice, há dois links para cada município com a mesma informação: um no sistema de coordenadas Portuguesas EPSG:3763 e outro em Europeias ETRS:4258.

Por exemplo, para o meu município, Ílhavo, terei que usar o índice da zona centro e descarregar:

wget http://inspire.ine.pt/AD/atom/gml/Addresses_0110_EPSG3763.zip

Não é fácil ler e transformar o GML em algo usável num editor de OSM. Mas como é um processo automatizável, aqui fica a descrição do processo. O que aqui fiz para Ílhavo, pode ser feito para qualquer outro concelho. Pode ser feito na linha de comandos. Vou usar o QGIS só para visualizar os dados.

Estou a utilizar o GDAL e uma base de dados PostgreSQL com Postgis.

Descompactar.

unzip Addresses_0110_EPSG3763.zip Inserir o GML em base de dados (num schema ilhavo)

GML_ATTRIBUTES_TO_OGR_FIELDS=YES GML_SKIP_RESOLVE_ELEMS=NONE ogr2ogr -f PostgreSQL PG:'service=osm schemas=ilhavo' GMLAS:Addresses_0110_EPSG3763.gml -nlt CONVERT_TO_LINEAR

Na base de dados, transformar as inúmeros tabelas numa única com as moradas e respetivos atributos.

create table ilhavo.moradas as with designator as ( select al.parent_ogr_pkid, json_object_agg(regexp_replace(ld.locatordesignator_type_href, 'http://inspire.ec.europa.eu/codelist/LocatorDesignatorTypeValue/(.*)Identifier', '\1'), ld.locatordesignator_designator) as designator from ilhavo.address_locator al, ilhavo.address_locator_addresslocator_designator ld where al.ogr_pkid = ld.parent_ogr_pkid group by al.parent_ogr_pkid, ld.parent_ogr_pkid), position as (select ap.parent_ogr_pkid, ap.geographicposition_geometry from ilhavo.address_position ap), postcode as (select parent_ogr_pkid, pd.postcode from ilhavo.address_component ac left join ilhavo.postaldescriptor pd on ac.href_postaldescriptor_pkid = pd.ogr_pkid where href_postaldescriptor_pkid is not null), toponimo as ( with tfnp as (select parent_ogr_pkid, json_object_agg( regexp_replace(partofname_type_href , 'http://inspire.ec.europa.eu/codelist/PartTypeValue/(.*)', '\1'), partofname_part) as partofname from ilhavo.thoroughfarename_ad_name_thoroughfarenamevalue_nameparts group by parent_ogr_pkid) select ac.parent_ogr_pkid, tfnp.partofname from ilhavo.address_component ac left join ilhavo.thoroughfarename tf on ac.href_thoroughfarename_pkid = tf.ogr_pkid left join ilhavo.thoroughfarename_ad_name tfn on tf.ogr_pkid = tfn.parent_ogr_pkid left join tfnp on tfnp.parent_ogr_pkid = tfn.ogr_pkid where href_thoroughfarename_pkid is not null) select a.ogr_pkid, p.geographicposition_geometry, d.designator->>'building' as numero, d.designator->>'floor' as piso, d.designator->>'unit' as fracao, t.partofname->>'name' as toponimo, t.partofname->>'type' as tipo, pc.postcode from ilhavo.address a, position p, designator d, toponimo t, postcode pc where a.ogr_pkid = p.parent_ogr_pkid and a.ogr_pkid = d.parent_ogr_pkid and a.ogr_pkid = pc.parent_ogr_pkid and a.ogr_pkid = t.parent_ogr_pkid;

ALTER TABLE ilhavo.moradas ADD CONSTRAINT moradas_pk PRIMARY KEY (ogr_pkid);

Depois de criada a tabela, exportar a mesma para uma shapefile.

ogr2ogr -f "ESRI Shapefile" ilhavo.shp PG:"service=osm" "ilhavo.moradas"

E já temos uma shapefile de endereços de alojamentos pronta a usar!

Se for uma moradia (um ponto de entrega corresponde a um endereço):

Se for um prédio (um ponto de entrega corresponde a múltiplos alojamentos e há pisos e frações nos endereços):

No QGIS pode-se trabalhar a simbologia para as moradas aparecem claras (e com o número de moradas para cada ponto de entrega do correio).

No JOSM, basta arrastar para lá shapefile e fica-se com as mesmas à disposição para editar.

Deixo três exemplos:

  • Ílhavo, com cerca de 22k alojamentos
  • Águeda, com cerca de 22k alojamentos
  • Braga, com cerca de 86k alojamentos
Location: Costa Nova, Gafanha da Encarnação, Ílhavo, Aveiro, Portugal

HOT Task Manager 2

Temos uma instalação do HOT Task Manager 2 para a comunidade portuguesa, em língua portuguesa (obrigado aos tradutores do HOT).

Já há pelo menos 3 mapeadores com permissões de “administrator” que podem dar permissão de “project manager” a quem precisar. Quem quiser criar um projeto, passe um email na nossa lista Talk-PT que um dos administradores faz isso.

Esta ferramenta é muito interessante para apoiar mapping parties.

Bom trabalho!

Location: Cidreiro, Vila de Rei, Castelo Branco, 6110-202, Portugal

Durante a party de Águeda, na Mourisca, editei a linha uqe delimitava a zona industrial, e quiz reverter essa linha para a versão original uns dias depois.

Para isso, saquei a versão 2 (boa) da linha, com o browser: http://api.openstreetmap.org/api/0.6/way/164427582/2

Depois alterei o XML, acrescentando action=”modify” na tab way, ficando:

Abri no JOSM, e tentei o upload. Deu conflitos. Resolvi os conflitos indicando que esta versão deveria sobrepor as anteriores. Fiz de novo upload. Acho que consegui. Depois descarreguei a nova versão (v5), com o URL: http://api.openstreetmap.org/api/0.6/way/164427582/2 Há uns nodos (2) de diferença. Vou pensar melhor no assunto, pois pensei que estes passos eram os suficientes para restaurar uma versão anterior de uma linha. Penso que estes nodos, como entretanto foram removidos ou alterados, já não podem fazer parte da linha.

Boa gente,

Na prossecução da minha missão de limpar a CAOP existente, tive que remover milhares de pontos que restaram de uma remoção dos ways, mas não dos nodes. Ou seja, haviam montes de nodes sem tags nenhumas que já foram as linhas da CAOP.

Por os seleccionar muito rapidamente, usei a seguinte expressão no JOSM:
type:node untagged -child
no diálogo do "Search..."

Ou seja, encontra nodos que não sejam filhos de nada (ways ou relactions) e que não tenham tags.

Funciona às mil maravilhas...

Sacar a hora de mofificação que ficou no cartão de memória do telemóvel

ls -al --time-style='+%Y:%m:%d %H:%M:%S' -l > /tmp/x.sh

Editar o ficheiro gerado para ficar algo do género:

#!/bin/bash

exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:02:48" Img015.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:03:14" Img016.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:03:46" Img017.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:04:22" Img018.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:04:44" Img019.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:04:52" Img020.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:07:08" Img021.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:09:00" Img022.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:09:52" Img023.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:10:06" Img024.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:10:50" Img025.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:11:02" Img026.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:11:54" Img027.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:14:06" Img028.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:14:32" Img029.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:14:42" Img030.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:15:08" Img031.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:15:16" Img032.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:15:36" Img033.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:15:50" Img034.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:16:20" Img035.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:16:36" Img036.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:17:22" Img037.jpg
exiv2 -M"set Exif.Photo.DateTimeOriginal 2011:04:01 11:22:44" Img038.jpg

Bingo!

O JOSM é bom rapaz, mas só consegue transformar em data layer um GPX que contenha tracks. Se o GPX só contiver pontos, não dá.

1) Usei um programa muito básico que se chama gpsbabel.
gpsbabel -i gpx -o osm lugaresnew.gpx lugares.osm

2) Abri o JOSM e carreguei lugares.osm

Neste caso...

3) Seleccionei tudo e:

3.1) acrescentei a mesma tag a todos os elementos ao
mesmo tempo (place=hamlet e source=CM Vale de Cambra)
3.2) Removi a tag created_by=GPSBabel

4) Fiz o upload e pronto.

1) Usando a XAPI, a coisa demora um pouco a responder.

curl -g "http://jxapi.openstreetmap.org/xapi/api/0.6/*[amenity=pharmacy][bbox=-9.2,39.68,-6.2,42.19]" -o farmacias.osm

2) Isolar as farmácias a partir de um dump no formato osm

Para "isolar" as farmácias já registadas, sem despejar o dump portugal.osm no Postgresql, pode-se usar o osmosis.

sudo apt-get install osmosis

osmosis --read-xml portugal.osm --tf accept-nodes amenity=pharmacy --tf reject-ways --tf reject-relations --write-xml farmacias.osm

ou ainda

osmosis --read-xml portugal.osm --tf accept-nodes amenity=pharmacy --tf accept-ways amenity=pharmacy --tf reject-relations --write-xml farmacias.osm