Professional Documents
Culture Documents
1
Sadržaj
1 Što je i zašto Python? 4
1.1 Karakteristike Pythona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Osnove programiranja 5
4 Osnove Pythona 8
4.1 Introspekcija i pomoć . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.2 Uvjetno izvršavanje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.3 Petlja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4.4 Lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4.5 Rječnik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.6 Funkcije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.7 Pretvorba tipova podataka . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
9 Linearno referenciranje 38
2
Sažetak
Python Java
Osim toga Python za terminator naredbe programa koristi oznaku za novi red, dok je kod
Jave terminator točka-zarez ;. Ovakav pristup je dvosjekli mač. Jer iako je Python kod lakše
čitati, zbog jasno prepoznatljivih blokova koda, jedna greška u formatiranju rezultira greškom
u programu. Napomena: za formatiranje koda koristiti ili razmak ili tabulator,
nikako oboje!
Za Python se često kaže da dolazi s uključenim baterijama, odnosno s velikim brojem
biblioteka i modula. Osim toga, postoji još veći broj biblioteka i modula kojima je moguće
1
http://en.wikipedia.org/wiki/Guido_van_Rossum
2
eng. whitespace
4
proširiti funkcionalnost. Zbog toga Python se koristi za izgradnju web aplikacija, obradu
podataka, interakciju s bazama podataka, razvoj korisničkih sučelja, skriptiranje procesa,
vizualizacije, …
Proširivost i jednostavnost omogućile su Pythonu široki raspon iskoristivosti, pa ga tako
koriste Youtube, Google, ILM, …, a moguće ga je koristiti za skriptiranje ArcGIS programskog
paketa, ili AutoCada kroz IronPython. Može se reći da ne donosi neke nove revolucionarne
značajke u programiranju, već na optimalan način ujedinjuje sve najbolje ideje i načela rada
drugih programskih jezika.
2 Osnove programiranja
Vjerojatno ste obradili osnove programiranja kroz neki kolegij na fakultetu, no ponoviti
ćemo neke osnovne pojmove:
program je niz instrukcija koje definiraju kako napraviti izračun, a svaki program ima sljedeće
dijelove:
ulazne kontrole ulaz podataka iz datoteka, tipkovnice, miša, …
kontrole izlaza prikaz podataka na zaslonu, spremanje u datoteku, slanje mrežom, …
matematika izvršavanje osnovnih matematičkih operacija, zbrajanje, množenje, …
uvjetno izvršavanje ovisno o uvjetima dijelovi koda će se izvršiti ili ne
ponavljanje ponovno izvršavanje koda
programiranje je proces u kojem razbijamo kompleksne zadatke na mnogo manjih koji se
mogu opisati jednostavnim operacijama, u tom procesu javljaju se greške, a proces uk-
lanjanja greški (bugova) naziva se debugging:
sintaksne krivo napisane instrukcije, npr. fi umjesto if ; najbrže se uklanjaju
izvršne greške koje se događaju tijekom izvršavanja programa, npr. ne postoji datoteka
na disku, ili nije moguće pristupiti mrežnom resursu; relativno se brzo uklanjaju
semantičke iako će se program uspješno izvršiti neće vratiti rezultat koji želimo, od-
nosno program će napraviti upravo ono što smo mu rekli da napravi; najteže se
uklanjaju
programski jezik je formalni jezik3 ; osnovni elementi jezika su simboli (riječi, brojevi, zna-
kovi, …) i struktura (određuje odnos u kojem se nalaze simboli)
Program koristi i upravlja vrijednostima, primjerice 3, Python je super!, 3.14 su
vrijednosti. Svakoj vrijednosti se može odrediti tip podatka, odnosno vrijednost je nekog tipa.
Uglavnom se razlikuju jednostavni i složeni tipovi podataka:
jednostavni tipovi kao cijeli broj int, realni broj float, datum date, niz znakova string, …
složeni tipovi su strukture koje mogu sadržavati jednostavne i složene tipove podataka, npr.
n-torka (eng. tuple) – (1,2,3,4,’Python’), lista (eng. list) – [1,2,3,4,’Python’], rječnik
(eng. dictonary) – {’broj’:123, ’naziv’:’Geodetski fakultet’}
3
formalni jezici su dizajnirani za specifičnu primjenu, tj. definirana su striktna pravila
5
Operatori su posebni simboli koji predstavljaju operacije na vrijednostima, poput zbra-
janja (+) i množenja (*). Python, kao i većina programskih jezika, ima sljedeći redoslijed
izvršavanja operatora:
1. zagrade ()
2. potenciranje **
3. množenje *, dijeljenje /
4. zbrajanje +, oduzimanje -
Ukoliko operatori imaju isti prioritet redoslijed izvršavanja je s lijeva na desno. Primjerice
izraz 2 + 3 − 5 ∗ 2, prvo će se izvršiti množenje, dakle 5 ∗ 2, nakon toga se izvršava zbrajanje
2 + 3, i tek nakon toga oduzimanje 5 − 10.
Varijabla je naziv koji povezujemo s vrijednosti, npr. broj_studenata=57 ili niz znakova
poruka=''Danas pada kiša!''. Varijable koristimo jer je lakše pamtiti i upravljati varijabla-
ma nego vrijednostima. Vrijednost se dodjeljuje varijabli upotrebom operatora dodjeljivanja
=.
Kao i svaki jezik Python definira pravila kako nazivati varijable, također treba uzeti u
obzir da razlikuje velika i mala slova:
Na kraju treba spomenuti naredbe (eng. statement) koje su izgrađene od izjava (eng.
expressions) i temeljni su građevni elementi programa. Izjava je kombinacija vrijednosti,
varijabli i operatora. Primjer naredbi:
print 1+1
moja_placa = min(sve_place)
moja_placa = moja_placa * 9.81
print ';)'
6
3 Instalacija i konfiguracija Python okoline
Za ove vježbe preporuča se upotreba verzije Python 2.7.x, koja se može preuzeti sa https:
//www.python.org/downloads/. Iako postoji i novija 3.x verzija Pythona, za ove vježbe
se zbog kompatibilnosti sa dodatnim modulima, preporuča stabilna 2.7.x verzija. Ukoliko
koristite Linux operativni sustav, Python se može pronaći u službenim repozitorijima vaše
distibucije, ukoliko već nije instaliran.
Instalacija na Windows operativnom sustavu se svodi na preuzimanje odgovarajuće dato-
teke, koja ovisi o arhitekturi (32/64 bita), i pokretanje instalacije.
Nakon instalacije u Start izborniku (Slika 1) se nalazi Python 2.6. Kroz vježbe ćemo koris-
titi IDLE (Python GUI) koji omogućava interakciju s Python interpreterom. IDLE (Slika 3)
također omogućava uređivanje datoteka, tzv. Python skripti, koje mogu jednostavno pokretati
direktno iz sučelja.
ili
>>> 1+1
2
>>> a=10
>>> b=5.5
>>> a*b
7
55
>>>
Postoji mnogo uređivača teksta i razvojnih okruženja koja omogućavaju uređivanje Python
koda. Za ovaj kolegij dovoljan će biti ugrađeni IDLE uređivač, koji se pokreće otvaranjem
postojeće Python datoteke ili odabirom File → New window. Na slici 3, prikazan je IDLE
uređivač koji sadrži samo jednu liniju print ``Dobar dan'', te nakon spremanja skripte u
datoteku test.py, pritiskom na tipku F5, interpreter će izvršiti našu skriptu.
4 Osnove Pythona
U ovom dijelu obraditi će se uvjetno izvršavanje, petlje i manipulacija listama, koje će se
intenzivno koristiti kroz kolegij.
8
Python omogućava korištenje tzv, operatora uspoređivanja čiji je rezultat istinita ili ne
istinita vrijednost. Raspoznaju se sljedeći operatori uspoređivanja: ==, !=, >, <, >= i <=.
Osnovna forma uvjetnog izvršavanja je sljedeća:
if a > 100:
a = a + 10
elif a > 10:
a = a + 1
else:
a = 0
Nakon ključne riječi if definira se uvjet. Uvjeti se povezuju Booleovim operacijama, npr.
(a > 10 and a < 20) or a >= 50. Nakon definicije uvjeta početak novog bloka označava
se znakom :, poslije kojeg se u novom redu blok uvlači praznim prostorom. Ukoliko postoji
potreba zadovoljavanja dodatnih uvjeta koristi se ključna riječ elif, a svi ostali ne zadovoljeni
slučajevi izvršavaju se u bloku definiranom ključnom riječi else.
4.3 Petlja
Petlja omogućava ponovno izvršavanje bloka koda, koje nazivamo iteracija. Petlja se iz-
vršava dok je zadovoljen uvjet, odnosno dok je uvjet istinit. Sljedeći blok koda prikazuje
osnovnu petlju koja odbrojava od 10 do 1:
n = 10
while n > 0:
print n
n = n - 1
U programiranju se često koriste tzv. “beskonačne petlje” za koje se uvjet nikad ne zado-
volji nego se program završava na neki drugi način, npr. kombinacijom tipki CTRL+C.
4.4 Lista
Lista je poredan i indeksiran niz elemenata, što znači da se svakom elementu može pristupiti
preko indeksa. Prvi element liste ima indeks 0, tzv. “zero-based”, drugi element liste ima
indeks 1 itd. Lista može sadržavati različite tipove podataka, npr. ["hello", 2.0, 5, [10,
20]]. Lista se definira uglatim zagradama [ ], a elemente liste odvajaju zarezi.
Pristup nekom članu liste moguć je preko indeksa, primjerice trećem elementu liste pris-
tupiti ćemo na sljedeći način:
lista = ['danas','je','petak',13,2010]
print lista[2]
print len(lista)
print 'danas' in lista
print 'sutra' in lista
del lista[1]
9
Funkcija len vraća koliko lista ima elementa, tzv. dužinu liste, a operator in pripadnost nekog
elementa listi. Funkcija del briše element liste.
Liste omogućavaju odabir podskupa liste, operatorom :, primjerice kada bi željeli podskup
od drugog do trećeg elementa to bi napravili na sljedeći način nova_lista=lista[1:3]. Mo-
guće izostaviti jedan od indeksa, npr. nova_lista=lista[:3] čime bi napravili podskup od
prva tri elementa liste.
Iterator omogućava hodanje po listi, element po element. Sljedeći primjer ispisuje samo
parne brojeve koji se nalaze u nekoj listi:
lista=[1,4,6,2,5,67,24,52,21,31]
for element in lista:
if element % 2 == 0:
print element, ' je paran broj!'
4.5 Rječnik
Jedna od vrlo korisnih struktura podataka u Pythonu je rječnik (eng. dictonary). Za
razliku od lista koje su indeksirane prema rednom broju elementa unutar liste, rječnik je
indeksiran prema ključu. Svaki element rječnika sadrži ključ prema kojem se pretražuje i
vrijednost za taj ključ. Upravo zbog ovoga, ova struktura se još naziva i ključ-vrijednost
struktura. Ključevi su uglavnom brojevi ili string tip podatka dok vrijednost može bili bilo
koji drugi objekt (tip podatka). Rječnici nisu poredani kao što je to slučaj s listama tako
da lokacija elementa unutar rječnika je promjenjiva, za razliku od lista. Vrijednosti ključa
su unikatne unutar jednog rječnika dok vrijednosti ne moraju biti. Ovdje su neki primjeri
rječnika:
Element rječnika se upisuje na način da se prvi definira ključ (‘hrvoje’, ‘marko’, ‘ana’), a
nakon toga vrijednosti za pojedine ključeve, u ovo slučaju to su brojevi 1234, 4251 i 2415.
Kod lista smo svakom elementu liste pristupali pomoću rednoga broja unutar same liste,
kod rječnika pristupamo pomoću ključa. U gornjem primjeru tražimo vrijednost rječnika za
ključ ‘ana’. Ukoliko želim dodati neki novi član unutar rječnika, dodajemo ga na način da
jednostavno kreiramo novi ključ sa nekom vrijednosti. Ukoliko taj ključ već postoji unutar
tog rječnika, stara vrijednost će biti izbrisana novom. Ovo također znači da ukoliko kreiramo
rječnik koji sadrži elemente s istim ključem, samo zadnji ključ će biti spremljen.
10
Ukoliko želimo saznati koji se sve ključevi nalaze unutar nekog rječnika, to činimo sa
funkcijom keys().
print rjecnik1.keys()
## ['ivan', 'marko', 'ana']
'hrvoje' in rjecnik1.keys()
## False
Ponekad je potrebno iterirati preko svih elemenata nekog rječnika. Najjednostavniji način
je pomoću iterimes() funkcije.
## ivan 9521
## marko 4251
## ana 2415
4.6 Funkcije
Funkcija je niz naredbi koja izvršava željenu radnju. Funkcija ima zaglavlje i tijelo. Zaglav-
lje funkcije počinje ključnom riječi def nakon koje sijedi naziv funkcije, pa lista parametara
poslije koje slijedi : . Tijelo funkcije je uvučeno kao i svaki drugi blok koda. Bitno je naglasiti
da su parametri i varijable unutar funkcije dostupni samo unutar funkcije. Funkcije koje ne
vračaju vrijednost nazivaju se procedurama. Npr. str() funkcija pretvara integer/decimal u
string.
def ispisi(broj):
print "Broj: " + str(broj)
ispisi(3)
def kvadriraj(broj):
kvadrat=broj*broj
return kvadrat
kvadrati=[kvadriraj(2),kvadriraj(3),kvadriraj(9)]
11
• kompleksne vrijednosti (complex)
U prethodnom poglavlju smo već vidjeli na koji način možemo pretvoriti decimal/integer
tip podatka u string tip. Ova pretvorba je prilično jednostavna jer se brojevi sami po sebi
mogu napisati kao skup alfanumeričkih znakova tj. string. S druge strane, obrnuti proces, iz
decimal/integer u string ili iz decimal u integer tip podatka je malo složeniji proces. Uzmimo
sljedeće primjere,
>>> x= '2'
>>> y='2.3'
>>> float(x)
2.0
>>> float(y)
2.2999999999999998
>>> int(x)
2
>>> int(y)
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '2.3'
>>> z = 8.62
>>> int(z)
8
>>> float(z)
8.6199999999999992
>>>
Ovdje vidimo da kod pretvaranje brojčane string vrijednosti u decimal/integer nije svejedno
koju vrijednost pretvaramo. Razlog greške je zbog toga što nije moguće jednoznačno odrediti
integer vrijednost od stringa ’2.3’. Također, možemo vidjeti da pretvorba decimal string vri-
jednosti u decimal tip podatka također nije jednostavna. Pretvorba stringa ’2.3’ u decimal kao
rezultat daje 2.2999999999999998. Iako približna vrijednost je 2.3, to nije vrijednost koja je
očekivana. Razlog ovakvog rezultata je izvan domene ovog kolegija te ukoliko vas više zanima
o tome možete pogledati u literaturi ili na internetu pojmove poput Floating Point Arithmetic
ili Floating Point Precision.
12
Sažetak
U prvoj liniji koda definirana je kodna stranica koja se koristi, to nije nužno, ali omogu-
ćava lakšu prenosivost koda. Nakon toga se u trenutnu izvršnu okolinu učitavaju moduli i
14
objekti. Specifično učitavamo objekte Polygon, LineString, Point, MultiPoint, … iz biblioteke
shapely.geometry. Da bi neki objekt mogli koristiti, moramo ga (tj. njegovu definiciju) učitati
u trenutnu okolinu izvršavanja programa. U ovom slučaju je to IDLE okolina. Također učitava
se pyplot iz matplotlib biblioteke koji ćemo kasnije koristiti.
Ovdje smo definirali dvije točke s koordinatama 4, 4 i 1, 2 nekog prostornog sustava. Objekt
Point se inicijalizira s dva parametra x i y koordinatom. Ove vrijednosti smo pridružili
varijablama tocka1 i tocka2.
Na sličan način stvoriti ćemo linijski objekt LineString linija1. LineString objekt kao
parametar uzima listu s koordinatnim n-torkama, u ovom slučaju s dva elementa. Gotovo
identično stvaramo poligon1. Razlika između LineString i Polygon objekta je što su prva i
zadnja koordinata iste u Polygon objektu. U bilo kojem trenutku možemo saznati više o
objektu korištenjem introspekcije ili pomoći, što je opisano u prvoj vježbi.
Objekt MultiPoint je kolekcija više točaka, kao i MultiLineString te MultiPolygon. Postoji
i tzv. GeometryCollection kao skup različitih geometrija, ali se ne koristiti često u praksi jer
neke funkcije se ne mogu izvršavati nad ovim objektom te je vrlo upitna iskoristivost podataka
spremljenih u ovom obliku. GeometryCollection objekte neće stvarati, ali se mogu pojaviti
kao rezultati nekih funkcija.
15
#racuananje duzine objekta linija1. Tocka nema duzinu pa ce
#tocka1.lenght vratiti vrijednost 0.0
duzinaLinije1 = linija1.length
Informacija o tome da li je neki objekt “prazan” korisna je kada nakon neke operacije
želimo saznati postoje li rezultati te operacije. Znači, ako tražimo sjecište dvije linije, ukoliko
se te dvije linije sjeku, rezultat će biti točka, u suprotnom biti će “prazna” geometrija točke.
Ispitivanje da li je objekt “prazan” se testira pomoću atributa is_empty.
Pomoću atributa x i y, dolazimo do za točku jedinstvene vrijednosti koordinata X i Y. No
ako pristupimo istim atributima linije ili poligona dobiti ćemo liste x i y koordinata.
16
#ispisuje kojeg je tipa poligon2 objekt.
#Funkcija vraća vrijednost Point, LineString, Polygon, MultiPolygon ...
poligon2.geom_type
Jednakost dva objekta može se utvrditi funkcijom equals, u ovom slučaju napraviti ćemo
kopiju objekta linija1. Linije su identične, pa će i funkcija equals vratiti istinitu vrijednost
(True). Moguće je uspoređivati različite tipove geografskih objekata, ali ako nisu identični,
equals funkcija će vratiti ne istinitu vrijednost (False).
17
Prije nego iscrtamo točke ili objekte moramo pripremiti koordinate u obliku koji očekuje
matplotlib. Srećom postoji funkcija xy koja će vratiti x i y koordinate u obliku liste dužine
dva, odnosno dva elementa, upravo onako kako ih očekuje plot metoda. U primjeru koda
možete vidjeti prvi element liste se sprema u varijabli xLista, a drugi element liste u varijablu
yLista. Nakon toga pozivamo metodu plot kojoj predajemo liste koordinata i definiramo stil.
O stilovima se može više saznati u dokumentaciji, a u ovom primjeru svaka točka se prikazuje
kao crveni kvadrat (”rs” = Red Square).
Na sličan način se iscrtava linija, no ovdje liniju crtamo plavom isprekidanom crtom.
Poligoni su nešto problematičniji jer se proces iscrtavanja razdvaja u dva dijela. Prvo se
crta unutrašnjost poligona, odnosno ispunjava se, a nakon toga crta obrub. Kako bi iscrtali
poligon moramo iskoristiti njegovu granicu, a do granice dolazimo preko atributa exterior.
Na kraju ostaje nam samo prikazati iscrtano, matplotlib ima ugrađeni preglednik koji se
poziva metodom show. Ukoliko sliku želimo iskoristiti na neki drugi način, uvijek je možemo
spremiti u rastersku datoteku, u primjeru je to PNG formata.
5.4 Zadatak 1
18
NAPOMENA:
Ovaj zadatak je obavezan. Rješenje treba postaviti na e-ucenje na odgovarajuće mjesto.
19
Sažetak
poligon1 = Polygon([(1,2),(3,4),(6,5),(4,2),(3,3),(1,2)])
poligon2 = Polygon([(4,6),(5,3),(10,5),(7,7),(4,6)])
linija1 = LineString([(3,7),(7,5),(7,2)])
linija2 = LineString([(1,4),(3,4),(6,5),(8,7)])
tocka1 = Point(5,4)
tocka2 = Point(4,3)
tocka3 = Point(2,5)
21
#objekta poligon1
poligon1.contains(tocka1)
#objekt tocka3 se na nalazi unutar objekta poligon1 i funckija vraca
#vrijednost False
poligon1.contains(tocka3)
Želimo li ispitati križa li linija poligon (definiciju križanja potražite u predavanjim) koristit
će se funkcija crosses. Zanimljivo je da linija ne križa samu sebe kao što se može vidjeti u
primjeru. Funkcija disjoint je vrlo korisna, jer omogućava utvrđivanje da li postoji bilo kakav
prostorni odnos između dva objekta.
Funkcija intersects određuje da li objekt dodiruje granicu ili presijeca unutrašnjost nekog
drugog objekta. Razlikuje se od križanja po tome što križanje provjerava da li se vanjština
jednog objekta preklapa s unutrašnjosti drugog objekta. Intersects će vratiti istinitu ili ne
istinitu vrijednost.
Funkcija touches vratit će istinitu vrijednost ukoliko se granice, dva objekta dodiruju.
#naredba vraca True jer linija2 dodiruje poligon1 bez da ulazi u njega
linija2.touches(poligon1)
22
geometrijski centar poligona. Podsjećam da se geometrijski centar može nalaziti i izvan po-
ligona, primjerice ukoliko imamo poligon oblika tupog trokuta. Ukoliko želim točku koja se
uvijek nalazi unutar poligona, koristiti ćemo funkciju representative_point.
Razliku između dva objekta možemo saznati upotrebom funkcije difference. Ukoliko tra-
žimo razliku dva poligona rezultat će biti novi poligon. Tražimo li razliku između poligona i
linije rezultat će biti poligon, ali ako se traži razlika između linije i poligona, rezultat će biti
linija (Multilinija u našem slučaju). Ne postoji univerzalan odgovor koji je krajnji rezultat ove
funkcije jer ovisi koja dva prostorna objekta se uspoređuju.
23
poligon2.difference(poligon1) #vratiti će poligon, dio od poligon1 koji nije u poligon2
24
linija1.difference(poligon2) #vratiti će liniju
poligon2.symmetric_difference(poligon1)
Suprotno od funkcije difference je funkcija intersection, koja će kao rezultat dati zajednički
dio oba prostorna objekta.
25
poligon1.intersection(poligon2) #vratiti ce poligon
Dvije geometrije možemo zbrojiti funkcijom union. No treba biti oprezan oko tipa objekta,
npr. ako se želi napraviti zbroj poligona i linije rezultat će biti kolekcija geometrije. Kao i
kod funkcije difference, krajnji rezultat ovisi o odnosu tih dviju geometrija.
26
poligon1.union(linija1) #vratiti ce kolekciju geometija
Ukoliko bi željeli zbrojit više od dvije geometrije, morali bi prvo zbrojiti prvu i drugu, nakon
toga, rezultatu tog zbrajanja dodati treću geometriju itd. Koristeći funkciju unary_union
možemo zbrojiti listu geometrija odjednom.
Funkcija buffer će vratiti “tampon zonu” nekog objekta u obliku poligona. Funkcija kreira
novi poligon na određenoj udaljenosti od izvorne geometrije.
27
Funkcija convex_hull će vratiti najmanji poligon koji obuhvaća zadanu geometriju ili ko-
lekciju geometrija.
Funkcija envelope će vratiti najmanji mogući pravokutnik koji obuhvaća zadanu geometriju
ili kolekciju geometrija
tocka1.union(poligon2).envelope
Ukoliko bi željeli napraviti paralelnu liniju nekom linijskom objektu odmaknutu za određe-
nu udaljenost, možemo iskoristiti funkciju parallel_offset. Ova funkcija kao argument prima
udaljenost novije linije od linijskog objekta te stranu odmaka, gledajuću njezin smjer.
28
#funkcija koja vraća liniju paralelnu nekom linijskom objektu
paralelnaLinija = linija2.parallel_offset(1, 'left')
6.3 Zadatak 2
NAPOMENA:
Ovaj zadatak je obavezan. Rješenje treba postaviti na e-ucenje na odgovarajuće mjesto.
29
Sažetak
Slika 7: Katastarski podaci unutar SHP datoteke koja se koristi za ovu vježbu
U gornjem dijelu koda, iz Shapely modula učitavamo funkciju loads koja nam indirektno
pomaže da pretvorimo OGR prostorni objekt u shapely prostorni objekt. Ovo je potrebno
napraviti jer OGR i Shapely su dva nezavisna modula. Jedan se koristi za učitavanje prostornih
podatka iz vanjskih izvora (OGR) dok drugi se koristi za prostornu analizu i manipulaciju
prostornih podataka (Shapely).
Modul OGR omogućava nam manipulaciju velikim brojem prostornih formata podataka
(poput DXF, GPX, PostgreSQL itd.) upotrebom standardnog programskog sučelja. U ovom
slučaju OGR ćemo koristiti za učitavanje geometrije iz SHP datoteke. Kasnije će se ta geome-
trija pomoću funkcije loads transformirati u format koji odgovara Shapely modulu.
#definica funkcije koja sluzi za crtanje jednog poligona
def crtajPoligon(poligon,graf):
31
xLista,yLista = poligon.exterior.xy
graf.fill(xLista,yLista,"y")
graf.plot(xLista,yLista, "k-")
Ovaj dio koda predstavlja pomoćnu funkciju crtajPoligon koja iscrtava poligone na neku
crtaču površinu tj. na graf. Iako ovaj dio nije nužan, demonstrira kako napraviti reorganizaciju
koda s ciljem boljeg razumijevanja i preglednosti koda.
32
Funkcija GetNextFeature čita trenutni objekt iz sloja te se pomiče na sljedeći, odnosno pri
sljedećem pozivanju funkcije GetNextFeature taj sljedeći objekt postaje trenutni. Ovakav način
pristupa objektima (u ovom slučaju katastarskim česticama) nam omogućava iskorištavanje
petlje while. Petlja će se ponavljati sve dok varijabla cestica ima vrijednost. Ovaj način
iteracije objekata je vrlo čest u programiranju.
U navedenom kodu, prvo dohvaćamo geometriju objekta funkcijom GetGeometryRef(),
nakon toga tu geometriju izvozimo u WKB format (Well Known Binary) pomoću funkcije
ExportToWkb. Geometriju u WKB formatu prosljeđujemo funkciji loads iz Shapely modula,
koja vraća geometriju čestice u formatu iskoristiv za iscrtavanje. Ovi koraci su potrebni da bi
geometriju iz OGR formata pretvorili u shapely format. Tek nakon što geometriju pretvorimo
u shapely format, možemo ju iskoristiti za prostorne funkcije i operacije koje dolaze sa Shapely
modulom.
Sljedeći korak je pozivanje prethodno pripremljene funkcije za crtanje poligona crtajPoligon
kojoj kao argumente postavljamo varijable geomtriju geometrijaCestice i površinu za crtanje
ax. Nakon toga uzimamo sljedeći objekt iz sloja, a petlja se ponavlja.
Funkcijom GetFieldAsString(1) izvlačimo podatke o pojedinoj čestici na prvoj (1) koloni u
atributnoj tablici, u našem slučaju je to kolona KC_BROJ. SHP datoteka sadrži više kolona.
Ako bi željeli saznati podatke o općini pojedine čestice umjesto 1 upisali bi 2.
Pomoću Destroy funkcije “uništavamo” objekt datoteka. Ovo nije toliko bitno u ovom
slučaju, ali je dobra praksa uništiti objekte koji pokazuju prema datoteci ili na bazu.
Za kraj pozivamo funkciju za crtanje, koja prikazuje čestice učitane iz SHP datoteke.
#iscrtavamo cestice
pyplot.show()
datoteka = ogr.Open("../katastar.shp")
sloj = datoteka.GetLayerByName("katastar")
kc1289Geometrija = ''
cestica = sloj.GetNextFeature()
33
while cestica is not None:
if cestica.KC_BROJ == '1289':
kc1289Geometrija = loads(cestica.GetGeometryRef().ExportToWkb())
cestica = sloj.GetNextFeature()
sloj.ResetReading()
cestica = sloj.GetNextFeature()
datoteka.Destroy()
U ovom primjeru je prikazano na koji način se koristi ResetReading funkcija. Prvo smo
pomoću jedne petlje pronašli česticu 1289 te ju spremili u varijablu kc1289Geometrija. Nakon
toga smo morali resetirati kursor na početak jer smo došli do kraja datoteke. Drugom petljom
smo tražili koje čestice se dodiruju s česticom 1289.
7.3 Zadatak 3
NAPOMENA:
Rješenja ovih zadataka biti će objašnjenja na narednim vježbama. Izrada ovog zadatka nije obavezna,
već služi kao samostalna vježba dosada naučenoga te kao priprema za kolokvij. Stoga, preporučeno je
da samostalno izradite ove zadatke prije nego dobijete rješenja od asistenata.
2. Odrediti broj čestica koje presijeca linija definirana točkama 425345,5039528 i 425466,5039527
Dodatni zadaci:
34
4. Ispisati sve čestice koje se nalaze (ili presijecaju) buffera 100 metara linije definirane
točakama 425345,5039528 i 425466,5039527
6. Izračunajte koja je najveća udaljenost između dva poligona u zadanom setu podataka i
ispišite dva najudaljenija poligona
7. Izračunajte dužinu ruba buffera (50) linije definirane točakama 425345,5039528 i 425466,5039527
35
Sažetak
datoteka = ogr.Open("../podaci/katastar.shp")
sloj = datoteka.GetLayerByName("katastar")
cestica = sloj.GetNextFeature()
datoteka.Destroy()
Ovaj dio koda je vrlo sličan onome u prijašnjoj vježbi, samo umjesto da čitamo vrijednost
atributa prema mjestu na kojem se nalazi unutar tablice (GetFieldAsString(0)), ovdje ju či-
tamo dirketno putem imena polja. Broj čestice dobivamo direktnim pozivanjem imena polja
nad OGR objektom čestice,a opcinu pomoću GetField funkcije. Sva tri načina su ispravna.
str() funkciju smo koristili jer rezultat funkcije area je brojčana vrijednost, a potreban nam
je string.
datoteka = ogr.Open("../podaci/katastar.shp")
sloj = datoteka.GetLayerByName("katastar")
37
sloj.SetAttributeFilter('kc_broj = "4190/11" AND ko_naziv = "Karlovac II"')
cestica = sloj.GetNextFeature()
geometrijaCestice = loads(cestica.GetGeometryRef().ExportToWkb())
print 'Opseg cestice s oznakom 4190/11 je ' \
+ str(geometrijaCestice.length) + " m."
datoteka.Destroy()
SetAttributeFilter() funkcija kao parametar uzima string koji se sastoji od WHERE uvjeta
(podsjetite se kolegija Baze podataka i SQL WHERE uvjeta).
9 Linearno referenciranje
Linearno referenciranje je metoda definiranja objekta u prostoru pomoću negove udalje-
nosti duž nekog linijskog objekta. Najbolji primjer ovoga bi bila cesta i kilometarska oznaka
na cesti. Ukoliko kažemo da se nešto nalazi na 10-tom kilometru od Zagreba na cesti A1 te
ukoliko imamo liniju ceste A1 u nekom koordinatnom sustavu, možemo dobiti točnu lokaci-
ju (koordinatu) tog objekta. Linearno referenciranje je moguće samo na linijskim (krivulje)
objektima.
Uzmimo liniju iz prethodnih vježbi te odredimo koordinatu točke koja se nalazi na 3 metra
od početka te linije (pod pretpostavkom da su koordinate linije također u metrima).
linija2 = LineString([(1,4),(3,4),(6,5),(8,7)])
tocka_na_3m = linija2.interpolate(3)
print tocka_na_3m.wkt
#dobijemo POINT (3.948683298050514 4.316227766016838)
print linija2.length
#dobijemo 7.99070478491
Ukoliko bi zadana udaljenost od početka bila veća nego što je ukupna dužina cijele linije,
kao rezultat bi dobili zadnju točku bez obzira na zadanu vrijednost. Također, ukoliko bi za
udaljenost unijeli vrijednost od 0, dobili bi početnu točku linije.
38
tocka_na_10m = linija2.interpolate(10)
print tocka_na_10m.wkt
#dobijemo POINT (8 7)
tocka_na_0m = linija2.interpolate(0)
print tocka_na_0m.wkt
#dobijemo POINT (1 4)
Ovo je jedan od načina koji je moguće dobiti koordinatu točke pomoću linearnog referen-
ciranja. Drugi način je da umjesto da upisujemo točnu vrijednost udaljenosti, da upišemo
normaliziranu vrijednosti tj. vrijednost od 0 do 1. Vrijednost 0 označava početak linije, a 1
kraj linije. Uzmimo da želim izračunati koordinatu točke točno na polovici linije. Umjesto da
računamo na kojoj je udaljenosti točno polovica linije, možemo tu vrijednost dobiti pomoću
normalizirane vrijednosti tj. u ovom slučaju 0.5 .
39
Slika 8: Točka na 10% udaljenosti od početka linije (plava) i točka na kraju te linije (zelena).
40
Sažetak
def crtajPoligon(poligon,graf):
xLista,yLista = poligon.exterior.xy
graf.fill(xLista,yLista,"y")
graf.plot(xLista,yLista, "k-")
pyplot.show()
Kao i do sada, prvo učitavamo potrebne module, fiona, shapely i matplotlib. Nakon toga
definiramo područje gdje će se iscrtatvati čestice te pomoćnu funkciju crtajPoligon za crtanje
svake pojedine čestice. Za razliku od dosadašnjeg način otvaranja datoteka, ovdje koristimo
praktičniji način pomoću with izraza. Pomoću njega lakše kontroliramo učitavanje datoteka,
u ovom slučaju SHP datoteke. Ovo nije specifično za Fiona modul već za Python programski
jezik. Varijabla datoteka postaje iterator koji je moguće iterirati kao što je prikazano u
prijašnjim vježbama na listama. Ostatak koda je identičan kao i u poglavlju 7. Odmah se
vidi koliko je jasnije napisan kod i jednostavniji za čitati.
42
i intuitivniji.
geomtocka = Point(300,440)
nova_tocka = {}
nova_tocka['geometry'] = mapping(geomtocka)
nova_tocka['properties'] = {'naziv' : 'Moja druga tocka'}
datoteka.write(nova_tocka)
• koji je format novostvorene datoteke, u ovom slučaju to je SHP, ali može biti bilo koji
drugi OGR podržani format
Unutar with izraza, definirane su dvije shapely točke sa koordinatama (276, 443) i (300,440)
te su spremljene u varijablu geomtocka. Ukoliko želimo dodati novi zapis unutar nove SHP
datoteke moramo kreirati novi rječnik koji će sadržavati geometriju zajedno sa atributima.
Cilj je napraviti rječnik koji će imati strukturu u obliku GeoJSON-a. Koristeći mapping
funkciju, pripremamo shapely geometriju za GeoJSON format koji zahtijeva fiona modul.
Pomoću varijable datoteka zapisujemo (write) rječnik koji smo prethodno napravili, unutar
SHP datoteke. Nakon što izvršavanje koda izađe iz with bloka, varijabla datoteka se automatski
zatvara te ne moramo ju posebno zatvarati kao što je to bio prije slučaj kada nismo koristili
with izraz.
Ovdje smo vidjeli vrlo jednostavan primjer stvaranja nove SHP datoteke. U sljedećem
primjeru biti će prikazan primjer stvaranja nove SHP datoteke koristeći podatke iz postojeće
43
SHP datoteke. Iz datoteke katastar.shp izvući ćemo samo čestice koje imaju broj čestice ”897”,
”898” i ”899” te ih spremiti u datoteku dio_katastra.shp.
Ovdje možemo vidjeti da se koriste dva with izraza, jedan kojim otvaramo postojeću da-
toteku (katastar.shp) i drugi za novu datoteku (dio_katastra.shp). Unutar drugog with izraza
iteriramo preko svih postojećih čistica i tražimo samo one koje imaju broj čestice ”897”, ”898”
ili ”899”. Možemo primjetiti da ne moramo stvoriti novi rječnik jer varijabla cestica je rječnik
(u GeoJSON obliku) te ju možemo direktno spremiti u novu datoteku.
44