16.5. Lesson: Construirea Geometriei
În această secțiune vom intra în detalii despre cum sunt construite geometriile în SQL. În realitate, probabil veți utiliza un GIS cum ar fi QGIS pentru creearea geometriilor complexe folosind instrumentele acestora; cu toate acestea, întelegerea modului cum sunt stocate poate fi utilă pentru scrierea de interogări și înțelegerea modului cum este alcătuită baza de date.
Scopul acestei lecții: De a înțelege mai bine cum să creați entități spațiale direct în PostgreSQL/PostGIS.
16.5.1. Crearea Șirurilor de Linii
Întorcându-ne la baza de date address, să facem tabelul de străzi să se potrivească cu celelalte; de ex., să aibă o constrângere pentru geometrie, un index și o intrare în tabelul geometry_columns.
16.5.2. Try Yourself
Modificați tabela streets, astfel încât ea să aibă o coloană de geometrie de tipul ST_LineString.
Nu uitați să faceți actualizarea coloanelor de geometrie!
De asemenea, adăugați o constrângere pentru a preveni adăugarea geometrii care nu sunt null sau de tip LINESTRINGS.
Creați un index spațial în noua coloană de geometrie
Răspuns
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;
Aruncați o privire la rezultatele din QGIS. (Poate fi necesar să faceți clic-dreapta pe stratul străzilor din panoul «Straturilor», apoi alegeți «Transfocare la extinderea stratului».)
Acum, creați mai multe intrări de străzi - unele în QGIS, iar altele din linia de comandă.
16.5.3. Crearea Poligoanelor
Creating polygons is just as easy. One thing to remember is that by definition, polygons have at least four vertices, with the last and first being co-located:
insert into cities (name, the_geom)
values ('Tokyo', 'SRID=4326;POLYGON((10 -10, 5 -32, 30 -27, 10 -10))');
Notă
Un poligon necesită acolade duble în jurul listei sale de coordonate; aceasta pentru a permite poligoane complexe având multiple zone neconectate. De exemplu
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))'
);
Dacă ați urmat acest pas, puteți verifica rezultatul prin încărcarea setului de date orașe în QGIS, deschizând tabelul de atribute al acestuia, și selectând noua intrare. Remarcați cum cele două noi poligoane se comportă ca unul singur.
16.5.4. Exercițiu: Learea Orașelor de Persoane
Pentru acest exercițiu ar trebui să faceți următoarele:
Ștergeți toate datele din tabela de personal.
Adăugați o coloană de cheie străină în tabela de personal, care face referire la cheia primară a tabelei orașelor.
Utilizați QGIS pentru a captura unele orașe.
Utilizați SQL pentru a introduce câteva înregistrări de personal, verificând că fiecare are asociate o stradă și un oraș.
Your updated people schema should look something like this:
\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)
Răspuns
delete from people;
alter table people add column city_id int not null references cities(id);
(capture cities in 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)');
If you’re getting the following error message:
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. Analizați Schema Noastră
Acum, schrma noastră ar trebui să arate în felul următor:
16.5.6. Try Yourself
Creați marginile orașelor prin calucularea înfășurătorii convexe pentru toate adresele din acel oraș și calcularea unei zone tampon în jurul acesteia.
16.5.7. Accesul la Sub-Obiecte
Folosind funcțiile SFS-Model, aveți la dispoziție o largă gamă de opțiuni pentru accesarea sub-obiectelor geometriilor SFS. Când doriți să selectați primul punct vertex al fiecărei geometrii poligon în tabelul myPolygonTable, trebuie să o faceți în felul acesta:
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. Procesarea Datelor
PostGIS suportă toate funcțiile conforme standardelor OGC SFS/MM. Toate aceste funcții încep cu ST_
.
16.5.9. Decuparea
To clip a subpart of your data you can use the ST_INTERSECT()
function.
To avoid empty geometries, 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. Construirea de Geometrii pornind de la Alte Geometrii
Plecând de la de la un tabel de puncte dat, doriți să generați un linestring. Ordinea punctelor este dată de valoarea id. O altă metodă de ordonare ar putea fi marca de timp, cum ar fi cea pe care o primiți când capturiați puncte cu un receptor GPS.
To create a linestring from a new point layer called «points», you can run the following command:
select ST_LineFromMultiPoint(st_collect(the_geom)), 1 as id
from (
select the_geom
from points
order by id
) as foo;
Pentru a vedea cum funcționează fără a crea un nou strat, puteți executa această comandă în stratul «people», deși desigur nu ar avea prea mult sens în lumea reală.
16.5.11. Curățarea Geometriilor
You can get more information for this topic in this blog entry.
16.5.12. Diferențele dintre tabele
To detect the difference between two tables with the same structure, you can
use the PostgreSQL keyword EXCEPT
:
select * from table_a
except
select * from table_b;
Ca rezultat, veți obține toate acele înregistrări din table_a care nu se regăsesc și în table_b.
16.5.13. Spațiile tabelelor
You can define where postgres should store its data on disk by creating tablespaces:
CREATE TABLESPACE homespace LOCATION '/home/pg';
Atunci când creați o bază de date, aveți posibilitatea să specificați care spațiu de tabelă să fie utilizat, de exemplu:
createdb --tablespace=homespace t4a
16.5.14. In Conclusion
Ați învățat cum să creeați geometrii mai complexe folosing instrucțiuni PostGIS. Rețineți că aceasta folosește la îmbunătățirea cunoștințelor pentru lucrul cu o bază de date spațială printr-o interfață GIS. În mod curent nu veți avea nevoie să folosiți aceste instrucțiuni manual, dar o înțelegere generală vă va ajuta la utilizarea unui GIS, în special dacă întâlniți erori care ar putea să pară altfel criptice.