Difference between revisions of "Parcely"
m (→Dotazy s prostorovou složkou) |
m (→Dotazy s prostorovou složkou) |
||
Line 214: | Line 214: | ||
SELECT idparcela, tvarparcela | SELECT idparcela, tvarparcela | ||
− | WHERE | + | FROM parcela |
+ | WHERE idparcela=24; | ||
a poté zobrazení geometrie v prohlížečce jako na obrázku [[Media:parcela24.png | Parcela 24]]. | a poté zobrazení geometrie v prohlížečce jako na obrázku [[Media:parcela24.png | Parcela 24]]. | ||
Revision as of 16:07, 5 August 2014
Contents
Příklad Parcely
Představme si velmi jednoduchý systém pro evidenci parcel a jejich vlastníků. Vytvoříme jednoduchou datovou strukturu, pomocí které budeme evidovat vlastníka/vlastníky pozemku/ů. Připouštíme variantu, kdy jeden vlastník může vlastnit více parcel (současně i postupně v čase). Stejně jako jedna parcela může mít více vlastníků v daném okamžiku.
Rozborem situace zjistíme, že lze nadefinovat datové entity VLASTNIK a PARCELA, mezi kterými vznikne vztah typu M:N:
VLASTNIK m – VLASTNI – n PARCELA
Strukturu entitních typů zapíšeme pomocí lineárního zápisu:
VLASTNIK(idVlastnik, jmenoVla, prijmeniVla, adresaVla), PARCELA(idParcela, KU, tvarParcela), VLASTNI(VLASTNIK, PARCELA, datumOd, datumDo)
kde atributy s prefixem 'id' představují primární atributy, a vazba umožňuje díky vazebním atributům sledovat kdo vlastnil parcelu v určitém období.
Před vytvořením struktury v databázi připravíme rozkladem této vazby vazební tabulku, jejíž záznamy budou představovat údaje o vlastníkovi parcely, včetně časového intervalu vlastnictví.
VLASTNIK 1 --- m VLASTNICTVI n---1 PARCELA
Vazební tabulka VLASTNICTVI bude mít primární atribut a dva atributy typu cizí klíč, a atributy vazby.
VLASTNICTVI(idVlastnictvi, idVlastnik, idParcela, vlastniOd, vlastniDo).
Vytvoření tabulek a vložení dat
Tabulky vytvoříme pomocí příkazu CREATE TABLE, kde uvedeme název tabulky, názvy a datové typy atributů, a omezení na atributy či tabulku.
Tabulka VLASTNIK
Před tvorbou samotné tabulky je vhodné ošetřit možnost existence tabulky se stejným názvem (například z důvodu předchozího nepovedeného příkazu:-)).
DROP TABLE VLASTNIK;
CREATE TABLE VLASTNIK( idVlastnik NUMBER PRIMARY KEY, jmenoVla VARCHAR2(25) NOT NULL, prijmeniVla VARCHAR2(25) NOT NULL, adresaVla VARCHAR2(30) );
Do tabulky VLASTNIK vložíme několik záznamů pomocí příkazu INSERT INTO table_name VALUES (value1, value2, value3, ...), kdy je nutno dodržet pořadí vkládaných hodnot podle definice tabulky.
INSERT INTO vlastnik VALUES (1, 'Jan', 'Volný', 'Frýdek-Místek'); INSERT INTO vlastnik VALUES (2, 'Petr', 'Krátký', 'Frýdek-Místek'); INSERT INTO vlastnik VALUES (3, 'Jan', 'Bohustý', 'Frýdek-Místek'); INSERT INTO vlastnik VALUES (4, 'Jindřich', 'Volný', 'Ostrava'); INSERT INTO vlastnik VALUES (5, 'Jana', 'Volná', 'Ostrava'); INSERT INTO vlastnik values (6, 'Věra', 'Krásná', 'Frýdek-Místek');
Ověříme uložení dat kontrolním výpisem z tabulky: SELECT * FROM VLASTNIK.
Tabulka PARCELA
Dále vytvoříme tabulku PARCELA podobným působem jako VLASTNIK.
DROP TABLE PARCELA;
CREATE TABLE PARCELA (idParcela NUMBER PRIMARY KEY, ku VARCHAR2(8) NOT NULL, tvarParcela SDO_GEOMETRY );
Vložíme data o několika parcelách:
INSERT INTO parcela VALUES(20, 'ova005', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,1), -- polygon SDO_ORDINATE_ARRAY(5,10, 4,10, 2,10, 9,15, 9,16, 20,10, 5,10 ) ) ); INSERT INTO parcela VALUES(21, 'ova005', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,1), -- polygon SDO_ORDINATE_ARRAY(5,1, 8,1, 8,6, 5,7, 5,1) ) ); INSERT INTO parcela VALUES(0,'ova01', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,3), --obdelnik SDO_ORDINATE_ARRAY(1,1,5,10) ) ); INSERT INTO parcela VALUES(23, 'ova005', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(5,7, 5,10, 2,10, 1,9, 1,7, 5,7) ) ); INSERT INTO parcela VALUES(24, 'ova005', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(5,10, 5,7, 8,6, 7,10, 5,10) ) ); INSERT INTO parcela VALUES(25, 'ova001', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,1), --polygon SDO_ORDINATE_ARRAY(1,9, 2,10, 9,15, 9,20, 1,16, 1,9) ) ); INSERT INTO parcela VALUES(26, 'ova001', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,1), --polygon SDO_ORDINATE_ARRAY(9,20, 1,16, 1,20, 9,20) ) ); INSERT INTO parcela VALUES(111, 'ova005', SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1005,2, 1,2,1, 5,2,2), -- compound polygon SDO_ORDINATE_ARRAY(20,10, 8,6, 8,1, 15,3, 20,10) ) );
Tvorba prostorového indexu
Nejprve je nutno do systému zadat existenci nové tabulky s geometrickou složkou. Uložíme nový záznam přes pohled user_sdo_geom_metadata, kam zapíšeme název tabulky, jméno sloupce obsahujícího geosložku, rámec prostoru, nad kterým bude vytvořen prostorový index a souřadnicový systém, ke kterému jsou data vztažena.
INSERT INTO user_sdo_geom_metadata VALUES ('parcela', 'tvarparcela', SDO_DIM_ARRAY(sdo_dim_element('X',0,30,0.005), sdo_dim_element('Y',0,30,0.005)), NULL );
Ověření správně uložených informací: :'select * from user_sdo_geom_metadata';
Požadavek na prostorové zaindexování geometrie parcel urychlí další práce s prostorovou složkou. Bez zaindexování nelze zobrazit geometrie v prohlížeči, ani pokládat některé typy dotazů.
CREATE INDEX sp_par_idx ON parcela(tvarparcela) INDEXTYPE is mdsys.spatial_index;
Po správném vytvoření prostorového indexu je možné zobrazit geometrickou složku v GeoRaptoru. Klikněte pravým tlačítkem na název tabulky a zvolte GeoRaptor. Poté si vyberte 'Přidat do prohlížeče'. Otevře se nové okno, které je provázáno s prostorovou složkou tabulky.
Tvorba vazební tabulky VLASTNICTVI
Vytvoříme tabulku VLASTNICTVI, která zachycuje kdo je vlastníkem parcely v daném čase. Pokud ve sloupci 'doVlastni' nebude uvedena hodnota, pak je parcela ve vlastnictví majitele s odpovídajícím idVlastnik, proto je zde povolena hodnota NULL. Dále jsou při vytváření tabulky uvedena omezení, která plynou z vazby na tabulky VLASTNIK a PARCELA. Jsou zde vytvořeny cizí klíče se shodnými názvy, jako primární klíče u nadřazených tabulek.
DROP TABLE VLASTNICTVI; CREATE TABLE VLASTNICTVI( idVlastnictvi NUMBER PRIMARY KEY, idVlastnik NUMBER(6) NOT NULL, idParcela NUMBER(6) NOT NULL, odVlastni DATE NOT NULL, -- datum nabyti parcely doVlastni DATE, -- datum pozbyti parcely constraints vla_vla FOREIGN KEY (idVlastnik) references VLASTNIK, constraints vla_pa FOREIGN KEY (idParcela) references PARCELA );
Vložíme záznamy do tabulky Vlastnictví. Pro vložení hodnot datumu je využita konverzní funkce to_date, která umožňuje zadávat datum ve zvoleném formátu (zde DD-MM-YY).
insert into vlastnictvi values(1, 2, 20, to_date('01-01-07', 'DD-MM-YY'),to_date('01-01-08', 'DD-MM-YY')); insert into vlastnictvi values(2, 4, 20, to_date('01-01-09', 'DD-MM-YY'),to_date('01-01-11', 'DD-MM-YY')); insert into vlastnictvi values(3, 2, 20, to_date('01-01-12', 'DD-MM-YY'),null); insert into vlastnictvi values(4, 3, 21, to_date('01-12-10', 'DD-MM-YY'),null); insert into vlastnictvi values(5, 5, 22, to_date('01-05-13', 'DD-MM-YY'),null);
Co ukazují tyto záznamy? O jaké změny vlastnictví v čase se jedná? Tatáž parcela (s id=20) mění majitele, poté se vrací zpět prvně uvedenému vlastníkovi.
Vyhledání aktuálního vlastníka parcely s číslem id=20.
select y.jmenovla, y.prijmenivla from vlastnictvi x, vlastnik y where x.idVlastnik = y.idVlastnik and x.doVlastni is null and x.idParcela = 20;
Vyhledání aktuálních vlastníků parcel z katastrálního území 'ova005'.
select y.jmenovla, y.prijmenivla from vlastnictvi x, vlastnik y, parcela z where x.idparcela = z.idparcela and x.idVlastnik = y.idVlastnik and x.doVlastni is null and z.ku = 'ova005';
V případě, že chceme zobrazit parcely vyhledaných vlastníků, přidáme do výstupu i geometrickou složku parcely a tu zobrazíme v GoeRaptoru kliknutím na hodnoty geometrie ve výsledku dotazu.
select y.jmenovla, y.prijmenivla, z.tvarparcela from vlastnictvi x, vlastnik y, parcela z where x.idparcela = z.idparcela and x.idVlastnik = y.idVlastnik and x.doVlastni is null and z.ku = 'ova005';
Podkladová síť
Pro lepší orientaci ve vizuálních výstupech je možné si vytvořit síťový podklad ve stejném prostoru, jako jsou uloženy parcely. Jde o jednoduchou tabulku NET s dvěmi složenými geometriemi typu linie.
DROP TABLE NET; CREATE TABLE NET ( id NUMBER, geo SDO_GEOMETRY);
Vložíme dva záznamy se složeným typem geometrie (2006):
INSERT INTO net VALUES (1, sdo_geometry (2006, null, null, sdo_elem_info_array (1,2,1, 5,2,1, 9,2,1, 13,2,1, 17,2,1, 21,2,1, 25,2,1, 29,2,1, 33,2,1, 37,2,1, 41,2,1, 45,2,1, 49,2,1, 53,2,1, 57,2,1, 61,2,1, 65,2,1, 69,2,1, 73,2,1, 77,2,1), sdo_ordinate_array (0,0,0,20, 1,0,1,20, 2,0,2,20, 3,0,3,20, 4,0,4,20, 5,0,5,20, 6,0,6,20, 7,0,7,20, 8,0,8,20, 9,0,9,20, 10,0,10,20, 11,0,11,20, 12,0,12,20, 13,0,13,20, 14,0,14,20, 15,0,15,20, 16,0,16,20, 17,0,17,20, 18,0,18,20, 19,0,19,20)) );
INSERT INTO net VALUES (2, sdo_geometry (2006, null, null, sdo_elem_info_array (1,2,1, 5,2,1, 9,2,1, 13,2,1, 17,2,1, 21,2,1, 25,2,1, 29,2,1, 33,2,1, 37,2,1, 41,2,1, 45,2,1, 49,2,1, 53,2,1, 57,2,1, 61,2,1, 65,2,1, 69,2,1, 73,2,1, 77,2,1), sdo_ordinate_array (0,0,20,0, 0,1,20,1, 0,2,20,2, 0,3,20,3, 0,4,20,4, 0,5,20,5, 0,6,20,6, 0,7,20,7, 0,8,20,8, 0,9,20,9, 0,10,20,10, 0,11,20,11, 0,12,20,12, 0,13,20,13, 0,14,20,14, 0,15,20,15, 0,16,20,16, 0,17,20,17, 0,18,20,18, 0,19,20,19)) );
Před vytvořením prostorového indexu uložíme metainformace o nové tabulce:
INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) VALUES ('net', 'geo', SDO_DIM_ARRAY (SDO_DIM_ELEMENT('X', 0, 30, 0.5), SDO_DIM_ELEMENT('Y', 0, 30, 0.5)), NULL);
a vytvoříme prostorový index:
CREATE INDEX NET_SPIDX ON net(geo) INDEXTYPE IS mdsys.spatial_index;
Na výsledek se můžeme podívat v prohlížeči GeoRaptor a měl by vypadat podboně jako na obrázku podkladová síť. Tuto "vrstvu" můžeme nechat zobrazenou po celou dobu další práce, mělo by to vést k lepšímu pochopení principů, na kterých jsou postaveny topologické vztahy mezi geobjekty.
Kontrola validnosti geometrie
Pomocí metody SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT, kterou jsme již použili při práci s bodovými daty, provedem kontrolu validnosti. V dokumentaci Oracle samostatně najděte formát použití metody a její význam. Zjistěte, zda jsou námi vkládaná data validní. Pokud tomu tak nebude, opravte za správná na základě významu ohlášené chyby.
Dotazy s prostorovou složkou
V našem minikatastru budeme chtít koupit parcelu s id=24.
Kde leží je možno ověřit buď přímo přes poklikávání na geometrie při aktivním tlačítku inform v GeoRaptoru, nebo pomocí jednoduchého výběru
SELECT idparcela, tvarparcela FROM parcela WHERE idparcela=24;
a poté zobrazení geometrie v prohlížečce jako na obrázku Parcela 24.
Pokud chceme vědět, s kterými parcelami sousedí, pokusíme se vyhledat sousední parcely. Všechny, se kterými má parcela 24 nějaký dotyk (postačí jediný společný bod ve vrcholu polygonu, nemusí to být nutně společná hrana). Pro vyhledání sousedních parcel můžeme postupovat různě, zde si předvedeme využití operátoru SDO_RELATE s topologickou vazbou TOUCH.
SELECT h.idparcela SOUSEDE, h.tvarparcel FROM parcela h, parcela p WHERE p.idparcela=24 AND SDO_RELATE(p.tvarparcely, h.tvarparcely, 'mask=touch')='TRUE';
Ve výsledku máme id sousedních parcel i jejich tvary, takže při označení a kliknutí pravým tlačítkem uvidíme i umístění sousedních parcel vůči zájmové parcele.
xxxxxxxxxxxxxxxxxxx
Chceme zjistit, co se stane s parcelami v případě, že budu chtít postavit novou budovu. Jak bude vypadat průnik stavby a dotčených parcel?
Novou budovu s její geometrií uložím do tabulky STAVBA.
CREATE TABLE STAVBA (idStavba NUMBER PRIMARY KEY, typStavba VARCHAR2(8) NOT NULL, tvarStavba SDO_GEOMETRY );
INSERT INTO stavba VALUES(1122,'rodDum', SDO_GEOMETRY(2003, NULL, NULL,SDO_ELEM_INFO_ARRAY(1,1003,3),SDO_ORDINATE_ARRAY(4,6, 8,8)) );
Zopakujeme kroky se zadáním záznamu metadat o tabulce s prostorovými dat do systémové tabulky user_sdo_geom_metadat
INSERT INTO user_sdo_geom_metadata VALUES ('stavba', 'tvarStavba', SDO_DIM_ARRAY(sdo_dim_element('X',0,30,0.005), sdo_dim_element('Y',0,30,0.005)), NULL );
a vytvoříme prostorový index.
CREATE INDEX sp_stav_idx ON stavba(tvarStavba) INDEXTYPE is mdsys.spatial_index;
Zjistíme, které parcely by novou stavbou byly dotčeny?
select idparcela, SDO_GEOM.RELATE(p.tvarparcela,'anyinteract',s.tvarstavba,0.005) dd from parcela p, stavba s where s.idstavba = 1122;
Protože zasahuje i do cizích pozemků, je nutno korigovat umístění stavby
INSERT INTO stavba VALUES(222,'rodDum', SDO_GEOMETRY(2003, NULL, NULL,SDO_ELEM_INFO_ARRAY(1,1003,3),SDO_ORDINATE_ARRAY(1.5, 4.5, 4.5,6)) );
Ověřte, na které parcele je plánovaná stavba teď. Komu patří?
Bazén
Vlastník parcely 21 chce postavit nový bazén s osvětlením.
INSERT INTO stavba VALUES(1144,'bazen', SDO_GEOMETRY(2003, NULL, NULL,SDO_ELEM_INFO_ARRAY(1,1003,4), SDO_ORDINATE_ARRAY(7,2, 6,6, 8,6)) );
Plánuje nasvětlení bazénu z těchto míst:
INSERT INTO stavba VALUES(1,'sloupek1', SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(7,2, NULL), NULL, NULL) ); INSERT INTO stavba VALUES(2,'sloupek2', SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(6,6, NULL), NULL, NULL) ); INSERT INTO stavba VALUES(3,'sloupek3', SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(8,6, NULL), NULL, NULL) );
Vyjde postavit bazén požadovaného tvaru na jeho pozemku? Naformulujte dotaz, kterým je možné to ověřit.
SELECT s.idstavba, p.idparcela, SDO_GEOM.SDO_INTERSECTION(p.tvarparcela,s.tvarstavba,0.005) FROM parcela p, stavba s WHERE s.idstavba = 1144;
SELECT p.idparcela FROM parcela p, stavba s WHERE SDO_GEOM.SDO_INTERSECTION(p.tvarparcela,s.tvarstavba,0.005) is not null and s.idstavba = 1144;
Jsou alespoň sloupky na jeho pozemku?
SELECT s.idstavba, s.tvarstavba, s.typstavba FROM parcela p, stavba s WHERE SDO_CONTAINS(p.tvarparcela,s.tvarstavba) = 'TRUE' and p.idparcela=21;
Vyjde tento menší?
INSERT INTO stavba VALUES(1177,'bazen', SDO_GEOMETRY(2003, NULL, NULL,SDO_ELEM_INFO_ARRAY(1,1003,4), SDO_ORDINATE_ARRAY(7.0,2.0, 5.0,3.0, 6.0,3.0)) );
Nebo tento?
INSERT INTO stavba VALUES(1199,'bazen', SDO_GEOMETRY(2003, NULL, NULL,SDO_ELEM_INFO_ARRAY(1,1003,4), SDO_ORDINATE_ARRAY(6,2, 5.5,3.5, 6.5,3.5)) );
Kolik půdy zabere stavba posledního bazénu?
SELECT s.idstavba, SDO_GEOM.SDO_AREA(s.tvarstavba, 0.005) FROM stavba s WHERE s.idstavba = 1199; {vybrán bazén s id=1199}
Kolik by zabraly všechny bazény?
SELECT SUM(SDO_GEOM.SDO_AREA(s.tvarstavba, 0.005)) FROM stavba s WHERE s.typstavba = 'bazen';
Jak daleko je poslední bazén od sousedního pozemku (pozemek s idparcela 22)?
SELECT SDO_GEOM.SDO_DISTANCE(p.tvarparcela,s.tvarstavba, 0.005) FROM parcela p, stavba s WHERE p.idparcela=22 AND s.idstavba=1199;
Využití metod, které jsou definovány pro třídu objektů SDO_Geometry. Lze ověřit hodnoty atributů v prostorové složce objektů.
Ověření dimenze objektů:
SELECT s.idstavba, s.typstavba, s.tvarstavba.Get_Dims() FROM stavba s;
Hodnota označení typu geoobjektu, která je uložena v parametru SDO_GTYPE:
SELECT s.idstavba, s.typstavba, s.tvarstavba.Get_GType() FROM stavba s;
Ověření validnosti objektu (podle standardu "The ISO/IEC SQL Multimedia standard" pak nese označení "well formed for valid").
SELECT s.idstavba, s.typstavba, s.tvarstavba.ST_IsValid() FROM stavba s;