16.5. geometria de construção
Nesta seção, vamos nos aprofundar um pouco mais em como as geometrias simples são construídas com SQL. Na realidade, você provavelmente irá usar um GIS como QGIS para criar geometrias complexas, utilizando suas ferramentas de digitalização; no entanto, compreender como elas são formuladas pode ser útil para escrever consultas e entender como o banco de dados é montado.
O objetivo desta lição: entender melhor como criar entidades espaciais diretamente no PostgreSQL/PostGIS.
16.5.1. Criando linhas
Voltando ao nosso banco de dados address, vamos deixar a nossa tabela streets igual às outras; ou seja, tendo uma restrição na geometria, um índice e uma entrada na tabela geometry_columns.
16.5.2. Try Yourself
Modifique a tabela streets para que ela tenha uma coluna geometria do tipo ST_LineString.
Não se esqueça de fazer a atualização correspondente na tabela geometry_columns!
Crie também uma restrição para evitar que quaisquer geometrias diferentes de LINESTRINGS ou nulo sejam inseridas.
Crie um índice espacial para a nova coluna do tipo geometry.
Responda
alter table streets add column the_geom geometry;
alter table streets add constraint streets_geom_point_chk check
(st_geometrytype(the_geom) = 'ST_LineString'::text OR the_geom IS NULL);
insert into geometry_columns values ('','public','streets','the_geom',2,4326,
'LINESTRING');
create index streets_geo_idx
on streets
using gist
(the_geom);
Now let’s insert a linestring into our streets table. In this case we will update an existing street record:
update streets
set the_geom = 'SRID=4326;LINESTRING(20 -33, 21 -34, 24 -33)'
where streets.id=2;
Dê uma olhada nos resultados no QGIS. (Você pode precisar clicar com o botão direito sobre a camada street no painel ‘Camadas’, e escolher a opção ‘Zoom para a camada’.)
Agora, crie mais alguns registros em ‘streets’ - alguns pelo QGIS e alguns pela linha de comando.
16.5.3. Criando poligonos
Criar polígonos é igualmente fácil. Uma coisa a lembrar é que, por definição, os polígonos têm pelo menos quatro vértices, com o último e o primeiro co-localizados:
insert into cities (name, the_geom)
values ('Tokyo', 'SRID=4326;POLYGON((10 -10, 5 -32, 30 -27, 10 -10))');
Nota
Um polígono requer colchetes duplos em torno de sua lista de coordenadas; isto serve para permitir que você adicione polígonos complexos com múltiplas áreas não conectadas. Por exemplo:
insert into cities (name, the_geom)
values ('Tokyo Outer Wards',
'SRID=4326;POLYGON((20 10, 20 20, 35 20, 20 10),
(-10 -30, -5 0, -15 -15, -10 -30))'
);
Se você seguir esse passo, você poderá verificar o que ele faz carregando o DataSet ‘cities’ no QGIS, abrindo a sua tabela de atributos, e selecionando o novo registro. Note como os dois novos polígonos comportam-se como um único polígono.
16.5.4. Exercício: Ligando Cidades a Pessoas
Para este execício você deve fazer o seguinte:
Delete todos os dados da tabela ‘people’.
Adicione uma coluna de chave estrangeira na tabela ‘people’ que referencie a chave primária da tabela ‘cities’.
Use QGIS para capturar algumas cidades.
Use SQL para inserir alguns registros novos de pessoas, garantindo que cada um tenha uma rua e uma cidade associados aos mesmos.
Seu esquema de pessoas atualizado deve se parecer com isso:
\d people
Table "public.people"
Column | Type | Modifiers
-----------+-----------------------+--------------------------------------------
id | integer | not null
| | default nextval('people_id_seq'::regclass)
name | character varying(50) |
house_no | integer | not null
street_id | integer | not null
phone_no | character varying |
the_geom | geometry |
city_id | integer | not null
Indexes:
"people_pkey" PRIMARY KEY, btree (id)
"people_name_idx" btree (name)
Check constraints:
"people_geom_point_chk" CHECK (st_geometrytype(the_geom) =
'ST_Point'::text OR the_geom IS NULL)
Foreign-key constraints:
"people_city_id_fkey" FOREIGN KEY (city_id) REFERENCES cities(id)
"people_street_id_fkey" FOREIGN KEY (street_id) REFERENCES streets(id)
Responda
delete from people;
alter table people add column city_id int not null references cities(id);
(capturar cidades no QGIS)
insert into people (name,house_no, street_id, phone_no, city_id, the_geom)
values ('Faulty Towers',
34,
3,
'072 812 31 28',
1,
'SRID=4326;POINT(33 33)');
insert into people (name,house_no, street_id, phone_no, city_id, the_geom)
values ('IP Knightly',
32,
1,
'071 812 31 28',
1,F
'SRID=4326;POINT(32 -34)');
insert into people (name,house_no, street_id, phone_no, city_id, the_geom)
values ('Rusty Bedsprings',
39,
1,
'071 822 31 28',
1,
'SRID=4326;POINT(34 -34)');
Se você estiver recebendo a seguinte mensagem de erro:
ERROR: insert or update on table "people" violates foreign key constraint
"people_city_id_fkey"
DETAIL: Key (city_id)=(1) is not present in table "cities".
then it means that while experimenting with creating polygons for the cities table, you must have deleted some of them and started over. Just check the entries in your cities table and use any id which exists.
16.5.5. Verificando nosso esquema
Por enquanto, nosso esquema deve estar parecendo com isso:
16.5.6. Try Yourself
Crie limites de cidade computando o menor polígono que contenha todos os endereços para aquela cidade e crie um buffer em torno dessa área.
16.5.7. Acessando Subobjetos
Com as funções do modelo SFS, você tem uma grande variedade de opções para acessar subobjetos de Geometrias SFS. Quando você quiser selecionar o primeiro vértice de cada polígono na tabela myPolygonTable, você terá que fazer dessa maneira:
Transform the polygon boundary to a linestring:
select st_boundary(geometry) from myPolygonTable;
Select the first vertex point of the resultant linestring:
select st_startpoint(myGeometry) from ( select st_boundary(geometry) as myGeometry from myPolygonTable) as foo;
16.5.8. Processamento de dados
O PostGIS suporta todas as funções conformes do padrão OGC SFS/MM. Todas essas funções começam com ST_
.
16.5.9. Recortando
Para recortar uma subparte dos seus dados, você pode usar a função ST_INTERSECT ()
. Para evitar geometrias vazias, use:
where not st_isempty(st_intersection(a.the_geom, b.the_geom))
select st_intersection(a.the_geom, b.the_geom), b.*
from clip as a, road_lines as b
where not st_isempty(st_intersection(st_setsrid(a.the_geom,32734),
b.the_geom));
16.5.10. Construindo Geometrias a partir de outras Geometrias
A partir de uma determinada tabela de pontos, você quer gerar uma linha. A ordem dos pontos é definida pelo id. Outro método de ordenação poderia ser o horário, como quando você captura pontos em um caminho com um receptor GPS.
Para criar uma linestring a partir de uma nova camada de pontos chamada ‘points’, você pode executar o seguinte comando:
select ST_LineFromMultiPoint(st_collect(the_geom)), 1 as id
from (
select the_geom
from points
order by id
) as foo;
Para ver como isso funciona sem criar uma nova camada, você também pode executar esse comando sobre a camada ‘people’, embora, naturalmente, fizesse pouco sentido fazer isso no mundo real.
16.5.11. Limpeza de Geometria
You can get more information for this topic in this blog entry.
16.5.12. As diferenças entre as tabelas
Para detectar a diferença entre duas tabelas com a mesma estrutura, você pode usar a palavra-chave do PostgreSQL EXCEPT
:
select * from table_a
except
select * from table_b;
Como resultado, você terá todos os registros de table_a que não estão presentes em table_b.
16.5.13. Tablespaces
Você pode definir onde o postgres deve armazenar seus dados no disco criando espaços de tabela:
CREATE TABLESPACE homespace LOCATION '/home/pg';
Quando você cria um banco de dados, você pode especificar qual tablespace usar. Por exemplo:
createdb --tablespace=homespace t4a
16.5.14. In Conclusion
Você aprendeu como criar geometrias mais complexas usando declarações do PostGIS. Tenha em mente que isso é principalmente para melhorar o seu conhecimento tácito ao trabalhar com bancos de dados geo-capacitados através de uma interface GIS. Você normalmente não precisará entrar com essas declarações manualmente, mas ter uma ideia geral de sua estrutura irá ajudá-lo quando for usar um SIG, especialmente se você encontrar erros que de outra forma podem parecer enigmáticos.