AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
03 Geographic scripting in uDig - halfway between user and developer
1. Open Source GIS
Geographic scripting in uDig - halfway
between user and developer
Geoinformation Research Group, Department of Geography
University of Potsdam
March 2013
The scripting console
Tutor: Andrea Antonello
ydroloGIS nvironmental ngineering
HydroloGIS S.r.l. - Via Siemens, 19 - 39100 Bolzano www.hydrologis.com
2. The Geoscript editor
Scritping is one of the powerful things in GIS. Non developers have the
possibility to create great automatisations through it.
uDig's scripting console is based on the groovy java scripting language.
The geoscript geographic scripting engine can be used from within uDig.
3. Open the console
Two icons can be used to open the scripting editor: one for creating a new
empty script and one to open an existing script.
4. Let's create a new one. The user will be prompted to save the new script to
file and an empty editor is opened.
There are a few tool inside the editor, needed to start and stop scripts, or set
the heap memory allowed to be used by a script or enable logging.
5. Script away, with command completion and syntax coloring
Inside the editor some basic command completion is available. For geoscript
objects, as for example the widely use Geometry:
6. but also for methods, as for example the fromWKT, a handy way to create
geometries on the fly:
7. The base language: be Groovy!
In order to be able exploit 100% the console and scripting engine, it is
mandatory to get a good insight of the base language that can be used in the
console.
Before we start with the geo part, we will investigate a bit groovy.
Let's create a new script to do so. We should find ourself in front of a nice
empty editor.
8. Writing strings
To run your first script, simply write the following in the editor
// write a string
println "This is a string"
and push the play button.
The result should be the following inside the console window:
Process started: 2013-02-10 18:02:03
This is a string
Process finished: 2013-02-10 18:02:04
The script simply prints the string in the console. It also gives information
about the start and end timestamps of the script execution.
Note that the editor executes only the selected text inside the editor. If
nothing is selected, all of it is used.
9. Also more complex strings can be used, by surrounding text with triple
quotes:
// write a complex string
println """Inside triple quotes
you can
do almost anything.
It is kind of an advanced string!"""
Select only the second part and see if it is executed properly.
10. Variables
// define variables
// a string
def name = "Luis"
// a number
def age = 25
/*
* insert the variables into a string template
* through the use of ${}
*/
def myTemplate1 = "Hi, my name is ${name} and I'm ${age}."
println myTemplate1
// strings and numbers can also be concatenated through the + sign
def myTemplate2 = "Hi, my name is " + name + " and I'm " + age + "."
println myTemplate2
11. Lists
// working with lists
// create a list of strings
def list = ["Merano", "Bolzano", "Trento"];
println list;
// how to access the elements?
println "The elements start at position 0: " + list[0]
// how to add an element to the list?
list << "Potsdam"
println list;
// how to remove an element from the list?
// by object?
list.remove("Potsdam")
println list;
// better by index
list.remove(0)
println list;
12. Lists magic - part 1
// lists magic - part 1
def list = ["Merano", "Bolzano", "Trento"];
// to loop over a list the default 'it' can be used
list.each {
println it
}
// ...or your very own variable...
list.each{ myVar ->
println "This a town: " + myVar
}
// ...or you can use an index, too
list.eachWithIndex{myVar, i ->
println "${myVar} is town N.${i}"
}
13. Lists magic - part 2
// lists magic - part 2
def list = ["Merano", "Bolzano", "Trento"];
println "This is the original list: " + list
// lists can be sorted
list.sort();
println "This is the sorted list: " + list
// and reverse sorted
def revList = list.reverse();
// note that while sort changes the original list, reverse makes a copy
println "This is list after the sorting: " + list
println "This is reverse list: " + revList
println "This is list after the reverse sorting: " + list
14. Lists magic - part 3
// lists magic - part 3
// concatenate list
def abc = ["a", "b", "c"]
def cde = ["c", "d", "e"]
def newabcde = abc + cde
println newabcde
// through 'join' the list can be concatenated to one single string
println newabcde.join(",")
println newabcde.join(" | ")
// if we are talking about numbers, some functions apply
def nums = [1.0, 2, 3.5]
println nums.max()
println nums.min()
println nums.sum()
15. Lists magic - part 4
// lists magic - part 4
// modify each element of the list with collect
def abc = ["a", "b", "c"]
println "Original abc: " + abc
abc = abc.collect{
it += " is a letter"
}
println "Modified abc: " + abc
// flatten nested lists
def abc = ["a", "b", "c"]
def cde = ["c", "d", "e"]
abc << cde
println abc
println abc.flatten()
16. Maps (Hash)
Groovy speaking a Map is a container of key and value pairs.
// working with maps
// create a map
// key1:value1, key2:value2, ...
def townsProvinceMap = [merano:"BZ", bolzano:"BZ", trento:"TN"]
println townsProvinceMap
// ways of accessing the values of a map
// implicit
println townsProvinceMap.merano
// the "array" way
println townsProvinceMap["merano"]
// through the "getter"
println townsProvinceMap.get("merano")
// ways to add an element
// implicit
townsProvinceMap.lagundo = "BZ"
println townsProvinceMap
// through the put method
townsProvinceMap.put("Postdam", "BR")
println townsProvinceMap
17. Maps magic
// maps magic
def townsProvinceMap = [merano:"BZ", bolzano:"BZ", trento:"TN"]
// iterate the thing with the default value...
townsProvinceMap.each{
println it
}
// ...or with key and value separated...
townsProvinceMap.each{
println "${it.key} is in province of ${it.value}"
}
// ...or with own vars
townsProvinceMap.each{key, value ->
println "${key} is in province of ${value}"
}
18. Ranges
Range can be seen at first as a sequence, but there is much more behind it.
// working with ranges
// create a range
def range = 1..3
// do some iterations
range.each{
println it
}
range.each{
println "what?"
}
// and what about dates?
def now = new Date();
def nextWeek = now + 7;
(now..nextWeek).each{
println it
}
// since ranges have a from, to and size...
println "A range from " + range.from + " to " + range.to + " of size " + range.size()
// ...you can use them in for loops...
for (i in 1..3){
println "step number: ${i}"
}
// ...which ovbiously could be done like the following
(1..3).each{
println "closure step number: ${it}"
}
19. Groovy: working with files & filesystem
Groovy allows to access the OS-environment and read the filesystem.
// working with the filesystem
// get system info
System.env.each{ println it}
// get the home folder
def userHome = System.getenv("HOME")
println userHome
// list a folder's content
def home = new File(userHome)
println "The contents of " + home.absolutePath + " are:"
home.eachFile{ file ->
println "t" + file
}
// list only folders
println "...of which folders:"
home.eachDir{ dir ->
println "t" + dir
}
// list only files
println "...of which files:"
home.eachFile{ file ->
if(file.isFile())
println "t" + file
}
// recursive list content
println "Recursive folders content:"
home.eachDirRecurse{ dir ->
println "t" + dir
}
20. Reading Files
// reading files
// start with creating a new file to be read afterwards
def newFile = new File(System.getenv("HOME") + "/testFileToBeRemoved.txt");
// one way to writ text to file
newFile.write("""A new header.
A new testline.
A second testline.
""")
// read the file line by line
newFile.eachLine{ line, index ->
println "line " + index + ". " + line
}
// read the file into a string variable
def content = newFile.text
println content
21. Writing Files
// writing files
def file = new File(System.getenv("HOME") + "/testFileToBeRemoved.txt");
println file.text
// append some content
file << "Some text after the last line is appended!"
println file.text
// merge files
def file2 = new File(file.absolutePath + "2")
file2.write("Content of file 2");
println file2.text
def mergedFile = new File(file.absolutePath + "_merged")
mergedFile << file.text
mergedFile << file2.text
println "nThe merged file:"
println mergedFile.text
// delete the files
file.delete()
file2.delete()
mergedFile.delete()
23. Groovy: Data structures for complex scripts
// working with data structures
// create a data structure
class Record {
def id
def lat
def lon
def elev
public String toString(){
"Values: [${id}, ${lat}, ${lon}, ${elev}]"
}
}
// read the csv into a list of records
def file = new File(System.getenv("HOME") + "/sample.csv");
def recordsList = []
file.eachLine{
if(it.trim().length() > 0 && !it.startsWith("#")) {
def lineSplit = it.split(",")
def record = new Record()
record.id = lineSplit[0]
record.lat = lineSplit[1]
record.lon = lineSplit[2]
record.elev = lineSplit[3]
recordsList << record
}
}
println recordsList
24. Groovy: most important conditions and loops
If-then-else:
def x = false
def y = false
if ( x ) {
x = false
} else {
y = true
}
Ternary operator:
def y = 5
def x = (y > 1) ? "worked" : "failed"
While loop:
def x = 0
def y = 5
while ( y-- > 0 ) {
x++
}
25. For loop:
for (int i = 0; i < 5; i++) {
...
}
def x = 0
for ( i in 0..9 ) {
x += i
}
x = 0
for ( i in [0, 1, 2, 3, 4] ) {
x += i
}
Loop with closures:
def stringList = [ "java", "perl", "python", "ruby", "c#", "cobol",
"groovy", "jython", "smalltalk", "prolog", "m", "yacc" ];
stringList.each() {
print " ${it}"
}
26. This work is released under Creative Commons Attribution Share
Alike (CC-BY-SA)
Much of the knowledge needed to create this training material has
been produced by the sparkling knights of the GeoTools, JTS,
Geoscript and uDig community. Their community websites are full of
learning material that can be use to grow knowledge beyond the
boundaries of this set of tutorials.
The Groovy examples base on the great documentation available on
Groovy's homepage.
Another essential source has been the Wikipedia community effort.
Particular thanks go to those friends that directly or indirectly helped
out in the creation and review of this series of handbooks.
This tutorial is brought to you by HydroloGIS.