Introduction
The GeoScript Groovy Cookbook contains short recipes on how to use the GeoScript Groovy library.
GeoScript is a geospatial library written in Groovy. It provides modules for working with geometries, projections, features, layers, rasters, styles, rendering, and tiles. It is built on top of the Java Topology Suite (JTS) and GeoTools libraries. GeoScript Groovy is open source and licensed under the MIT license.
Using GeoScript
To use GeoScript Groovy you need Java, Java Advanced Imaging (JAI), and Groovy installed and on your PATH. Next, download the latest stable release, the latest in development build, or build the code yourself. Then put the GeoScript Groovy bin directory on your PATH. You are now ready to use GeoScript Groovy!
GeoScript Groovy has three commands:
-
geoscript-groovy (which can run Groovy files)

-
geoscript-groovysh (which starts a REPL shell)

-
geoscript-groovyConsole (which starts a graphical editor/mini IDE)

geoscript-groovy
The geoscript-groovy command can run scripts file, but it can also run inline scripts.
geoscript-groovy -e "println new geoscript.layer.Shapefile('states.shp').toJSONString()"
geoscript-groovy -e "println new geoscript.layer.Shapefile('states.shp').bounds.geometry"
geoscript-groovy -e "println new geoscript.layer.Shapefile('states.shp').count"
geoscript-groovy -e "geoscript.render.Draw.draw(new geoscript.layer.Shapefile('states.shp'), out: 'image.png')"
geoscript-groovy -e "new geoscript.layer.Shapefile('states.shp').eachFeature{ println it.geom.centroid}" | geom combine | geom buffer -d 1.5
echo "POINT (1 1)" | geom buffer -d 10 | geoscript-groovy -e "println geoscript.geom.Geometry.fromWKT(System.in.text).kml"
Uber Jar
GeoScript Groovy also comes packaged as an uber jar which contains all dependencies. Download geoscript-groovy-app-1.23.0-SNAPSHOT.jar from github.
java -jar geoscript-groovy-app-1.23.0-SNAPSHOT.jar
The uber jar can take four commands:
-
script = Runs a script file like the geoscript-groovy command.
-
shell = Start an interactive shell like the geoscript-groovysh commmand.
-
console = Open the simple GUI like the geoscript-groovyConsole command.
-
version = Print the versions of GeoScript, GeoTools, and Groovy
Library
Maven
<repository>
<id>osgeo-releases</id>
<name>OSGeo Nexus Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
<dependency>
<groupId>org.geoscript</groupId>
<artifactId>geoscript-groovy</artifactId>
<version>1.23.0-SNAPSHOT</version>
</dependency>
Geometry Recipes
The Geometry classes are in the geoscript.geom package.
Creating Geometries
LineString
LineString lineString = new LineString(
[3.1982421875, 43.1640625],
[6.7138671875, 49.755859375],
[9.7021484375, 42.5927734375],
[15.3271484375, 53.798828125]
)

Polygon
Polygon polygon = new Polygon([[
[-101.35986328125, 47.754097979680026],
[-101.5576171875, 46.93526088057719],
[-100.12939453125, 46.51351558059737],
[-99.77783203125, 47.44294999517949],
[-100.45898437499999, 47.88688085106901],
[-101.35986328125, 47.754097979680026]
]])

Polygon polygonWithHoles = new Polygon(
// Exterior Ring
new LinearRing(
[-122.39138603210449, 47.58659965790016],
[-122.41250038146973, 47.57681522195182],
[-122.40305900573729, 47.56523364515569],
[-122.38117218017578, 47.56621817878201],
[-122.3712158203125, 47.57235661809739],
[-122.37602233886717, 47.584747123985615],
[-122.39138603210449, 47.58659965790016]
),
// Holes
[
new LinearRing(
[-122.39859580993652, 47.578957532923376],
[-122.40468978881836, 47.57548347095205],
[-122.39593505859376, 47.570271945800094],
[-122.3920726776123, 47.57606249728773],
[-122.39859580993652, 47.578957532923376]
),
new LinearRing(
[-122.3836612701416, 47.58156292813543],
[-122.38829612731934, 47.57114056934196],
[-122.37456321716309, 47.57420959047542],
[-122.37868309020995, 47.58023129789275],
[-122.3836612701416, 47.58156292813543]
)
]
)

MultiPoint
MultiPoint multiPoint = new MultiPoint([
new Point(-122.3876953125, 47.5820839916191),
new Point(-122.464599609375, 47.25686404408872),
new Point(-122.48382568359374, 47.431803338643334)
])

MultiLineString
MultiLineString multiLineString = new MultiLineString([
new LineString (
[-122.3822021484375, 47.57837853860192],
[-122.32452392578125, 47.48380086737799]
),
new LineString (
[-122.32452392578125, 47.48380086737799],
[-122.29705810546874, 47.303447043862626]
),
new LineString (
[-122.29705810546874, 47.303447043862626],
[-122.42889404296875, 47.23262467463881]
)
])

MultiPolygon
MultiPolygon multiPolygon = new MultiPolygon(
new Polygon ([[
[-122.2723388671875, 47.818687628247105],
[-122.37945556640624, 47.66168780332917],
[-121.95373535156249, 47.67093619422418],
[-122.2723388671875, 47.818687628247105]
]]),
new Polygon ([[
[-122.76672363281249, 47.42437092240516],
[-122.76672363281249, 47.59505101193038],
[-122.52227783203125, 47.59505101193038],
[-122.52227783203125, 47.42437092240516],
[-122.76672363281249, 47.42437092240516]
]]),
new Polygon ([[
[-122.20367431640624, 47.543163654317304],
[-122.3712158203125, 47.489368981370724],
[-122.33276367187499, 47.35371061951363],
[-122.11029052734374, 47.3704545156932],
[-122.08831787109375, 47.286681888764214],
[-122.28332519531249, 47.2270293988673],
[-122.2174072265625, 47.154237057576594],
[-121.904296875, 47.32579231609051],
[-122.06085205078125, 47.47823216312885],
[-122.20367431640624, 47.543163654317304]
]])
)

GeometryCollection
GeometryCollection geometryCollection = new GeometryCollection(
new LineString ([-157.044, 58.722], [-156.461, 58.676]),
new Point(-156.648, 58.739),
new Polygon([[
[-156.395, 58.7083],
[-156.412, 58.6026],
[-155.874, 58.5825],
[-155.313, 58.4822],
[-155.385, 58.6655],
[-156.203, 58.7368],
[-156.395, 58.7083]
]]),
new Point(-156.741, 58.582)
)

CircularString
CircularString circularString = new CircularString([
[-122.464599609375, 47.247542522268006],
[-122.03613281249999, 47.37789454155521],
[-122.37670898437499, 47.58393661978134]
])

CircularRing
CircularRing circularRing = new CircularRing([
[-118.47656249999999, 41.508577297439324],
[-109.6875, 57.51582286553883],
[-93.8671875, 42.032974332441405],
[-62.57812500000001, 30.14512718337613],
[-92.10937499999999, 7.36246686553575],
[ -127.265625, 14.604847155053898],
[-118.47656249999999, 41.508577297439324]
])

CompoundCurve
CompoundCurve compoundCurve = new CompoundCurve([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
])
])

CompoundRing
CompoundRing compoundRing = new CompoundRing([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
]),
new LineString([
[69.9609375, 24.5271348225978],
[27.0703125, 23.885837699862005],
])
])

Points
Point point = new Point(-122.38632, 47.58208, 101.45)
println "X = ${point.x}"
println "Y = ${point.y}"
println "Z = ${point.z}"

X = -122.38632 Y = 47.58208 Z = 101.45
Point point1 = new Point(-122.38632, 47.58208)
Point point2 = new Point(-122.37001, 47.55868)
MultiPoint points = point1 + point2

MultiPoint multiPoint = new MultiPoint(
new Point(-122.83813,47.05141),
new Point(-122.38220,47.58023)
)
println multiPoint.wkt
MultiPoint newMultiPoint = multiPoint + new Point(-122.48657, 47.271775)
println newMultiPoint.wkt
MULTIPOINT ((-122.83813 47.05141), (-122.3822 47.58023)) MULTIPOINT ((-122.83813 47.05141), (-122.3822 47.58023), (-122.48657 47.271775))
MultiPoint

MultiPoint with extra Point

Point point1 = new Point(-122.29980, 47.65058)
Point point2 = new Point(-120.54199, 46.64943)
double angleInDegrees = point1.getAngle(point2, "degrees")
println "Angle in degrees = ${angleInDegrees}"
double angleInRadians = point1.getAngle(point2, "radians")
println "Angle in radians = ${angleInRadians}"

Angle in degrees = -29.663413013476646 Angle in radians = -0.5177242244641005
Point point1 = new Point(-122.29980, 47.65058)
Point point2 = new Point(-120.54199, 46.64943)
double azimuth = point1.getAzimuth(point2)
println "Azimuth = ${azimuth}"

Azimuth = 129.21026122904846
LineStrings
LineString lineString = new LineString(
[3.1982421875, 43.1640625],
[6.7138671875, 49.755859375],
[9.7021484375, 42.5927734375],
[15.3271484375, 53.798828125]
)
Point startPoint = lineString.startPoint

LineString lineString = new LineString(
[3.1982421875, 43.1640625],
[6.7138671875, 49.755859375],
[9.7021484375, 42.5927734375],
[15.3271484375, 53.798828125]
)
Point endPoint = lineString.endPoint

LineString lineString = new LineString(
[3.1982421875, 43.1640625],
[6.7138671875, 49.755859375],
[9.7021484375, 42.5927734375],
[15.3271484375, 53.798828125]
)
Point startPoint = lineString.startPoint
LineString reversedLineString = lineString.reverse()
Point reversedStartPoint = reversedLineString.startPoint
Original LineString showing start point

Reversed LineString showing start point

LineString lineString1 = new LineString(
[3.1982421875, 43.1640625],
[6.7138671875, 49.755859375],
[9.7021484375, 42.5927734375],
[15.3271484375, 53.798828125]
)
boolean isClosed1 = lineString1.closed
println "Is ${lineString1.wkt} closed? ${isClosed1}"
LineString lineString2 = new LineString(
[3.1982421875, 43.1640625],
[6.7138671875, 49.755859375],
[9.7021484375, 42.5927734375],
[15.3271484375, 53.798828125],
[3.1982421875, 43.1640625]
)
boolean isClosed2 = lineString2.closed
println "Is ${lineString2.wkt} closed? ${isClosed2}"

Is LINESTRING (3.1982421875 43.1640625, 6.7138671875 49.755859375, 9.7021484375 42.5927734375, 15.3271484375 53.798828125) closed? false

Is LINESTRING (3.1982421875 43.1640625, 6.7138671875 49.755859375, 9.7021484375 42.5927734375, 15.3271484375 53.798828125, 3.1982421875 43.1640625) closed? true
LineString lineString1 = new LineString(
[-122.391428, 47.563300],
[-122.391836, 47.562793],
[-122.391010, 47.562417],
[-122.390516, 47.563126]
)
boolean isRing1 = lineString1.ring
println "Is ${lineString1.wkt} a ring? ${isRing1}"
LineString lineString2 = new LineString(
[-122.391428, 47.563300],
[-122.391836, 47.562793],
[-122.391010, 47.562417],
[-122.390516, 47.563126],
[-122.391428, 47.563300]
)
boolean isRing2 = lineString2.ring
println "Is ${lineString2.wkt} a ring? ${isRing2}"

Is LINESTRING (-122.391428 47.5633, -122.391836 47.562793, -122.39101 47.562417, -122.390516 47.563126) a ring? false

Is LINESTRING (-122.391428 47.5633, -122.391836 47.562793, -122.39101 47.562417, -122.390516 47.563126, -122.391428 47.5633) a ring? true
LineString lineString = new LineString(
[-122.391428, 47.563300],
[-122.391836, 47.562793],
[-122.391010, 47.562417],
[-122.390516, 47.563126]
)
LinearRing linearRing = lineString.close()
Open LineString

Closed LinearRing

LineString lineString1 = new LineString([
[-122.39142894744873, 47.5812734461813],
[-122.38237380981445, 47.58121554959838]
])
LineString lineString2 = new LineString([
[-122.38640785217285, 47.58552866972616],
[-122.38670825958253, 47.57837853860192]
])
MultiLineString multiLineString = lineString1 + lineString2

LineString lineString = new LineString([
[-122.39142894744873, 47.5812734461813],
[-122.38237380981445, 47.58121554959838]
])
Point point = new Point(-122.38640785217285, 47.58552866972616)
LineString lineStringWithPoint = lineString + point


LineString lineString = new LineString([
[-122.39142894744873, 47.5812734461813],
[-122.38237380981445, 47.58121554959838]
])
Point point = new Point(-122.38640785217285, 47.58552866972616)
LineString lineStringWithPoint = lineString.addPoint(1, point)


LineString lineString = new LineString([
[-122.39142894744873, 47.5812734461813],
[-122.38237380981445, 47.58121554959838]
])
Point point = new Point(-122.38640785217285, 47.58552866972616)
LineString newLineString = lineString.setPoint(1, point)


LineString lineString = new LineString([
[-122.39142894744873, 47.5812734461813],
[-122.38237380981445, 47.58121554959838],
[-122.38640785217285, 47.58552866972616]
])
LineString newLineString = lineString.removePoint(2)


LineString lineString1 = new LineString([
[-122.39423990249632, 47.57926150237904],
[-122.3918581008911, 47.58121554959838],
[-122.38657951354979, 47.58121554959838],
[-122.38638639450075, 47.58535499390333],
[-122.38374710083008, 47.58535499390333]
])

LineString lineString2 = -lineString1

LineString lineString3 = -lineString2

LineString lineString = new LineString([
[-122.39423990249632, 47.57926150237904],
[-122.3918581008911, 47.58121554959838],
[-122.38657951354979, 47.58121554959838],
[-122.38638639450075, 47.58535499390333],
[-122.38374710083008, 47.58535499390333]
])
Point startPoint = lineString.interpolatePoint(0.0)
Point midPoint = lineString.interpolatePoint(0.5)
Point endPoint = lineString.interpolatePoint(1.0)

LineString lineString = new LineString([
[-122.39423990249632, 47.57926150237904],
[-122.3918581008911, 47.58121554959838],
[-122.38657951354979, 47.58121554959838],
[-122.38638639450075, 47.58535499390333],
[-122.38374710083008, 47.58535499390333]
])
Point point1 = new Point(-122.39423990249632, 47.57926150237904)
Double position1 = lineString.locatePoint(point1)
println "Position of ${point1} is ${position1}"
Point point2 = new Point(-122.38736758304911, 47.58121554959838)
Double position2 = lineString.locatePoint(point2)
println "Position of ${point2} is ${position2}"
Point point3 = new Point(-122.38374710083008, 47.58535499390333)
Double position3 = lineString.locatePoint(point3)
println "Position of ${point3} is ${position3}"

Position of POINT (-122.39423990249632 47.57926150237904) is 0.0 Position of POINT (-122.38736758304911 47.58121554959838) is 0.5000000000004425 Position of POINT (-122.38374710083008 47.58535499390333) is 1.0
LineString lineString = new LineString ([
[-122.37155914306639, 47.57166173655188],
[-122.32160568237306, 47.5714301073211]
])
Point point1 = new Point(-122.358341217041, 47.57432539907205)
Point pointOnLine1 = lineString.placePoint(point1)
Point point2 = new Point(-122.33860015869139, 47.56830301243495)
Point pointOnLine2 = lineString.placePoint(point2)
Points near LineString

Point on LineString

LineString lineString = new LineString([
[-122.39423990249632, 47.57926150237904],
[-122.3918581008911, 47.58121554959838],
[-122.38657951354979, 47.58121554959838],
[-122.38638639450075, 47.58535499390333],
[-122.38374710083008, 47.58535499390333]
])
LineString subLine = lineString.subLine(0.33, 0.66)


LineString lineString = new LineString([
[-122.39423990249632, 47.57926150237904],
[-122.3918581008911, 47.58121554959838],
[-122.38657951354979, 47.58121554959838],
[-122.38638639450075, 47.58535499390333],
[-122.38374710083008, 47.58535499390333]
])
MultiPoint multiPoint = lineString.createPointsAlong(0.001)

Polygons
Polygon polygon = new Polygon(
// Exterior Ring
new LinearRing(
[-122.39138603210449, 47.58659965790016],
[-122.41250038146973, 47.57681522195182],
[-122.40305900573729, 47.56523364515569],
[-122.38117218017578, 47.56621817878201],
[-122.3712158203125, 47.57235661809739],
[-122.37602233886717, 47.584747123985615],
[-122.39138603210449, 47.58659965790016]
),
// Holes
[
new LinearRing(
[-122.39859580993652, 47.578957532923376],
[-122.40468978881836, 47.57548347095205],
[-122.39593505859376, 47.570271945800094],
[-122.3920726776123, 47.57606249728773],
[-122.39859580993652, 47.578957532923376]
),
new LinearRing(
[-122.3836612701416, 47.58156292813543],
[-122.38829612731934, 47.57114056934196],
[-122.37456321716309, 47.57420959047542],
[-122.37868309020995, 47.58023129789275],
[-122.3836612701416, 47.58156292813543]
)
]
)
LinearRing exteriorRing = polygon.getExteriorRing()


Polygon polygon = new Polygon(
// Exterior Ring
new LinearRing(
[-122.39138603210449, 47.58659965790016],
[-122.41250038146973, 47.57681522195182],
[-122.40305900573729, 47.56523364515569],
[-122.38117218017578, 47.56621817878201],
[-122.3712158203125, 47.57235661809739],
[-122.37602233886717, 47.584747123985615],
[-122.39138603210449, 47.58659965790016]
),
// Holes
[
new LinearRing(
[-122.39859580993652, 47.578957532923376],
[-122.40468978881836, 47.57548347095205],
[-122.39593505859376, 47.570271945800094],
[-122.3920726776123, 47.57606249728773],
[-122.39859580993652, 47.578957532923376]
),
new LinearRing(
[-122.3836612701416, 47.58156292813543],
[-122.38829612731934, 47.57114056934196],
[-122.37456321716309, 47.57420959047542],
[-122.37868309020995, 47.58023129789275],
[-122.3836612701416, 47.58156292813543]
)
]
)
println "# Interior Rings = ${polygon.numInteriorRing}"
(0..<polygon.numInteriorRing).each { int i ->
println " ${polygon.getInteriorRingN(i)}"
}
println "Interior Rings"
polygon.interiorRings.each { LinearRing ring ->
println " ${ring}"
}
# Interior Rings = 2 LINEARRING (-122.39859580993652 47.578957532923376, -122.40468978881836 47.57548347095205, -122.39593505859376 47.570271945800094, -122.3920726776123 47.57606249728773, -122.39859580993652 47.578957532923376) LINEARRING (-122.3836612701416 47.58156292813543, -122.38829612731934 47.57114056934196, -122.37456321716309 47.57420959047542, -122.37868309020995 47.58023129789275, -122.3836612701416 47.58156292813543) Interior Rings LINEARRING (-122.39859580993652 47.578957532923376, -122.40468978881836 47.57548347095205, -122.39593505859376 47.570271945800094, -122.3920726776123 47.57606249728773, -122.39859580993652 47.578957532923376) LINEARRING (-122.3836612701416 47.58156292813543, -122.38829612731934 47.57114056934196, -122.37456321716309 47.57420959047542, -122.37868309020995 47.58023129789275, -122.3836612701416 47.58156292813543)



Polygon polygon1 = new Polygon ([[
[-122.2723388671875, 47.818687628247105],
[-122.37945556640624, 47.66168780332917],
[-121.95373535156249, 47.67093619422418],
[-122.2723388671875, 47.818687628247105]
]])
Polygon polygon2 = new Polygon ([[
[-122.76672363281249, 47.42437092240516],
[-122.76672363281249, 47.59505101193038],
[-122.52227783203125, 47.59505101193038],
[-122.52227783203125, 47.42437092240516],
[-122.76672363281249, 47.42437092240516]
]])
MultiPolygon multiPolygon = polygon1 + polygon2

Polygon polygon = new Polygon(
new LinearRing(
[-122.39138603210449, 47.58659965790016],
[-122.41250038146973, 47.57681522195182],
[-122.40305900573729, 47.56523364515569],
[-122.38117218017578, 47.56621817878201],
[-122.3712158203125, 47.57235661809739],
[-122.37602233886717, 47.584747123985615],
[-122.39138603210449, 47.58659965790016]
)
)
LineString lineString = new LineString([
[-122.3924160003662, 47.56395951534652],
[-122.38649368286131, 47.58729434121508]
])
MultiPolygon multiPolygon = polygon.split(lineString)


MultiLineStrings
MultiLineString multiLineString = new MultiLineString([
new LineString (
[-122.3822021484375, 47.57837853860192],
[-122.32452392578125, 47.48380086737799]
),
new LineString (
[-122.32452392578125, 47.48380086737799],
[-122.29705810546874, 47.303447043862626]
)
])
LineString lineString = new LineString (
[-122.29705810546874, 47.303447043862626],
[-122.42889404296875, 47.23262467463881]
)
MultiLineString newMultiLineString = multiLineString + lineString

MultiLineString multiLineString = new MultiLineString([
new LineString (
[-122.3822021484375, 47.57837853860192],
[-122.32452392578125, 47.48380086737799]
),
new LineString (
[-122.32452392578125, 47.48380086737799],
[-122.29705810546874, 47.303447043862626]
),
new LineString (
[-122.29705810546874, 47.303447043862626],
[-122.42889404296875, 47.23262467463881]
)
])
MultiLineString mergedMultiLineString = multiLineString.merge()
println "Original MultiLineString = ${multiLineString}"
println "Merged MultiLineString = ${mergedMultiLineString}"
Original MultiLineString = MULTILINESTRING ((-122.3822021484375 47.57837853860192, -122.32452392578125 47.48380086737799), (-122.32452392578125 47.48380086737799, -122.29705810546874 47.303447043862626), (-122.29705810546874 47.303447043862626, -122.42889404296875 47.23262467463881)) Merged MultiLineString = MULTILINESTRING ((-122.3822021484375 47.57837853860192, -122.32452392578125 47.48380086737799, -122.29705810546874 47.303447043862626, -122.42889404296875 47.23262467463881))

MultiLineString lines = new MultiLineString(
new LineString ([-5.70068359375, 45.1416015625], [2.47314453125, 53.9306640625]),
new LineString ([-1.21826171875, 53.9306640625], [8.88916015625, 46.1962890625]),
new LineString ([0.71533203125, 42.63671875], [7.13134765625, 50.37109375]),
new LineString ([-5.83251953125, 46.943359375], [4.45068359375, 42.98828125])
)
MultiPoint points = lines.createPointsAlong(1)

MultiPolygons
MultiPolygon multiPolygon = new MultiPolygon (
new Polygon([[
[-122.2723388671875, 47.818687628247105],
[-122.37945556640624, 47.66168780332917],
[-121.95373535156249, 47.67093619422418],
[-122.2723388671875, 47.818687628247105]
]]),
new Polygon ([[
[-122.76672363281249, 47.42437092240516],
[-122.76672363281249, 47.59505101193038],
[-122.52227783203125, 47.59505101193038],
[-122.52227783203125, 47.42437092240516],
[-122.76672363281249, 47.42437092240516]
]])
)
Polygon polygon = new Polygon ([[
[-122.32177734375, 47.54501765940571],
[-122.27645874023438, 47.36673410912714],
[-122.03887939453125, 47.44480754169437],
[-122.15972900390624, 47.55150616084034],
[-122.32177734375, 47.54501765940571]
]])
MultiPolygon newMultiPolygon = multiPolygon + polygon

MultiPolygon multiPolygon = new MultiPolygon (
new Polygon([[
[-122.2723388671875, 47.818687628247105],
[-122.37945556640624, 47.66168780332917],
[-121.95373535156249, 47.67093619422418],
[-122.2723388671875, 47.818687628247105]
]]),
new Polygon ([[
[-122.76672363281249, 47.42437092240516],
[-122.76672363281249, 47.59505101193038],
[-122.52227783203125, 47.59505101193038],
[-122.52227783203125, 47.42437092240516],
[-122.76672363281249, 47.42437092240516]
]]),
new Polygon ([[
[-122.32177734375, 47.54501765940571],
[-122.27645874023438, 47.36673410912714],
[-122.03887939453125, 47.44480754169437],
[-122.15972900390624, 47.55150616084034],
[-122.32177734375, 47.54501765940571]
]])
)
LineString lineString = new LineString([
[-122.84362792968749, 47.484728927366504],
[-122.05810546875, 47.50421439972969],
[-122.35748291015625, 47.85832433461554]
])
Geometry splitGeometry = multiPolygon.split(lineString)
Before

After

Geometry Collections
GeometryCollection geometryCollection = new GeometryCollection([
new Point(-122.38654196262358, 47.581211931059826),
new LineString([
[-122.3865446448326, 47.58118841055313],
[-122.38657146692276, 47.58067638459562]
]),
new Polygon(new LinearRing([
[-122.38693356513977, 47.58088445228483],
[-122.38672703504562, 47.58088445228483],
[-122.38672703504562, 47.58096225129535],
[-122.38693356513977, 47.58096225129535],
[-122.38693356513977, 47.58088445228483]
]))
])
GeometryCollection newGeometryCollection = geometryCollection + new Point(-122.38718032836913, 47.58121374032914)
Original Geometry Collection

New Geometry Collection

GeometryCollection geometryCollection = new GeometryCollection([
new Point(-122.38654196262358, 47.581211931059826),
new LineString([
[-122.3865446448326, 47.58118841055313],
[-122.38657146692276, 47.58067638459562]
]),
new Polygon(new LinearRing([
[-122.38693356513977, 47.58088445228483],
[-122.38672703504562, 47.58088445228483],
[-122.38672703504562, 47.58096225129535],
[-122.38693356513977, 47.58096225129535],
[-122.38693356513977, 47.58088445228483]
]))
])

Polygon slicedGeometryCollection1 = geometryCollection.slice(2)

GeometryCollection slicedGeometryCollection2 = geometryCollection.slice(0,2)

GeometryCollection geometryCollection1 = new GeometryCollection([
new Point(-122.38654196262358, 47.581211931059826),
new Point(-122.38718032836913, 47.58121374032914),
])
Geometry narrowedGeometry1 = geometryCollection1.narrow()
println "Narrow Geometry #1 = ${narrowedGeometry1.wkt}"

Narrow Geometry #1 = MULTIPOINT ((-122.38654196262358 47.581211931059826), (-122.38718032836913 47.58121374032914))
GeometryCollection geometryCollection2 = new GeometryCollection([
new Point(-122.38654196262358, 47.581211931059826),
new Polygon(new LinearRing([
[-122.38693356513977, 47.58088445228483],
[-122.38672703504562, 47.58088445228483],
[-122.38672703504562, 47.58096225129535],
[-122.38693356513977, 47.58096225129535],
[-122.38693356513977, 47.58088445228483]
]))
])
Geometry narrowedGeometry2 = geometryCollection2.narrow()
println "Narrow Geometry #2 = ${narrowedGeometry2.wkt}"

Narrow Geometry #2 = GEOMETRYCOLLECTION (POINT (-122.38654196262358 47.581211931059826), POLYGON ((-122.38693356513977 47.58088445228483, -122.38672703504562 47.58088445228483, -122.38672703504562 47.58096225129535, -122.38693356513977 47.58096225129535, -122.38693356513977 47.58088445228483)))
Circular Strings
CircularString circularString = new CircularString([
[-122.464599609375, 47.247542522268006],
[-122.03613281249999, 47.37789454155521],
[-122.37670898437499, 47.58393661978134]
])
println "WKT = ${circularString.wkt}"
println "Curnved WKT = ${circularString.curvedWkt}"

WKT = LINESTRING (-122.464599609375 47.247542522268006, -122.45502379201072 47.23410579860775, -122.43487808337773 47.21113402059189, -122.41190630536187 47.19098831195889, -122.38650151145399 47.1740133713689, -122.35909838472138 47.160499644761764, -122.33016580026003 47.150678355746436, -122.3001988026117 47.14471754930094, -122.26971013541457 47.14271921647622, -122.23922146821744 47.14471754930094, -122.2092544705691 47.150678355746436, -122.18032188610776 47.160499644761764, -122.15291875937515 47.1740133713689, -122.12751396546727 47.19098831195889, -122.10454218745141 47.21113402059189, -122.08439647881842 47.23410579860775, -122.06742153822843 47.25951059251563, -122.05390781162129 47.28691371924824, -122.04408652260595 47.315846303709584, -122.03812571616047 47.34581330135792, -122.03612738333574 47.37630196855505, -122.03613281249999 47.37789454155521, -122.03812571616047 47.406790635752174, -122.04408652260595 47.43675763340051, -122.05390781162129 47.465690217861855, -122.06742153822843 47.49309334459446, -122.08439647881842 47.518498138502345, -122.10454218745141 47.5414699165182, -122.12751396546727 47.561615625151205, -122.15291875937515 47.578590565741194, -122.18032188610776 47.59210429234833, -122.2092544705691 47.60192558136366, -122.23922146821744 47.60788638780915, -122.26971013541457 47.60988472063387, -122.3001988026117 47.60788638780915, -122.33016580026003 47.60192558136366, -122.35909838472138 47.59210429234833, -122.37670898437499 47.58393661978134) Curnved WKT = CIRCULARSTRING (-122.464599609375 47.247542522268006, -122.03613281249999 47.37789454155521, -122.37670898437499 47.58393661978134)
CircularString circularString = new CircularString([
[-122.464599609375, 47.247542522268006],
[-122.03613281249999, 47.37789454155521],
[-122.37670898437499, 47.58393661978134]
])
List<Point> points = circularString.controlPoints
points.each { Point point ->
println point
}

POINT (-122.464599609375 47.247542522268006) POINT (-122.03613281249999 47.37789454155521) POINT (-122.37670898437499 47.58393661978134)
CircularString circularString = new CircularString([
[-122.464599609375, 47.247542522268006],
[-122.03613281249999, 47.37789454155521],
[-122.37670898437499, 47.58393661978134]
])
Geometry linear = circularString.linear
println linear.wkt

LINESTRING (-122.464599609375 47.247542522268006, -122.45502379201072 47.23410579860775, -122.43487808337773 47.21113402059189, -122.41190630536187 47.19098831195889, -122.38650151145399 47.1740133713689, -122.35909838472138 47.160499644761764, -122.33016580026003 47.150678355746436, -122.3001988026117 47.14471754930094, -122.26971013541457 47.14271921647622, -122.23922146821744 47.14471754930094, -122.2092544705691 47.150678355746436, -122.18032188610776 47.160499644761764, -122.15291875937515 47.1740133713689, -122.12751396546727 47.19098831195889, -122.10454218745141 47.21113402059189, -122.08439647881842 47.23410579860775, -122.06742153822843 47.25951059251563, -122.05390781162129 47.28691371924824, -122.04408652260595 47.315846303709584, -122.03812571616047 47.34581330135792, -122.03612738333574 47.37630196855505, -122.03613281249999 47.37789454155521, -122.03812571616047 47.406790635752174, -122.04408652260595 47.43675763340051, -122.05390781162129 47.465690217861855, -122.06742153822843 47.49309334459446, -122.08439647881842 47.518498138502345, -122.10454218745141 47.5414699165182, -122.12751396546727 47.561615625151205, -122.15291875937515 47.578590565741194, -122.18032188610776 47.59210429234833, -122.2092544705691 47.60192558136366, -122.23922146821744 47.60788638780915, -122.26971013541457 47.60988472063387, -122.3001988026117 47.60788638780915, -122.33016580026003 47.60192558136366, -122.35909838472138 47.59210429234833, -122.37670898437499 47.58393661978134)
Circular Rings
CircularRing circularRing = new CircularRing([
[-118.47656249999999, 41.508577297439324],
[-109.6875, 57.51582286553883],
[-93.8671875, 42.032974332441405],
[-62.57812500000001, 30.14512718337613],
[-92.10937499999999, 7.36246686553575],
[ -127.265625, 14.604847155053898],
[-118.47656249999999, 41.508577297439324]
])
println "WKT = ${circularRing.wkt}"
println "Curnved WKT = ${circularRing.curvedWkt}"

WKT = LINEARRING (-118.47656249999999 41.508577297439324, -118.58869123015454 41.90177457905915, -118.91479847512255 43.54122641035521, -119.02412442253559 45.20921804090461, -118.91479847512254 46.87720967145401, -118.58869123015452 48.51666150275007, -118.05138247300695 50.099522059417374, -117.31206570548476 51.5987081584795, -116.38339084245754 52.98856831012859, -115.28124776830907 54.24532162182789, -114.02449445660977 55.34746469597637, -112.63463430496068 56.27613955900357, -111.13544820589856 57.01545632652577, -109.6875 57.51582286553883, -109.55258764923124 57.55276508367335, -107.91313581793518 57.878872328641364, -106.24514418738578 57.988198276054405, -104.57715255683637 57.878872328641364, -102.93770072554031 57.55276508367335, -101.354840168873 57.01545632652578, -99.85565406981087 56.27613955900357, -98.46579391816178 55.34746469597637, -97.20904060646248 54.245321621827884, -96.106897532314 52.98856831012859, -95.1782226692868 51.598708158479496, -94.4389059017646 50.09952205941737, -93.90159714461703 48.516661502750054, -93.57548989964901 46.877209671454, -93.46616395223596 45.209218040904595, -93.57548989964901 43.54122641035519, -93.8671875 42.032974332441405, -92.52944589377745 42.87620255408929, -90.13998424943786 44.054554634672606, -87.61715897053443 44.91093841996456, -85.00413629704852 45.43070094596436, -82.34562577139023 45.604948931746776, -79.68711524573195 45.430700945964375, -77.07409257224603 44.910938419964566, -74.5512672933426 44.05455463467261, -72.161805649003 42.8762025540893, -69.9465919904458 41.396044109014326, -67.94352923754218 39.63940522082037, -66.18689034934822 37.63634246791675, -64.70673190427324 35.42112880935956, -63.52837982368993 33.031667165019954, -62.67199603839798 30.508841886116528, -62.57812500000001 30.14512718337613, -62.15223351239817 27.89581921263062, -61.97798552661577 25.237308686972334, -62.15223351239817 22.578798161314044, -62.67199603839798 19.96577548782814, -63.528379823689924 17.44295020892471, -64.70673190427324 15.053488564585109, -66.1868903493482 12.838274906027912, -67.94352923754217 10.835212153124287, -69.94659199044578 9.07857326493033, -72.16180564900299 7.598414819855357, -74.55126729334258 6.420062739272041, -77.074092572246 5.563678953980087, -79.68711524573192 5.043916427980278, -82.3456257713902 4.869668442197874, -85.0041362970485 5.043916427980275, -87.6171589705344 5.56367895398008, -90.13998424943783 6.4200627392720335, -92.10937499999999 7.36246686553575, -94.00832592648507 5.722586433241055, -96.36933879828982 4.1450080684486394, -98.91606817456315 2.889100125199903, -101.60493880959024 1.9763515366073001, -104.38994338131 1.4223796840833565, -107.22342968935116 1.2366631796147836, -110.05691599739234 1.4223796840833742, -112.84192056911209 1.9763515366073285, -115.53079120413918 2.8891001251999526, -118.0775205804125 4.145008068448703, -120.43853345221724 5.72258643324113, -122.57343223472039 7.594842416368291, -124.44568821784753 9.729741198871434, -126.02326658263995 12.090754070676176, -127.265625 14.604847155053898, -127.27917452588868 14.637483446949501, -128.19192311448128 17.32635408197659, -128.74589496700523 20.111358653696357, -128.93161147147381 22.944844961737523, -128.74589496700523 25.77833126977869, -128.19192311448128 28.56333584149845, -127.27917452588866 31.25220647652554, -126.0232665826399 33.79893585279886, -124.44568821784749 36.159948724603595, -122.57343223472034 38.29484750710674, -120.4385334522172 40.167103490233885, -118.47656249999999 41.508577297439324) Curnved WKT = CIRCULARSTRING (-118.47656249999999 41.508577297439324, -109.6875 57.51582286553883, -93.8671875 42.032974332441405, -62.57812500000001 30.14512718337613, -92.10937499999999 7.36246686553575, -127.265625 14.604847155053898, -118.47656249999999 41.508577297439324)
CircularRing circularRing = new CircularRing([
[-118.47656249999999, 41.508577297439324],
[-109.6875, 57.51582286553883],
[-93.8671875, 42.032974332441405],
[-62.57812500000001, 30.14512718337613],
[-92.10937499999999, 7.36246686553575],
[ -127.265625, 14.604847155053898],
[-118.47656249999999, 41.508577297439324]
])
List<Point> points = circularRing.controlPoints
points.each { Point point ->
println point
}

POINT (-118.47656249999999 41.508577297439324) POINT (-109.6875 57.51582286553883) POINT (-93.8671875 42.032974332441405) POINT (-62.57812500000001 30.14512718337613) POINT (-92.10937499999999 7.36246686553575) POINT (-127.265625 14.604847155053898) POINT (-118.47656249999999 41.508577297439324)
CircularRing circularRing = new CircularRing([
[-118.47656249999999, 41.508577297439324],
[-109.6875, 57.51582286553883],
[-93.8671875, 42.032974332441405],
[-62.57812500000001, 30.14512718337613],
[-92.10937499999999, 7.36246686553575],
[ -127.265625, 14.604847155053898],
[-118.47656249999999, 41.508577297439324]
])
Geometry linear = circularRing.linear
println linear.wkt

LINEARRING (-118.47656249999999 41.508577297439324, -118.58869123015454 41.90177457905915, -118.91479847512255 43.54122641035521, -119.02412442253559 45.20921804090461, -118.91479847512254 46.87720967145401, -118.58869123015452 48.51666150275007, -118.05138247300695 50.099522059417374, -117.31206570548476 51.5987081584795, -116.38339084245754 52.98856831012859, -115.28124776830907 54.24532162182789, -114.02449445660977 55.34746469597637, -112.63463430496068 56.27613955900357, -111.13544820589856 57.01545632652577, -109.6875 57.51582286553883, -109.55258764923124 57.55276508367335, -107.91313581793518 57.878872328641364, -106.24514418738578 57.988198276054405, -104.57715255683637 57.878872328641364, -102.93770072554031 57.55276508367335, -101.354840168873 57.01545632652578, -99.85565406981087 56.27613955900357, -98.46579391816178 55.34746469597637, -97.20904060646248 54.245321621827884, -96.106897532314 52.98856831012859, -95.1782226692868 51.598708158479496, -94.4389059017646 50.09952205941737, -93.90159714461703 48.516661502750054, -93.57548989964901 46.877209671454, -93.46616395223596 45.209218040904595, -93.57548989964901 43.54122641035519, -93.8671875 42.032974332441405, -92.52944589377745 42.87620255408929, -90.13998424943786 44.054554634672606, -87.61715897053443 44.91093841996456, -85.00413629704852 45.43070094596436, -82.34562577139023 45.604948931746776, -79.68711524573195 45.430700945964375, -77.07409257224603 44.910938419964566, -74.5512672933426 44.05455463467261, -72.161805649003 42.8762025540893, -69.9465919904458 41.396044109014326, -67.94352923754218 39.63940522082037, -66.18689034934822 37.63634246791675, -64.70673190427324 35.42112880935956, -63.52837982368993 33.031667165019954, -62.67199603839798 30.508841886116528, -62.57812500000001 30.14512718337613, -62.15223351239817 27.89581921263062, -61.97798552661577 25.237308686972334, -62.15223351239817 22.578798161314044, -62.67199603839798 19.96577548782814, -63.528379823689924 17.44295020892471, -64.70673190427324 15.053488564585109, -66.1868903493482 12.838274906027912, -67.94352923754217 10.835212153124287, -69.94659199044578 9.07857326493033, -72.16180564900299 7.598414819855357, -74.55126729334258 6.420062739272041, -77.074092572246 5.563678953980087, -79.68711524573192 5.043916427980278, -82.3456257713902 4.869668442197874, -85.0041362970485 5.043916427980275, -87.6171589705344 5.56367895398008, -90.13998424943783 6.4200627392720335, -92.10937499999999 7.36246686553575, -94.00832592648507 5.722586433241055, -96.36933879828982 4.1450080684486394, -98.91606817456315 2.889100125199903, -101.60493880959024 1.9763515366073001, -104.38994338131 1.4223796840833565, -107.22342968935116 1.2366631796147836, -110.05691599739234 1.4223796840833742, -112.84192056911209 1.9763515366073285, -115.53079120413918 2.8891001251999526, -118.0775205804125 4.145008068448703, -120.43853345221724 5.72258643324113, -122.57343223472039 7.594842416368291, -124.44568821784753 9.729741198871434, -126.02326658263995 12.090754070676176, -127.265625 14.604847155053898, -127.27917452588868 14.637483446949501, -128.19192311448128 17.32635408197659, -128.74589496700523 20.111358653696357, -128.93161147147381 22.944844961737523, -128.74589496700523 25.77833126977869, -128.19192311448128 28.56333584149845, -127.27917452588866 31.25220647652554, -126.0232665826399 33.79893585279886, -124.44568821784749 36.159948724603595, -122.57343223472034 38.29484750710674, -120.4385334522172 40.167103490233885, -118.47656249999999 41.508577297439324)
Compound Curves
CompoundCurve compoundCurve = new CompoundCurve([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
])
])
println "WKT = ${compoundCurve.wkt}"
println "Curnved WKT = ${compoundCurve.curvedWkt}"

WKT = LINESTRING (27.0703125 23.885837699862005, 27.02233144941429 23.848852560584696, 25.52476733728419 22.848212211944787, 23.909405319245256 22.051603821364196, 22.203884687289097 21.472657579267327, 20.43738737228814 21.121279416370683, 18.640138633067632 21.003481510461857, 16.842889893847126 21.121279416370697, 15.076392578846168 21.47265757926735, 13.370871946890016 22.051603821364225, 11.755509928851087 22.848212211944826, 10.25794581672099 23.84885256058474, 8.903803347661489 25.036403633488828, 7.716252274757407 26.390546102548335, 6.7156119261174965 27.888110214678434, 5.9190035355369055 29.503472232717364, 5.340057293440033 31.208992864673522, 4.988679130543385 32.97549017967448, 4.870881224634555 34.77273891889499, 4.988679130543391 36.569987658115494, 5.340057293440042 38.33648497311645, 5.919003535536916 40.0420056050726, 5.9765625 40.17887331434696, 6.715611926117511 41.65736762311153, 7.716252274757425 43.15493173524163, 8.903803347661508 44.509074204301136, 10.257945816721014 45.69662527720522, 11.755509928851112 46.697265625845134, 13.370871946890045 47.493874016425735, 15.076392578846201 48.072820258522604, 16.84288989384716 48.424198421419256, 18.64013863306767 48.54199632732809, 20.437387372288185 48.424198421419256, 22.203884687289143 48.072820258522604, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138722 48.95345106044013, 74.12646468490567 48.43073090444655, 75.58494601643166 47.71148750685246, 76.93706973601536 46.80802732160264, 78.1597006319352 45.7358088029532, 79.23191915058463 44.51317790703337, 80.13537933583444 43.161054187449665, 80.85462273342853 41.70257285592368, 81.37734288942211 40.16268893240523, 81.5625 39.36827914916011, 81.69459591702073 38.56775025776221, 81.80095352896302 36.94504667491831, 81.69459591702073 35.322343092074405, 81.37734288942211 33.72740441743139, 80.85462273342853 32.18752049391294, 80.13537933583444 30.72903916238695, 79.23191915058463 29.376915442803245, 78.1597006319352 28.154284546883417, 76.93706973601536 27.08206602823398, 75.58494601643166 26.17860584298416, 74.12646468490567 25.45936244539007, 72.58658076138722 24.93664228939649, 70.9916420867442 24.619389261797874, 69.9609375 24.5271348225978) Curnved WKT = COMPOUNDCURVE (CIRCULARSTRING (27.0703125 23.885837699862005, 5.9765625 40.17887331434696, 22.5 47.98992166741417), (22.5 47.98992166741417, 71.71875 49.15296965617039), CIRCULARSTRING (71.71875 49.15296965617039, 81.5625 39.36827914916011, 69.9609375 24.5271348225978))
CompoundCurve compoundCurve = new CompoundCurve([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
])
])
List<LineString> lineStrings = compoundCurve.components
lineStrings.each { LineString lineString ->
println lineString
}

LINESTRING (27.0703125 23.885837699862005, 27.02233144941429 23.848852560584696, 25.52476733728419 22.848212211944787, 23.909405319245256 22.051603821364196, 22.203884687289097 21.472657579267327, 20.43738737228814 21.121279416370683, 18.640138633067632 21.003481510461857, 16.842889893847126 21.121279416370697, 15.076392578846168 21.47265757926735, 13.370871946890016 22.051603821364225, 11.755509928851087 22.848212211944826, 10.25794581672099 23.84885256058474, 8.903803347661489 25.036403633488828, 7.716252274757407 26.390546102548335, 6.7156119261174965 27.888110214678434, 5.9190035355369055 29.503472232717364, 5.340057293440033 31.208992864673522, 4.988679130543385 32.97549017967448, 4.870881224634555 34.77273891889499, 4.988679130543391 36.569987658115494, 5.340057293440042 38.33648497311645, 5.919003535536916 40.0420056050726, 5.9765625 40.17887331434696, 6.715611926117511 41.65736762311153, 7.716252274757425 43.15493173524163, 8.903803347661508 44.509074204301136, 10.257945816721014 45.69662527720522, 11.755509928851112 46.697265625845134, 13.370871946890045 47.493874016425735, 15.076392578846201 48.072820258522604, 16.84288989384716 48.424198421419256, 18.64013863306767 48.54199632732809, 20.437387372288185 48.424198421419256, 22.203884687289143 48.072820258522604, 22.5 47.98992166741417) LINESTRING (22.5 47.98992166741417, 71.71875 49.15296965617039) LINESTRING (71.71875 49.15296965617039, 72.58658076138722 48.95345106044013, 74.12646468490567 48.43073090444655, 75.58494601643166 47.71148750685246, 76.93706973601536 46.80802732160264, 78.1597006319352 45.7358088029532, 79.23191915058463 44.51317790703337, 80.13537933583444 43.161054187449665, 80.85462273342853 41.70257285592368, 81.37734288942211 40.16268893240523, 81.5625 39.36827914916011, 81.69459591702073 38.56775025776221, 81.80095352896302 36.94504667491831, 81.69459591702073 35.322343092074405, 81.37734288942211 33.72740441743139, 80.85462273342853 32.18752049391294, 80.13537933583444 30.72903916238695, 79.23191915058463 29.376915442803245, 78.1597006319352 28.154284546883417, 76.93706973601536 27.08206602823398, 75.58494601643166 26.17860584298416, 74.12646468490567 25.45936244539007, 72.58658076138722 24.93664228939649, 70.9916420867442 24.619389261797874, 69.9609375 24.5271348225978)
CompoundCurve compoundCurve = new CompoundCurve([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
])
])
Geometry linear = compoundCurve.linear
println linear.wkt

LINESTRING (27.0703125 23.885837699862005, 27.02233144941429 23.848852560584696, 25.52476733728419 22.848212211944787, 23.909405319245256 22.051603821364196, 22.203884687289097 21.472657579267327, 20.43738737228814 21.121279416370683, 18.640138633067632 21.003481510461857, 16.842889893847126 21.121279416370697, 15.076392578846168 21.47265757926735, 13.370871946890016 22.051603821364225, 11.755509928851087 22.848212211944826, 10.25794581672099 23.84885256058474, 8.903803347661489 25.036403633488828, 7.716252274757407 26.390546102548335, 6.7156119261174965 27.888110214678434, 5.9190035355369055 29.503472232717364, 5.340057293440033 31.208992864673522, 4.988679130543385 32.97549017967448, 4.870881224634555 34.77273891889499, 4.988679130543391 36.569987658115494, 5.340057293440042 38.33648497311645, 5.919003535536916 40.0420056050726, 5.9765625 40.17887331434696, 6.715611926117511 41.65736762311153, 7.716252274757425 43.15493173524163, 8.903803347661508 44.509074204301136, 10.257945816721014 45.69662527720522, 11.755509928851112 46.697265625845134, 13.370871946890045 47.493874016425735, 15.076392578846201 48.072820258522604, 16.84288989384716 48.424198421419256, 18.64013863306767 48.54199632732809, 20.437387372288185 48.424198421419256, 22.203884687289143 48.072820258522604, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138722 48.95345106044013, 74.12646468490567 48.43073090444655, 75.58494601643166 47.71148750685246, 76.93706973601536 46.80802732160264, 78.1597006319352 45.7358088029532, 79.23191915058463 44.51317790703337, 80.13537933583444 43.161054187449665, 80.85462273342853 41.70257285592368, 81.37734288942211 40.16268893240523, 81.5625 39.36827914916011, 81.69459591702073 38.56775025776221, 81.80095352896302 36.94504667491831, 81.69459591702073 35.322343092074405, 81.37734288942211 33.72740441743139, 80.85462273342853 32.18752049391294, 80.13537933583444 30.72903916238695, 79.23191915058463 29.376915442803245, 78.1597006319352 28.154284546883417, 76.93706973601536 27.08206602823398, 75.58494601643166 26.17860584298416, 74.12646468490567 25.45936244539007, 72.58658076138722 24.93664228939649, 70.9916420867442 24.619389261797874, 69.9609375 24.5271348225978)
Compound Rings
CompoundRing compoundRing = new CompoundRing([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
]),
new LineString([
[69.9609375, 24.5271348225978],
[27.0703125, 23.885837699862005],
])
])
println "WKT = ${compoundRing.wkt}"
println "Curnved WKT = ${compoundRing.curvedWkt}"

WKT = LINEARRING (27.0703125 23.885837699862005, 27.02233144941429 23.848852560584696, 25.52476733728419 22.848212211944787, 23.909405319245256 22.051603821364196, 22.203884687289097 21.472657579267327, 20.43738737228814 21.121279416370683, 18.640138633067632 21.003481510461857, 16.842889893847126 21.121279416370697, 15.076392578846168 21.47265757926735, 13.370871946890016 22.051603821364225, 11.755509928851087 22.848212211944826, 10.25794581672099 23.84885256058474, 8.903803347661489 25.036403633488828, 7.716252274757407 26.390546102548335, 6.7156119261174965 27.888110214678434, 5.9190035355369055 29.503472232717364, 5.340057293440033 31.208992864673522, 4.988679130543385 32.97549017967448, 4.870881224634555 34.77273891889499, 4.988679130543391 36.569987658115494, 5.340057293440042 38.33648497311645, 5.919003535536916 40.0420056050726, 5.9765625 40.17887331434696, 6.715611926117511 41.65736762311153, 7.716252274757425 43.15493173524163, 8.903803347661508 44.509074204301136, 10.257945816721014 45.69662527720522, 11.755509928851112 46.697265625845134, 13.370871946890045 47.493874016425735, 15.076392578846201 48.072820258522604, 16.84288989384716 48.424198421419256, 18.64013863306767 48.54199632732809, 20.437387372288185 48.424198421419256, 22.203884687289143 48.072820258522604, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138722 48.95345106044013, 74.12646468490567 48.43073090444655, 75.58494601643166 47.71148750685246, 76.93706973601536 46.80802732160264, 78.1597006319352 45.7358088029532, 79.23191915058463 44.51317790703337, 80.13537933583444 43.161054187449665, 80.85462273342853 41.70257285592368, 81.37734288942211 40.16268893240523, 81.5625 39.36827914916011, 81.69459591702073 38.56775025776221, 81.80095352896302 36.94504667491831, 81.69459591702073 35.322343092074405, 81.37734288942211 33.72740441743139, 80.85462273342853 32.18752049391294, 80.13537933583444 30.72903916238695, 79.23191915058463 29.376915442803245, 78.1597006319352 28.154284546883417, 76.93706973601536 27.08206602823398, 75.58494601643166 26.17860584298416, 74.12646468490567 25.45936244539007, 72.58658076138722 24.93664228939649, 70.9916420867442 24.619389261797874, 69.9609375 24.5271348225978, 27.0703125 23.885837699862005) Curnved WKT = COMPOUNDCURVE (CIRCULARSTRING (27.0703125 23.885837699862005, 5.9765625 40.17887331434696, 22.5 47.98992166741417), (22.5 47.98992166741417, 71.71875 49.15296965617039), CIRCULARSTRING (71.71875 49.15296965617039, 81.5625 39.36827914916011, 69.9609375 24.5271348225978), (69.9609375 24.5271348225978, 27.0703125 23.885837699862005))
CompoundRing compoundRing = new CompoundRing([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
]),
new LineString([
[69.9609375, 24.5271348225978],
[27.0703125, 23.885837699862005],
])
])
List<LineString> lineStrings = compoundRing.components
lineStrings.each { LineString lineString ->
println lineString
}

LINESTRING (27.0703125 23.885837699862005, 27.02233144941429 23.848852560584696, 25.52476733728419 22.848212211944787, 23.909405319245256 22.051603821364196, 22.203884687289097 21.472657579267327, 20.43738737228814 21.121279416370683, 18.640138633067632 21.003481510461857, 16.842889893847126 21.121279416370697, 15.076392578846168 21.47265757926735, 13.370871946890016 22.051603821364225, 11.755509928851087 22.848212211944826, 10.25794581672099 23.84885256058474, 8.903803347661489 25.036403633488828, 7.716252274757407 26.390546102548335, 6.7156119261174965 27.888110214678434, 5.9190035355369055 29.503472232717364, 5.340057293440033 31.208992864673522, 4.988679130543385 32.97549017967448, 4.870881224634555 34.77273891889499, 4.988679130543391 36.569987658115494, 5.340057293440042 38.33648497311645, 5.919003535536916 40.0420056050726, 5.9765625 40.17887331434696, 6.715611926117511 41.65736762311153, 7.716252274757425 43.15493173524163, 8.903803347661508 44.509074204301136, 10.257945816721014 45.69662527720522, 11.755509928851112 46.697265625845134, 13.370871946890045 47.493874016425735, 15.076392578846201 48.072820258522604, 16.84288989384716 48.424198421419256, 18.64013863306767 48.54199632732809, 20.437387372288185 48.424198421419256, 22.203884687289143 48.072820258522604, 22.5 47.98992166741417) LINESTRING (22.5 47.98992166741417, 71.71875 49.15296965617039) LINESTRING (71.71875 49.15296965617039, 72.58658076138722 48.95345106044013, 74.12646468490567 48.43073090444655, 75.58494601643166 47.71148750685246, 76.93706973601536 46.80802732160264, 78.1597006319352 45.7358088029532, 79.23191915058463 44.51317790703337, 80.13537933583444 43.161054187449665, 80.85462273342853 41.70257285592368, 81.37734288942211 40.16268893240523, 81.5625 39.36827914916011, 81.69459591702073 38.56775025776221, 81.80095352896302 36.94504667491831, 81.69459591702073 35.322343092074405, 81.37734288942211 33.72740441743139, 80.85462273342853 32.18752049391294, 80.13537933583444 30.72903916238695, 79.23191915058463 29.376915442803245, 78.1597006319352 28.154284546883417, 76.93706973601536 27.08206602823398, 75.58494601643166 26.17860584298416, 74.12646468490567 25.45936244539007, 72.58658076138722 24.93664228939649, 70.9916420867442 24.619389261797874, 69.9609375 24.5271348225978) LINESTRING (69.9609375 24.5271348225978, 27.0703125 23.885837699862005)
CompoundRing compoundRing = new CompoundRing([
new CircularString([
[27.0703125, 23.885837699862005],
[5.9765625, 40.17887331434696],
[22.5, 47.98992166741417],
]),
new LineString([
[22.5, 47.98992166741417],
[71.71875, 49.15296965617039],
]),
new CircularString([
[71.71875, 49.15296965617039],
[81.5625, 39.36827914916011],
[69.9609375, 24.5271348225978]
]),
new LineString([
[69.9609375, 24.5271348225978],
[27.0703125, 23.885837699862005],
])
])
Geometry linear = compoundRing.linear
println linear.wkt

LINEARRING (27.0703125 23.885837699862005, 27.02233144941429 23.848852560584696, 25.52476733728419 22.848212211944787, 23.909405319245256 22.051603821364196, 22.203884687289097 21.472657579267327, 20.43738737228814 21.121279416370683, 18.640138633067632 21.003481510461857, 16.842889893847126 21.121279416370697, 15.076392578846168 21.47265757926735, 13.370871946890016 22.051603821364225, 11.755509928851087 22.848212211944826, 10.25794581672099 23.84885256058474, 8.903803347661489 25.036403633488828, 7.716252274757407 26.390546102548335, 6.7156119261174965 27.888110214678434, 5.9190035355369055 29.503472232717364, 5.340057293440033 31.208992864673522, 4.988679130543385 32.97549017967448, 4.870881224634555 34.77273891889499, 4.988679130543391 36.569987658115494, 5.340057293440042 38.33648497311645, 5.919003535536916 40.0420056050726, 5.9765625 40.17887331434696, 6.715611926117511 41.65736762311153, 7.716252274757425 43.15493173524163, 8.903803347661508 44.509074204301136, 10.257945816721014 45.69662527720522, 11.755509928851112 46.697265625845134, 13.370871946890045 47.493874016425735, 15.076392578846201 48.072820258522604, 16.84288989384716 48.424198421419256, 18.64013863306767 48.54199632732809, 20.437387372288185 48.424198421419256, 22.203884687289143 48.072820258522604, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138722 48.95345106044013, 74.12646468490567 48.43073090444655, 75.58494601643166 47.71148750685246, 76.93706973601536 46.80802732160264, 78.1597006319352 45.7358088029532, 79.23191915058463 44.51317790703337, 80.13537933583444 43.161054187449665, 80.85462273342853 41.70257285592368, 81.37734288942211 40.16268893240523, 81.5625 39.36827914916011, 81.69459591702073 38.56775025776221, 81.80095352896302 36.94504667491831, 81.69459591702073 35.322343092074405, 81.37734288942211 33.72740441743139, 80.85462273342853 32.18752049391294, 80.13537933583444 30.72903916238695, 79.23191915058463 29.376915442803245, 78.1597006319352 28.154284546883417, 76.93706973601536 27.08206602823398, 75.58494601643166 26.17860584298416, 74.12646468490567 25.45936244539007, 72.58658076138722 24.93664228939649, 70.9916420867442 24.619389261797874, 69.9609375 24.5271348225978, 27.0703125 23.885837699862005)
Processing Geometries
Geometry geom = Geometry.fromString("POINT (-124.80 48.92)")
String type = geom.geometryType
println type
Point
Point point1 = new Point(-121.915, 47.390)
Point point2 = new Point(-121.915, 47.390)
Point point3 = new Point(-121.409, 47.413)
boolean does1equal2 = point1.equals(point2)
println "Does ${point1} equal ${point2}? ${does1equal2 ? 'Yes' : 'No'}"
boolean does1equal3 = point1.equals(point3)
println "Does ${point1} equal ${point3}? ${does1equal3 ? 'Yes' : 'No'}"
boolean does2equal3 = point2.equals(point3)
println "Does ${point2} equal ${point3}? ${does2equal3 ? 'Yes' : 'No'}"
Does POINT (-121.915 47.39) equal POINT (-121.915 47.39)? Yes Does POINT (-121.915 47.39) equal POINT (-121.409 47.413)? No Does POINT (-121.915 47.39) equal POINT (-121.409 47.413)? No
Point point1 = new Point(-121.915, 47.390)
Point point2 = new Point(-121.915, 47.390)
Point point3 = new Point(-121.409, 47.413)
boolean does1equal2 = point1.equalsTopo(point2)
println "Does ${point1} equal ${point2}? ${does1equal2 ? 'Yes' : 'No'}"
boolean does1equal3 = point1.equalsTopo(point3)
println "Does ${point1} equal ${point3}? ${does1equal3 ? 'Yes' : 'No'}"
boolean does2equal3 = point2.equalsTopo(point3)
println "Does ${point2} equal ${point3}? ${does2equal3 ? 'Yes' : 'No'}"
Does POINT (-121.915 47.39) equal POINT (-121.915 47.39)? Yes Does POINT (-121.915 47.39) equal POINT (-121.409 47.413)? No Does POINT (-121.915 47.39) equal POINT (-121.409 47.413)? No
Geometry geom1 = Geometry.fromWKT("POLYGON ((2 4, 1 3, 2 1, 6 1, 6 3, 4 4, 2 4))")
Geometry geom2 = Geometry.fromWKT("POLYGON ((1 3, 2 4, 4 4, 6 3, 6 1, 2 1, 1 3))")
Geometry geom3 = Geometry.fromWKT("POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))")
boolean does1equal2 = geom1.equalsNorm(geom2)
println "Does ${geom1} equal ${geom2}? ${does1equal2 ? 'Yes' : 'No'}"
boolean does1equal3 = geom1.equalsNorm(geom3)
println "Does ${geom1} equal ${geom3}? ${does1equal3 ? 'Yes' : 'No'}"
boolean does2equal3 = geom2.equalsNorm(geom3)
println "Does ${geom2} equal ${geom3}? ${does2equal3 ? 'Yes' : 'No'}"
Does POLYGON ((2 4, 1 3, 2 1, 6 1, 6 3, 4 4, 2 4)) equal POLYGON ((1 3, 2 4, 4 4, 6 3, 6 1, 2 1, 1 3))? Yes Does POLYGON ((2 4, 1 3, 2 1, 6 1, 6 3, 4 4, 2 4)) equal POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))? No Does POLYGON ((1 3, 2 4, 4 4, 6 3, 6 1, 2 1, 1 3)) equal POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))? No
MultiPoint multiPoint = new MultiPoint([
new Point(-122.3876953125, 47.5820839916191),
new Point(-122.464599609375, 47.25686404408872),
new Point(-122.48382568359374, 47.431803338643334)
])
Point p1 = multiPoint[0]
println p1
Point p2 = multiPoint[1]
println p2
Point p3 = multiPoint[2]
println p3
POINT (-122.3876953125 47.5820839916191) POINT (-122.464599609375 47.25686404408872) POINT (-122.48382568359374 47.431803338643334)
Geometry geometry = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Bounds bounds = geometry as Bounds
println bounds
Point point = geometry as Point
println point
(-122.64,46.308,-120.981,47.413) POINT (-121.73789467295867 46.95085967283822)

Polygon polygon = new Polygon([[
[-124.80, 48.92],
[-126.21, 45.33],
[-114.60, 45.08],
[-115.31, 51.17],
[-121.99, 52.05],
[-124.80, 48.92]
]])
double area = polygon.area
println area
62.4026
LineString lineString = new LineString([-122.69, 49.61], [-99.84, 45.33])
double length = lineString.length
println length
23.24738479915536
Point point = new Point(-123,46)
Geometry bufferedPoint = point.buffer(2)

LineString line = new LineString([
[-122.563, 47.576],
[-112.0166, 46.589],
[-101.337, 47.606]
])
Geometry bufferedLine1 = line.buffer(2.1, 10, Geometry.CAP_BUTT)

Geometry bufferedLine2 = line.buffer(2.1, 10, Geometry.CAP_ROUND)

Geometry bufferedLine3 = line.buffer(2.1, 10, Geometry.CAP_SQUARE)

LineString line = new LineString([
[-122.563, 47.576],
[-112.0166, 46.589],
[-101.337, 47.606]
])
Geometry rightBufferedLine = line.singleSidedBuffer(1.5)

Geometry leftBufferedLine = line.singleSidedBuffer(-1.5)

LineString line = new LineString([
[-122.38494873046875, 47.57281986733871],
[-122.27508544921875, 47.342545069660225],
[-122.15972900390624, 47.14302937421008],
[-121.96197509765625, 47.03082254778662],
[-121.73950195312499, 46.89586230605985],
[-121.56372070312499, 46.81509864599243]
])
Geometry buffer = line.variableBuffer([0.03, 0.07])

LineString line = new LineString([
[-122.38494873046875, 47.57281986733871],
[-122.27508544921875, 47.342545069660225],
[-122.15972900390624, 47.14302937421008],
[-121.96197509765625, 47.03082254778662],
[-121.73950195312499, 46.89586230605985],
[-121.56372070312499, 46.81509864599243]
])
Geometry buffer = line.variableBuffer([0.03, 0.07, 0.1])

LineString line = new LineString([
[-122.38494873046875, 47.57281986733871],
[-122.27508544921875, 47.342545069660225],
[-122.15972900390624, 47.14302937421008],
[-121.96197509765625, 47.03082254778662],
[-121.73950195312499, 46.89586230605985],
[-121.56372070312499, 46.81509864599243]
])
Geometry buffer = line.variableBuffer([0.03, 0.05, 0.07, 0.09, 0.1, 0.2])

Polygon polygon1 = new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]])
Polygon polygon2 = new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]])
boolean contains = polygon1.contains(polygon2)
println contains

true
Polygon polygon1 = new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]])
Polygon polygon2 = new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]])
boolean within = polygon1.within(polygon2)
println within

true
Polygon polygon3 = new Polygon([[ [-120.563, 46.739], [-119.948, 46.739], [-119.948, 46.965], [-120.563, 46.965], [-120.563, 46.739] ]]) within = polygon1.within(polygon3) println within

false
LineString line1 = new LineString([
[-122.38651514053345, 47.58219978280006],
[-122.38651514053345, 47.58020234903306]
])
LineString line2 = new LineString([
[-122.38651514053345, 47.58124449789785],
[-122.38333940505981, 47.58124449789785]
])
boolean touches = line1.touches(line2)

true
LineString line3 = new LineString([ [-122.386257648468, 47.58183793450921], [-122.38348960876465, 47.5818668824645] ]) touches = line1.touches(line3)

false
Geometry geometry = new MultiPoint(
new Point(-119.882, 47.279),
new Point(-100.195, 46.316),
new Point(-111.796, 42.553),
new Point(-90.7031, 34.016)
)
Geometry convexHull = geometry.convexHull

Polygon polygon1 = new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]])
Polygon polygon2 = new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]])
boolean isCovered = polygon1.covers(polygon2)
println isCovered

true
Polygon polygon3 = new Polygon([[ [-120.563, 46.739], [-119.948, 46.739], [-119.948, 46.965], [-120.563, 46.965], [-120.563, 46.739] ]]) isCovered = polygon1.covers(polygon3) println isCovered

false
Polygon polygon1 = new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]])
Polygon polygon2 = new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]])
boolean isCoveredBy = polygon2.coveredBy(polygon1)
println isCoveredBy

true
Polygon polygon3 = new Polygon([[ [-120.563, 46.739], [-119.948, 46.739], [-119.948, 46.965], [-120.563, 46.965], [-120.563, 46.739] ]]) isCoveredBy = polygon3.coveredBy(polygon1) println isCoveredBy

false
LineString line1 = new LineString([[-122.486, 47.256], [-121.695, 46.822]])
LineString line2 = new LineString([[-122.387, 47.613], [-121.750, 47.353]])
LineString line3 = new LineString([[-122.255, 47.368], [-121.882, 47.746]])
boolean doesCross12 = line1.crosses(line2)
println doesCross12
boolean doesCross13 = line1.crosses(line3)
println doesCross13
boolean doesCross23 = line2.crosses(line3)
println doesCross23

false false true
Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Geometry difference = polygon1.difference(polygon2)

Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Geometry symDifference = polygon1.symDifference(polygon2)

Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Polygon polygon3 = new Polygon([[
[-120.541, 47.376],
[-120.695, 47.047],
[-119.794, 46.830],
[-119.586, 47.331],
[-120.102, 47.509],
[-120.541, 47.376]
]])
boolean isDisjoint12 = polygon1.disjoint(polygon2)
println isDisjoint12
boolean isDisjoint13 = polygon1.disjoint(polygon3)
println isDisjoint13
boolean isDisjoint23 = polygon2.disjoint(polygon3)
println isDisjoint23

false true true
Point point1 = new Point(-122.442, 47.256)
Point point2 = new Point(-122.321, 47.613)
double distance = point1.distance(point2)
println distance

0.37694827231332195
Point point = new Point(-123,46)
Polygon polygon = point.buffer(2)
Bounds bounds = polygon.bounds

Polygon polygon = new Polygon([
[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
],
[
[-122.255, 46.935],
[-121.992, 46.935],
[-121.992, 47.100],
[-122.255, 47.100],
[-122.255, 46.935]
],
[
[-121.717, 46.777],
[-121.398, 46.777],
[-121.398, 47.002],
[-121.717, 47.002],
[-121.717, 46.777]
]
])
Geometry boundary = polygon.boundary

Polygon polygon = new Polygon([[
[-118.937, 48.327],
[-121.157, 48.356],
[-121.684, 46.331],
[-119.355, 46.498],
[-119.355, 47.219],
[-120.629, 47.219],
[-120.607, 47.783],
[-119.201, 47.739],
[-118.937, 48.327]
]])
Geometry centroid = polygon.centroid

Polygon polygon = new Polygon([[
[-118.937, 48.327],
[-121.157, 48.356],
[-121.684, 46.331],
[-119.355, 46.498],
[-119.355, 47.219],
[-120.629, 47.219],
[-120.607, 47.783],
[-119.201, 47.739],
[-118.937, 48.327]
]])
Geometry interiorPoint = polygon.interiorPoint

MultiPoint multiPoint = new MultiPoint([
new Point(-122.3876953125, 47.5820839916191),
new Point(-122.464599609375, 47.25686404408872),
new Point(-122.48382568359374, 47.431803338643334)
])
int number = multiPoint.numGeometries
println number

3
MultiPoint multiPoint = new MultiPoint([
new Point(-122.3876953125, 47.5820839916191),
new Point(-122.464599609375, 47.25686404408872),
new Point(-122.48382568359374, 47.431803338643334)
])
(0..<multiPoint.getNumGeometries()).each { int i ->
Geometry geometry = multiPoint.getGeometryN(i)
println geometry.wkt
}

POINT (-122.3876953125 47.5820839916191) POINT (-122.464599609375 47.25686404408872) POINT (-122.48382568359374 47.431803338643334)
MultiPoint multiPoint = new MultiPoint([
new Point(-122.3876953125, 47.5820839916191),
new Point(-122.464599609375, 47.25686404408872),
new Point(-122.48382568359374, 47.431803338643334)
])
List<Geometry> geometries = multiPoint.geometries
geometries.each { Geometry geometry ->
println geometry.wkt
}

POINT (-122.3876953125 47.5820839916191) POINT (-122.464599609375 47.25686404408872) POINT (-122.48382568359374 47.431803338643334)
Polygon polygon = new Polygon([[
[-120.563, 46.739],
[-119.948, 46.739],
[-119.948, 46.965],
[-120.563, 46.965],
[-120.563, 46.739]
]])
int number = polygon.numPoints
println number

5
Geometry geometry = Geometry.createFromText("Geo")

Bounds bounds = new Bounds(21.645,36.957,21.676,36.970, "EPSG:4326")
Geometry geometry = Geometry.createSierpinskiCarpet(bounds, 50)

Bounds bounds = new Bounds(21.645,36.957,21.676,36.970, "EPSG:4326")
Geometry geometry = Geometry.createKochSnowflake(bounds, 50)

Geometry randomPoints = Geometry.createRandomPoints(new Bounds(-180,-90,180,90, "EPSG:4326").geometry, 100)
List<Geometry> bufferedPoints = randomPoints.collect{Geometry geom -> geom.buffer(4.5)}
Geometry unionedGeometry = Geometry.cascadedUnion(bufferedPoints)

Geometry geometry = new Bounds(-180, -90, 180, 90).geometry
MultiPoint randomPoints = Geometry.createRandomPoints(geometry, 100)

Bounds bounds = new Bounds(-180, -90, 180, 90)
MultiPoint randomPoints = Geometry.createRandomPointsInGrid(bounds, 100, true, 0.5)

Geometry points = Geometry.createRandomPoints(new Bounds(-180, -90, 180, 90).geometry, 100)
Geometry delaunayTriangle = points.delaunayTriangleDiagram

Geometry points = Geometry.createRandomPoints(new Bounds(-180, -90, 180, 90).geometry, 100)
Geometry voronoiDiagram = points.voronoiDiagram

Geometry geometry = Geometry.fromWKT("POLYGON ((-120.047607421875 48.100094697973795, -121.53076171875 48.44377831058802, " +
"-122.03613281249999 47.5394554474239, -120.81665039062499 47.249406957888446, -121.78344726562499 46.437856895024204, " +
"-119.20166015625 46.31658418182218, -118.05908203124999 47.39834920035926, -117.61962890624999 48.50204750525715, " +
"-119.3115234375 48.65468584817256, -119.20166015625 47.82053186746053, -120.003662109375 47.60616304386874, " +
"-120.0146484375 48.06339653776211, -120.047607421875 48.100094697973795))")
Geometry triangles = geometry.triangulate()

Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Geometry union = polygon1.union(polygon2)

Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Geometry intersection = polygon1.intersection(polygon2)

Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Polygon polygon3 = new Polygon([[
[-120.541, 47.376],
[-120.695, 47.047],
[-119.794, 46.830],
[-119.586, 47.331],
[-120.102, 47.509],
[-120.541, 47.376]
]])
boolean does1intersect2 = polygon1.intersects(polygon2)
println does1intersect2
boolean does1intersect3 = polygon1.intersects(polygon3)
println does1intersect3
boolean does2intersect3 = polygon2.intersects(polygon3)
println does2intersect3

true false false
Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Polygon polygon3 = new Polygon([[
[-120.541, 47.376],
[-120.695, 47.047],
[-119.794, 46.830],
[-119.586, 47.331],
[-120.102, 47.509],
[-120.541, 47.376]
]])
boolean does1overlap2 = polygon1.overlaps(polygon2)
println does1overlap2
boolean does1overlap3 = polygon1.overlaps(polygon3)
println does1overlap3
boolean does2overlap3 = polygon2.overlaps(polygon3)
println does2overlap3

true false false
Geometry geometry = new Polygon ([[
[-122.20367431640624, 47.543163654317304],
[-122.3712158203125, 47.489368981370724],
[-122.33276367187499, 47.35371061951363],
[-122.11029052734374, 47.3704545156932],
[-122.08831787109375, 47.286681888764214],
[-122.28332519531249, 47.2270293988673],
[-122.2174072265625, 47.154237057576594],
[-121.904296875, 47.32579231609051],
[-122.06085205078125, 47.47823216312885],
[-122.20367431640624, 47.543163654317304]
]])
Geometry octagonalEnvelope = geometry.octagonalEnvelope

Geometry geometry = new Polygon ([[
[-122.20367431640624, 47.543163654317304],
[-122.3712158203125, 47.489368981370724],
[-122.33276367187499, 47.35371061951363],
[-122.11029052734374, 47.3704545156932],
[-122.08831787109375, 47.286681888764214],
[-122.28332519531249, 47.2270293988673],
[-122.2174072265625, 47.154237057576594],
[-121.904296875, 47.32579231609051],
[-122.06085205078125, 47.47823216312885],
[-122.20367431640624, 47.543163654317304]
]])
Geometry minimumRectangle = geometry.minimumRectangle

Geometry geometry = new Polygon ([[
[-122.20367431640624, 47.543163654317304],
[-122.3712158203125, 47.489368981370724],
[-122.33276367187499, 47.35371061951363],
[-122.11029052734374, 47.3704545156932],
[-122.08831787109375, 47.286681888764214],
[-122.28332519531249, 47.2270293988673],
[-122.2174072265625, 47.154237057576594],
[-121.904296875, 47.32579231609051],
[-122.06085205078125, 47.47823216312885],
[-122.20367431640624, 47.543163654317304]
]])
Geometry minimumBoundingCircle = geometry.minimumBoundingCircle

Geometry geometry = new Polygon ([[
[-122.20367431640624, 47.543163654317304],
[-122.3712158203125, 47.489368981370724],
[-122.33276367187499, 47.35371061951363],
[-122.11029052734374, 47.3704545156932],
[-122.08831787109375, 47.286681888764214],
[-122.28332519531249, 47.2270293988673],
[-122.2174072265625, 47.154237057576594],
[-121.904296875, 47.32579231609051],
[-122.06085205078125, 47.47823216312885],
[-122.20367431640624, 47.543163654317304]
]])
Geometry minimumDiameter = geometry.minimumDiameter

Geometry geometry = new Polygon ([[
[-122.20367431640624, 47.543163654317304],
[-122.3712158203125, 47.489368981370724],
[-122.33276367187499, 47.35371061951363],
[-122.11029052734374, 47.3704545156932],
[-122.08831787109375, 47.286681888764214],
[-122.28332519531249, 47.2270293988673],
[-122.2174072265625, 47.154237057576594],
[-121.904296875, 47.32579231609051],
[-122.06085205078125, 47.47823216312885],
[-122.20367431640624, 47.543163654317304]
]])
Geometry minimumClearance = geometry.minimumClearance

Geometry g = Geometry.fromWKT("POLYGON ((-122.38855361938475 47.5805786829606, -122.38636493682861 47.5783206388176, " +
"-122.38700866699219 47.5750491969984, -122.38177299499512 47.57502024527343, " +
"-122.38481998443604 47.5780600889959, -122.38151550292969 47.5805786829606, " +
"-122.38855361938475 47.5805786829606))")
Geometry circle = g.getLargestEmptyCircle(1.0)

Geometry g = Geometry.fromWKT("POLYGON ((-122.38855361938475 47.5805786829606, -122.38636493682861 47.5783206388176, " +
"-122.38700866699219 47.5750491969984, -122.38177299499512 47.57502024527343, " +
"-122.38481998443604 47.5780600889959, -122.38151550292969 47.5805786829606, " +
"-122.38855361938475 47.5805786829606))")
Geometry circle = g.getMaximumInscribedCircle(1.0)

LineString line = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
LineString positive = line.offset(1.2)
LineString negative = line.offset(-2.4)

Point point = Geometry.fromWKT("POINT (-122.3437 47.7540)")
println "Point Dimension = ${point.dimension}"
LineString lineString = Geometry.fromWKT("LINESTRING (-122.525 47.256, -122.376 47.595)")
println "LineString Dimension = ${lineString.dimension}"
Polygon polygon = Geometry.fromWKT("POLYGON ((-122.590 47.204, -122.365 47.204, -122.365 47.312, -122.590 47.312, -122.590 47.204))")
println "Polygon Dimension = ${polygon.dimension}"
Point Dimension = 0 LineString Dimension = 1 Polygon Dimension = 2
Geometry geom1 = Geometry.fromWKT("POINT EMPTY")
boolean isGeom1Empty = geom1.empty
println "Is ${geom1.wkt} empty? ${isGeom1Empty ? 'Yes' : 'No'}"
Geometry geom2 = Geometry.fromWKT("POINT (-122.3437 47.7540)")
boolean isGeom2Empty = geom2.empty
println "Is ${geom2.wkt} empty? ${isGeom2Empty ? 'Yes' : 'No'}"
Is POINT EMPTY empty? Yes Is POINT (-122.3437 47.754) empty? No
Geometry geom1 = Geometry.fromWKT("POLYGON ((-122.590 47.204, -122.365 47.204, -122.365 47.312, -122.590 47.312, -122.590 47.204))")
boolean isGeom1Rect = geom1.isRectangle()
println "Is the geometry a rectangle? ${isGeom1Rect ? 'Yes' : 'No'}"

Is the geometry a rectangle? Yes
Geometry geom2 = Geometry.fromWKT("POLYGON ((-122.360 47.215, -122.656 46.912, -121.838 46.931, -122.360 47.215))") boolean isGeom2Rect = geom2.isRectangle() println "Is the geometry a rectangle? ${isGeom2Rect ? 'Yes' : 'No'}"

Is the geometry a rectangle? No
Geometry geom1 = new LineString(
[-122.323, 47.599],
[-122.385, 47.581]
)
boolean isGeom1Simple = geom1.simple
println "Is the Geometry simple? ${isGeom1Simple}"

Is the Geometry simple? true
Geometry geom2 = new LineString( [-122.356, 47.537], [-122.295, 47.580], [-122.284, 47.532], [-122.353, 47.574] ) boolean isGeom2Simple = geom2.simple println "Is the Geometry simple? ${isGeom2Simple}"

Is the Geometry simple? false
Geometry geom1 = new LineString(
[-122.323, 47.599],
[-122.385, 47.581]
)
boolean isGeom1Valid = geom1.valid
println "Is the Geometry valid? ${isGeom1Valid}"

Is the Geometry valid? true
Geometry geom2 = new Polygon(new LinearRing([ [48.16406, 42.29356], [35.15625, 25.79989], [64.33593, 24.52713], [26.71875, 39.09596], [48.16406, 42.29356], ])) boolean isGeom2Valid = geom2.valid println "Is the Geometry valid? ${isGeom2Valid}" println geom2.validReason

Is the Geometry valid? false Self-intersection
Geometry line = new LineString([[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [1, 1]])
println "LineString with duplicated Points = ${line.wkt}"
Geometry fixedLine = line.fix()
println "Fixed LineString = ${fixedLine}"

LineString with duplicated Points = LINESTRING (0 0, 0 0, 0 0, 0 0, 0 0, 1 1) Fixed LineString = LINESTRING (0 0, 1 1)
Geometry geom1 = new CircularString([
[-122.464599609375, 47.247542522268006],
[-122.03613281249999, 47.37789454155521],
[-122.37670898437499, 47.58393661978134]
])
boolean isGeom1Curved = geom1.curved
println "Is the Geometry valid? ${isGeom1Curved}"

Is the Geometry curved? true
Geometry geom2 = new LineString( [-122.323, 47.599], [-122.385, 47.581] ) boolean isGeom2Curved = geom2.curved println "Is the Geometry valid? ${isGeom2Curved}"

Is the Geometry curved? false
Geometry geom1 = new Point(-88.945, 41.771)
Geometry geom2 = new Point(-113.906, 37.160)
double distance1 = 26.0
boolean isWithin1 = geom1.isWithinDistance(geom2, distance1)
println "Is ${geom1} within ${distance1} of ${geom2}? ${isWithin1 ? 'Yes' : 'No'}"
Is POINT (-88.945 41.771) within 26.0 of POINT (-113.906 37.16)? Yes
double distance2 = 15.5 boolean isWithin2 = geom1.isWithinDistance(geom2, distance2) println "Is ${geom1} within ${distance2} of ${geom2}? ${isWithin2 ? 'Yes' : 'No'}"
Is POINT (-88.945 41.771) within 15.5 of POINT (-113.906 37.16)? No
Geometry geometry = Geometry.fromWKT("POLYGON((2 4, 1 3, 2 1, 6 1, 6 3, 4 4, 2 4))")
geometry.normalize()
println "Normalized Geometry = ${geometry}"

Normalized Geometry = POLYGON ((1 3, 2 4, 4 4, 6 3, 6 1, 2 1, 1 3))
Geometry geometry = Geometry.fromWKT("POLYGON((2 4, 1 3, 2 1, 6 1, 6 3, 4 4, 2 4))")
Geometry normalizedGeometry = geometry.norm
println "Un-normalized Geometry = ${geometry}"
println "Normalized Geometry = ${normalizedGeometry}"

Un-normalized Geometry = POLYGON ((2 4, 1 3, 2 1, 6 1, 6 3, 4 4, 2 4)) Normalized Geometry = POLYGON ((1 3, 2 4, 4 4, 6 3, 6 1, 2 1, 1 3))
Geometry geometry = Geometry.fromWKT("POLYGON((10 0, 10 20, 0 20, 0 30, 30 30, 30 20, 20 20, 20 0, 10 0))")
Geometry smoothed = geometry.smooth(0.75)

Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
IntersectionMatrix matrix = polygon1.relate(polygon2)
println "Intersection Matrix = ${matrix}"
println "Contains = ${matrix.contains}"
println "Covered By = ${matrix.coveredBy}"
println "Covers = ${matrix.covers}"
println "Disjoint = ${matrix.disjoint}"
println "Intersects = ${matrix.intersects}"
println "Within = ${matrix.within}"

Intersection Matrix = 212101212 Contains = false Covered By = false Covers = false Disjoint = false Intersects = true Within = false
Polygon polygon1 = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
println polygon1.relate(polygon2, "212101212")
println polygon1.relate(polygon2, "111111111")
println polygon1.relate(polygon2, "222222222")

true false false
Geometry geometry = new LineString([
[-122.28062152862547, 47.12986316579223],
[-122.2809863090515, 47.12935221617075],
[-122.2809863090515, 47.12786313499169],
[-122.28111505508421, 47.127731743474406],
[-122.28137254714966, 47.127673347140345],
[-122.28178024291992, 47.12768794622986],
[-122.28227376937865, 47.128067521151195],
[-122.28227376937865, 47.12906024275466]
])
Geometry densified = geometry.densify(0.0001)
println "# of points in original geometry = ${geometry.numPoints}"
println "# of points in densified geometry = ${densified.numPoints}"


# of points in original geometry = 8 # of points in densified geometry = 50
Geometry geometry = new LineString([
[-123.59619140625001, 47.338822694822],
[-123.04687499999999, 47.010225655683485],
[-122.2119140625, 46.965259400349275],
[-121.201171875, 47.17477833929903],
[-120.87158203125, 47.487513008956554],
[-120.62988281249999, 48.31242790407178],
[-120.84960937499999, 48.647427805533546],
[-121.59667968749999, 48.850258199721495],
[-122.36572265625, 48.980216985374994],
[-123.134765625, 48.83579746243093],
[-123.3984375, 48.44377831058802],
[-123.59619140625001, 48.10743118848039],
[-123.85986328124999, 47.62097541515849]
])
Geometry simplified = geometry.simplify(0.5)
println "# of points in original geometry = ${geometry.numPoints}"
println "# of points in simplified geometry = ${simplified.numPoints}"


# of points in original geometry = 13 # of points in simplified geometry = 5
Geometry geometry = new LineString([
[-123.59619140625001, 47.338822694822],
[-123.04687499999999, 47.010225655683485],
[-122.2119140625, 46.965259400349275],
[-121.201171875, 47.17477833929903],
[-120.87158203125, 47.487513008956554],
[-120.62988281249999, 48.31242790407178],
[-120.84960937499999, 48.647427805533546],
[-121.59667968749999, 48.850258199721495],
[-122.36572265625, 48.980216985374994],
[-123.134765625, 48.83579746243093],
[-123.3984375, 48.44377831058802],
[-123.59619140625001, 48.10743118848039],
[-123.85986328124999, 47.62097541515849]
])
Geometry simplified = geometry.simplifyPreservingTopology(0.1)
println "# of points in original geometry = ${geometry.numPoints}"
println "# of points in simplified geometry = ${simplified.numPoints}"


# of points in original geometry = 13 # of points in simplified geometry = 11
Geometry geometry = new Polygon(new LinearRing([
[-121.83837890625, 47.5913464767971],
[-122.76123046875, 46.9802523552188],
[-122.67333984374, 46.3014061543733],
[-121.00341796874, 46.3772542051002],
[-121.22314453124, 47.1448974855539],
[-121.83837890625, 47.5913464767971]
]))
Geometry translatedGeometry = geometry.translate(2.1, 3.2)

Geometry geometry = new Polygon(new LinearRing([
[-121.83837890625, 47.5913464767971],
[-122.76123046875, 46.9802523552188],
[-122.67333984374, 46.3014061543733],
[-121.00341796874, 46.3772542051002],
[-121.22314453124, 47.1448974855539],
[-121.83837890625, 47.5913464767971]
]))
Geometry scaledGeometry = geometry.scale(1.1,1.2)
println scaledGeometry

Geometry geometry = new Polygon(new LinearRing([
[-121.83837890625, 47.5913464767971],
[-122.76123046875, 46.9802523552188],
[-122.67333984374, 46.3014061543733],
[-121.00341796874, 46.3772542051002],
[-121.22314453124, 47.1448974855539],
[-121.83837890625, 47.5913464767971]
]))
Point centroid = geometry.centroid
Geometry scaledGeometry = geometry.scale(1.1, 1.1, centroid.x, centroid.y)

Geometry geometry = new Polygon(new LinearRing([
[-121.83837890625, 47.5913464767971],
[-122.76123046875, 46.9802523552188],
[-122.67333984374, 46.3014061543733],
[-121.00341796874, 46.3772542051002],
[-121.22314453124, 47.1448974855539],
[-121.83837890625, 47.5913464767971]
]))
Geometry theta = geometry.rotate(Math.toRadians(45))


Geometry thetaXY = geometry.rotate(Math.toRadians(90), geometry.centroid.x, geometry.centroid.y)

Geometry sinCos = geometry.rotate(Math.toRadians(15), Math.toRadians(35))


Geometry sinCosXY = geometry.rotate(Math.toRadians(15), Math.toRadians(35), geometry.centroid.x, geometry.centroid.y)

Geometry geometry = new Polygon(new LinearRing([
[-121.83837890625, 47.5913464767971],
[-122.76123046875, 46.9802523552188],
[-122.67333984374, 46.3014061543733],
[-121.00341796874, 46.3772542051002],
[-121.22314453124, 47.1448974855539],
[-121.83837890625, 47.5913464767971]
]))
Geometry shearedGeometry = geometry.shear(0.1,0.4)


Geometry geometry = new Polygon(new LinearRing([
[-121.83837890625, 47.5913464767971],
[-122.76123046875, 46.9802523552188],
[-122.67333984374, 46.3014061543733],
[-121.00341796874, 46.3772542051002],
[-121.22314453124, 47.1448974855539],
[-121.83837890625, 47.5913464767971]
]))
Point centroid = geometry.centroid
Geometry reflectedGeometry = geometry.reflect(0.1,0.4, centroid.x, centroid.y)

Geometry reflectedAroundOrigin = geometry.reflect(0.5, 0.34)


Geometry g1 = new Point(5.19775390625, 51.07421875)
println "Original Geometry: ${g1.wkt}"
Geometry g2 = g1.reducePrecision()
println "Floating Point Geometry: ${g2.wkt}"
Geometry g3 = g1.reducePrecision("fixed", scale: 100)
println "Fixed Point Geometry: ${g3.wkt}"
Geometry g4 = g1.reducePrecision("floating_single", pointwise: true, removecollapsed: true)
println "Floating Point Single Geometry: ${g4.wkt}"
Original Geometry: POINT (5.19775390625 51.07421875) Floating Point Geometry: POINT (5.19775390625 51.07421875) Fixed Point Geometry: POINT (5.2 51.07) Floating Point Single Geometry: POINT (5.19775390625 51.07421875)
Geometry point = new Point( -122.3845276236534, 47.58285653105873)
Geometry polygon = Geometry.fromWKT("POLYGON ((-122.3848307132721 47.58285110342092, " +
"-122.38484144210814 47.58255620092149, -122.38469392061235 47.582558010144346, " +
"-122.3846912384033 47.5825797208137, -122.38460808992384 47.58258695770149, " +
"-122.38460808992384 47.582628569786834, -122.38458126783371 47.58263037900717, " +
"-122.38458126783371 47.58277330721735, -122.38460540771483 47.58277149800195, " +
"-122.38460540771483 47.582805873084084, -122.38467246294022 47.5828131099406, " +
"-122.38467246294022 47.58285110342092, -122.3848307132721 47.58285110342092))")
List<Point> nearestPoints = polygon.getNearestPoints(point)

Geometry geometry = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
PreparedGeometry preparedGeometry = geometry.prepare()
Closure timer = { Closure action ->
long start = System.nanoTime()
action.call()
long end = System.nanoTime()
end - start
}
MultiPoint points = Geometry.createRandomPoints(new Bounds(-180, -90, 180, 90).geometry, 100000)
long timeWithGeometry = timer({ ->
points.geometries.each { Point point ->
geometry.contains(point)
}
})
println "Time with Geometry = ${timeWithGeometry} nanoseconds"
long timeWithPreparedGeometry = timer({ ->
points.geometries.each { Point point ->
preparedGeometry.contains(point)
}
})
println "Time with PreparedGeometry = ${timeWithPreparedGeometry} nanoseconds"
Time with Geometry = 222002302 nanoseconds Time with PreparedGeometry = 105851995 nanoseconds
Geometry geometry = new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]])
PreparedGeometry preparedGeometry = Geometry.prepare(geometry)
Closure timer = { Closure action ->
long start = System.nanoTime()
action.call()
long end = System.nanoTime()
end - start
}
MultiPoint points = Geometry.createRandomPoints(new Bounds(-180, -90, 180, 90).geometry, 100000)
long timeWithGeometry = timer({ ->
points.geometries.each { Point point ->
geometry.contains(point)
}
})
println "Time with Geometry = ${timeWithGeometry} nanoseconds"
long timeWithPreparedGeometry = timer({ ->
points.geometries.each { Point point ->
preparedGeometry.contains(point)
}
})
println "Time with PreparedGeometry = ${timeWithPreparedGeometry} nanoseconds"
Time with Geometry = 152446702 nanoseconds Time with PreparedGeometry = 93763731 nanoseconds
Prepared Geometry
PreparedGeometry are more effecient for spatial queries.
Polygon polygon = new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]])
PreparedGeometry preparedGeometry = new PreparedGeometry(polygon)
Geometry geometry = preparedGeometry.geometry

PreparedGeometry polygon1 = new PreparedGeometry(new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]]))
Polygon polygon2 = new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]])
boolean contains = polygon1.contains(polygon2)
println contains

true

false
PreparedGeometry polygon1 = new PreparedGeometry(new Polygon([[
[-122.50064849853516, 47.22096718353454],
[-122.41928100585938, 47.22096718353454],
[-122.41928100585938, 47.277365616965646],
[-122.50064849853516, 47.277365616965646],
[-122.50064849853516, 47.22096718353454]
]]))
Polygon polygon2 = new Polygon([[
[-122.44571685791014, 47.24031721435104],
[-122.42958068847656, 47.24031721435104],
[-122.42958068847656, 47.253135632244216],
[-122.44571685791014, 47.253135632244216],
[-122.44571685791014, 47.24031721435104]
]])
boolean contains = polygon1.containsProperly(polygon2)
println contains

true

false
Polygon polygon1 = new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]])
PreparedGeometry polygon2 = new PreparedGeometry(new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]]))
boolean isCoveredBy = polygon2.coveredBy(polygon1)
println isCoveredBy

true

false
PreparedGeometry polygon1 = new PreparedGeometry(new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]]))
Polygon polygon2 = new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]])
boolean isCovered = polygon1.covers(polygon2)
println isCovered

true

false
PreparedGeometry line1 = new PreparedGeometry(new LineString([[-122.387, 47.613], [-121.750, 47.353]]))
LineString line2 = new LineString([[-122.255, 47.368], [-121.882, 47.746]])
LineString line3 = new LineString([[-122.486, 47.256], [-121.695, 46.822]])
boolean doesCross12 = line1.crosses(line2)
println doesCross12
boolean doesCross13 = line1.crosses(line3)
println doesCross13

true false
PreparedGeometry polygon1 = new PreparedGeometry(new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]]))
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Polygon polygon3 = new Polygon([[
[-120.541, 47.376],
[-120.695, 47.047],
[-119.794, 46.830],
[-119.586, 47.331],
[-120.102, 47.509],
[-120.541, 47.376]
]])
boolean isDisjoint12 = polygon1.disjoint(polygon2)
println isDisjoint12
boolean isDisjoint13 = polygon1.disjoint(polygon3)
println isDisjoint13

false true
PreparedGeometry polygon1 = new PreparedGeometry(new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]]))
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Polygon polygon3 = new Polygon([[
[-120.541, 47.376],
[-120.695, 47.047],
[-119.794, 46.830],
[-119.586, 47.331],
[-120.102, 47.509],
[-120.541, 47.376]
]])
boolean does1intersect2 = polygon1.intersects(polygon2)
println does1intersect2
boolean does1intersect3 = polygon1.intersects(polygon3)
println does1intersect3

true false
PreparedGeometry polygon1 = new PreparedGeometry(new Polygon([[
[-121.915, 47.390],
[-122.640, 46.995],
[-121.739, 46.308],
[-121.168, 46.777],
[-120.981, 47.316],
[-121.409, 47.413],
[-121.915, 47.390]
]]))
Polygon polygon2 = new Polygon([[
[-120.794, 46.664],
[-121.541, 46.995],
[-122.200, 46.536],
[-121.937, 45.890],
[-120.959, 46.096],
[-120.794, 46.664]
]])
Polygon polygon3 = new Polygon([[
[-120.541, 47.376],
[-120.695, 47.047],
[-119.794, 46.830],
[-119.586, 47.331],
[-120.102, 47.509],
[-120.541, 47.376]
]])
boolean does1overlap2 = polygon1.overlaps(polygon2)
println does1overlap2
boolean does1overlap3 = polygon1.overlaps(polygon3)
println does1overlap3

true false
PreparedGeometry line1 = new PreparedGeometry(new LineString([
[-122.38651514053345, 47.58219978280006],
[-122.38651514053345, 47.58020234903306]
]))
LineString line2 = new LineString([
[-122.38651514053345, 47.58124449789785],
[-122.38333940505981, 47.58124449789785]
])
boolean touches = line1.touches(line2)

true
LineString line3 = new LineString([ [-122.386257648468, 47.58183793450921], [-122.38348960876465, 47.5818668824645] ]) touches = line1.touches(line3)

false
PreparedGeometry polygon1 = new PreparedGeometry(new Polygon([[
[-120.212, 47.591],
[-119.663, 47.591],
[-119.663, 47.872],
[-120.212, 47.872],
[-120.212, 47.591]
]]))
Polygon polygon2 = new Polygon([[
[-120.739, 48.151],
[-121.003, 47.070],
[-119.465, 47.137],
[-119.553, 46.581],
[-121.267, 46.513],
[-121.168, 45.706],
[-118.476, 45.951],
[-118.762, 48.195],
[-120.739, 48.151]
]])
boolean within = polygon1.within(polygon2)
println within

true
Polygon polygon3 = new Polygon([[ [-120.563, 46.739], [-119.948, 46.739], [-119.948, 46.965], [-120.563, 46.965], [-120.563, 46.739] ]]) within = polygon1.within(polygon3) println within

false
Reading and Writing Geometries
The geoscript.geom.io package has several Readers and Writers for converting geoscript.geom.Geometry to and from strings.
Readers and Writers
List<Reader> readers = Readers.list()
readers.each { Reader reader ->
println reader.class.simpleName
}
GeobufReader GeoJSONReader GeoRSSReader Gml2Reader Gml3Reader GpxReader KmlReader WkbReader WktReader GeoPackageReader GooglePolylineEncoder TWkbReader YamlReader
String wkt = "POINT (-123.15 46.237)"
Reader reader = Readers.find("wkt")
Geometry geometry = reader.read(wkt)

List<Writer> writers = Writers.list()
writers.each { Writer writer ->
println writer.class.simpleName
}
GeobufWriter GeoJSONWriter GeoRSSWriter Gml2Writer Gml3Writer GpxWriter KmlWriter WkbWriter WktWriter GeoPackageWriter GooglePolylineEncoder YamlWriter TWkbWriter
Geometry geometry = new Point(-122.45, 43.21)
Writer writer = Writers.find("geojson")
String geojson = writer.write(geometry)
println geojson
{"type":"Point","coordinates":[-122.45,43.21]}
Geometry geom1 = Geometry.fromString('POINT (-123.15 46.237)')
println geom1
Geometry geom2 = Geometry.fromString('{"type":"LineString","coordinates":[[3.198,43.164],[6.713,49.755],[9.702,42.592],[15.32,53.798]]}')
println geom2
Geometry geom3 = Geometry.fromString('<Point><coordinates>-123.15,46.237</coordinates></Point>')
println geom3
POINT (-123.15 46.237) LINESTRING (3.198 43.164, 6.713 49.755, 9.702 42.592, 15.32 53.798) POINT (-123.15 46.237)
WKB
String wkb = "0000000001C05EC9999999999A40471E5604189375"
WkbReader reader = new WkbReader()
Geometry geometry = reader.read(wkb)

String wkb = "000000000200000004400995810624DD2F404594FDF3B645A2401ADA1CAC0831274048E0A3D70A3D714023676C8B43958140454BC6A7EF9DB2402EA3D70A3D70A4404AE624DD2F1AA0"
Geometry geometry = Geometry.fromWKB(wkb)

Geometry geometry = new Point(-123.15, 46.237)
String wkb = geometry.wkb
println wkb
0000000001C05EC9999999999A40471E5604189375
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
WkbWriter writer = new WkbWriter()
String wkb = writer.write(geometry)
println wkb
000000000200000004400995810624DD2F404594FDF3B645A2401ADA1CAC0831274048E0A3D70A3D714023676C8B43958140454BC6A7EF9DB2402EA3D70A3D70A4404AE624DD2F1AA0
WKT
String wkt = "POINT (-123.15 46.237)"
WktReader reader = new WktReader()
Geometry geometry = reader.read(wkt)

String wkt = "LINESTRING (3.198 43.164, 6.7138 49.755, 9.702 42.592, 15.327 53.798)"
Geometry geometry = Geometry.fromWKT(wkt)

Geometry geometry = new Point(-123.15, 46.237)
String wkt = geometry.wkt
println wkt
POINT (-123.15 46.237)
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
WktWriter writer = new WktWriter()
String wkt = writer.write(geometry)
println wkt
LINESTRING (3.198 43.164, 6.713 49.755, 9.702 42.592, 15.32 53.798)
TWKB
String twkb = "E10801BFCBB99609A0D3F9B80300"
Geometry geometry = Geometry.fromTwkb(twkb)

Geometry geometry = new Point(-123.15, 46.237)
String twkb = geometry.twkb
println twkb
E10801BFCBB99609A0D3F9B80300
TWkbReader reader = new TWkbReader()
Geometry geometry = reader.read("E10801BFCBB99609A0D3F9B80300")
println geometry.wkt
POINT (-123.15 46.237)

Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
TWkbWriter writer = new TWkbWriter()
String twkb = writer.write(geometry)
println twkb
E2080104C0E7BF1E80B7D29B0300E0E2C221E0D3ED3E00A0D7C01CDFF2A74400C0F4C935C099EF6A00
GeoJSON
String json = '{"type":"Point","coordinates":[-123.15,46.237]}'
GeoJSONReader reader = new GeoJSONReader()
Geometry geometry = reader.read(json)

String json = '{"type":"LineString","coordinates":[[3.198,43.164],[6.713,49.755],[9.702,42.592],[15.32,53.798]]}'
Geometry geometry = Geometry.fromGeoJSON(json)

Geometry geometry = new Point(-123.15, 46.237)
String json = geometry.geoJSON
println json
{"type":"Point","coordinates":[-123.15,46.237]}
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
GeoJSONWriter writer = new GeoJSONWriter()
String json = writer.write(geometry)
println json
{"type":"LineString","coordinates":[[3.198,43.164],[6.713,49.755],[9.702,42.592],[15.32,53.798]]}
GeoPackage
String str = "4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375"
GeoPackageReader reader = new GeoPackageReader()
Geometry geometry = reader.read(str)

byte[] bytes = "4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375".decodeHex()
GeoPackageReader reader = new GeoPackageReader()
Geometry geometry = reader.read(bytes)

Geometry geometry = new Point(-123.15, 46.237)
GeoPackageWriter writer = new GeoPackageWriter()
String str = writer.write(geometry)
println str
4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375
Geometry geometry = new Point(-123.15, 46.237)
GeoPackageWriter writer = new GeoPackageWriter()
byte[] bytes = writer.writeBytes(geometry)
println bytes.encodeHex()
4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375
KML
String kml = "<Point><coordinates>-123.15,46.237</coordinates></Point>"
KmlReader reader = new KmlReader()
Geometry geometry = reader.read(kml)

String kml = "<LineString><coordinates>3.198,43.164 6.713,49.755 9.702,42.592 15.32,53.798</coordinates></LineString>"
Geometry geometry = Geometry.fromKml(kml)

Geometry geometry = new Point(-123.15, 46.237)
String kml = geometry.kml
println kml
<Point><coordinates>-123.15,46.237</coordinates></Point>
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
KmlWriter writer = new KmlWriter()
String kml = writer.write(geometry)
println kml
<LineString><coordinates>3.198,43.164 6.713,49.755 9.702,42.592 15.32,53.798</coordinates></LineString>
Geobuf
String geobuf = "10021806320c08001a08dffab87590958c2c"
GeobufReader reader = new GeobufReader()
Geometry geometry = reader.read(geobuf)

String geobuf = "10021806322408021a20e0b08603c0859529f089ad03b0c8a40690efec02efb1ea06a0e5ad05e0f5d70a"
Geometry geometry = Geometry.fromGeobuf(geobuf)

Geometry geometry = new Point(-123.15, 46.237)
String geobuf = geometry.geobuf
println geobuf
10021806320c08001a08dffab87590958c2c
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
GeobufWriter writer = new GeobufWriter()
String geobuf = writer.write(geometry)
println geobuf
10021806322408021a20e0b08603c0859529f089ad03b0c8a40690efec02efb1ea06a0e5ad05e0f5d70a
GML 2
String gml2 = "<gml:Point><gml:coordinates>-123.15,46.237</gml:coordinates></gml:Point>"
Gml2Reader reader = new Gml2Reader()
Geometry geometry = reader.read(gml2)

String gml2 = "<gml:LineString><gml:coordinates>3.198,43.164 6.713,49.755 9.702,42.592 15.32,53.798</gml:coordinates></gml:LineString>"
Geometry geometry = Geometry.fromGML2(gml2)

Geometry geometry = new Point(-123.15, 46.237)
String gml2 = geometry.gml2
println gml2
<gml:Point><gml:coordinates>-123.15,46.237</gml:coordinates></gml:Point>
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
Gml2Writer writer = new Gml2Writer()
String gml2 = writer.write(geometry)
println gml2
<gml:LineString><gml:coordinates>3.198,43.164 6.713,49.755 9.702,42.592 15.32,53.798</gml:coordinates></gml:LineString>
GML 3
String gml3 = "<gml:Point><gml:pos>-123.15 46.237</gml:pos></gml:Point>"
Gml3Reader reader = new Gml3Reader()
Geometry geometry = reader.read(gml3)

String gml3 = "<gml:LineString><gml:posList>3.198 43.164 6.713 49.755 9.702 42.592 15.32 53.798</gml:posList></gml:LineString>"
Geometry geometry = Geometry.fromGML3(gml3)

Geometry geometry = new Point(-123.15, 46.237)
String gml3 = geometry.gml3
println gml3
<gml:Point><gml:pos>-123.15 46.237</gml:pos></gml:Point>
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
Gml3Writer writer = new Gml3Writer()
String gml3 = writer.write(geometry)
println gml3
<gml:LineString><gml:posList>3.198 43.164 6.713 49.755 9.702 42.592 15.32 53.798</gml:posList></gml:LineString>
GPX
String gpx = "<wpt lat='46.237' lon='-123.15'/>"
GpxReader reader = new GpxReader()
Geometry geometry = reader.read(gpx)

String gpx = "<rte><rtept lat='43.164' lon='3.198' /><rtept lat='49.755' lon='6.713' /><rtept lat='42.592' lon='9.702' /><rtept lat='53.798' lon='15.32' /></rte>"
Geometry geometry = Geometry.fromGpx(gpx)

Geometry geometry = new Point(-123.15, 46.237)
String gpx = geometry.gpx
println gpx
<wpt lat='46.237' lon='-123.15'/>
Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
GpxWriter writer = new GpxWriter()
String gpx = writer.write(geometry)
println gpx
<rte><rtept lat='43.164' lon='3.198' /><rtept lat='49.755' lon='6.713' /><rtept lat='42.592' lon='9.702' /><rtept lat='53.798' lon='15.32' /></rte>
GeoRSS
String georss = "<georss:point>46.237 -123.15</georss:point>"
GeoRSSReader reader = new GeoRSSReader()
Geometry geometry = reader.read(georss)

Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
GeoRSSWriter writer = new GeoRSSWriter()
String georss = writer.write(geometry)
println georss
<georss:line>43.164 3.198 49.755 6.713 42.592 9.702 53.798 15.32</georss:line>
Google Polyline
String str = "_p~iF~ps|U_ulLnnqC_mqNvxq`@"
GooglePolylineEncoder encoder = new GooglePolylineEncoder()
Geometry geometry = encoder.read(str)

Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
GooglePolylineEncoder encoder = new GooglePolylineEncoder()
String str = encoder.write(geometry)
println str
_nmfGoroRwhfg@womTv_vj@gxfQotkcAogha@
YAML
String yaml = """---
geometry:
type: "Point"
coordinates:
- -122.23
- 45.67
"""
Geometry geometry = Geometry.fromYaml(yaml)

Geometry geometry = new Point(-123.15, 46.237)
String yaml = geometry.yaml
println yaml
--- geometry: type: Point coordinates: - -123.15 - 46.237
String yaml = """---
geometry:
type: "Point"
coordinates:
- -122.23
- 45.67
"""
YamlReader reader = new YamlReader()
Geometry geometry = reader.read(yaml)

Geometry geometry = new LineString(
[3.198, 43.164],
[6.713, 49.755],
[9.702, 42.592],
[15.32, 53.798]
)
YamlWriter writer = new YamlWriter()
String yaml = writer.write(geometry)
println yaml
--- geometry: type: LineString coordinates: - - 3.198 - 43.164 - - 6.713 - 49.755 - - 9.702 - 42.592 - - 15.32 - 53.798
Bounds Recipes
The Bounds class is in the geoscript.geom package.
It represents a minimum bounding box or rectangle, so it has minimum and maximum x and y coordinates in a specified projection.
Creating Bounds
Bounds bounds = new Bounds(-127.265, 43.068, -113.554, 50.289, "EPSG:4326")

Bounds bounds = new Bounds(-127.265, 43.068, -113.554, 50.289)
bounds.proj = new Projection("EPSG:4326")

Bounds bounds = Bounds.fromString("-127.265,43.068,-113.554,50.289,EPSG:4326")

Bounds bounds = Bounds.fromString("12.919921874999998 40.84706035607122 15.99609375 41.77131167976407 EPSG:4326")

Getting Bounds Properties
Bounds bounds = new Bounds(-127.265, 43.068, -113.554, 50.289, "EPSG:4326")
String boundsStr = bounds.toString()
println boundsStr
(-127.265,43.068,-113.554,50.289,EPSG:4326)
double minX = bounds.minX
println minX
-127.265
double minY = bounds.minY
println minY
43.068
double maxX = bounds.maxX
println maxX
-113.554
double maxY = bounds.maxY
println maxY
50.289
Projection proj = bounds.proj
println proj.id
EPSG:4326
double area = bounds.area
println area
99.00713100000004
double width = bounds.width
println width
13.710999999999999
double height = bounds.height
println height
7.221000000000004
double aspect = bounds.aspect
println aspect
1.8987674837280144
Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
Geometry geometry = bounds.geometry

Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
Polygon polygon = bounds.polygon

Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
List<Point> points = bounds.corners

Processing Bounds
Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
println bounds
(-122.485,47.246,-122.452,47.267,EPSG:4326)
Bounds reprojectedBounds = bounds.reproject("EPSG:2927")
println reprojectedBounds
(1147444.7684518,703506.2231641796,1155828.1202425023,711367.9403610165,EPSG:2927)
Bounds bounds1 = new Bounds(-127.265, 43.068, -113.554, 50.289, "EPSG:4326")
Bounds bounds2 = new Bounds(-127.265, 43.068, -113.554, 50.289, "EPSG:4326")
bounds2.expandBy(10.1)

Bounds bounds1 = new Bounds(8.4375, 37.996162679728116, 19.6875, 46.07323062540835, "EPSG:4326")
Bounds bounds2 = new Bounds(22.5, 31.952162238024975, 30.937499999999996, 37.43997405227057, "EPSG:4326")
bounds1.expand(bounds2)

Bounds bounds1 = new Bounds(-127.265, 43.068, -113.554, 50.289, "EPSG:4326")
Bounds bounds2 = bounds1.scale(2)

Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
List<Bounds> subBounds = bounds.tile(0.25)

Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326")
bounds.quadTree(0,2) { Bounds b ->
println b
}
(-180.0,-90.0,180.0,90.0,EPSG:4326) (-180.0,-90.0,0.0,0.0,EPSG:4326) (-180.0,0.0,0.0,90.0,EPSG:4326) (0.0,-90.0,180.0,0.0,EPSG:4326) (0.0,0.0,180.0,90.0,EPSG:4326)
Bounds bounds = new Bounds(0,10,10,20)
println bounds.isEmpty()
false
Bounds emptyBounds = new Bounds(0,10,10,10)
println emptyBounds.isEmpty()
true
Bounds bounds1 = new Bounds(-107.226, 34.597, -92.812, 43.068)
Bounds bounds2 = new Bounds(-104.326, 37.857, -98.349, 40.913)
println bounds1.contains(bounds2)

true
Bounds bounds3 = new Bounds(-112.412, 36.809, -99.316, 44.777)
println bounds1.contains(bounds3)

false
Bounds bounds = new Bounds(-107.226, 34.597, -92.812, 43.068)
Point point1 = new Point(-95.976, 39.639)
println bounds.contains(point1)

true
Point point2 = new Point(-89.384, 38.959)
println bounds.contains(point2)

true
Bounds bounds1 = new Bounds(-95.885, 46.765, -95.788, 46.811)
Bounds bounds2 = new Bounds(-95.847, 46.818, -95.810, 46.839)
println bounds1.intersects(bounds2)

false
Bounds bounds3 = new Bounds(-95.904, 46.747, -95.839, 46.792)
println bounds1.intersects(bounds3)

true
Bounds bounds1 = new Bounds(-95.885, 46.765, -95.788, 46.811)
Bounds bounds2 = new Bounds(-95.904, 46.747, -95.839, 46.792)
Bounds bounds3 = bounds1.intersection(bounds2)

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(5,4,"polygon")

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
List geometries = []
Geometry geometry = bounds.generateGrid(10,8,"point") { Geometry g, int col, int row ->
geometries.add(g)
}

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(72.0,72.0,"circle")

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
List geometries = []
Geometry geometry = bounds.generateGrid(72.0,72.0,"hexagon") { Geometry g, int col, int row ->
geometries.add(g)
}

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(5,5,"hexagon-inv")

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(5,5,"triangle")

Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createRectangle(20,Math.toRadians(45))

Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createEllipse()

Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createSquircle()

Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createSuperCircle(1.75)

Bounds bounds = new Bounds(0,0,20,20)
LineString lineString = bounds.createArc(Math.toRadians(45), Math.toRadians(90))

Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createArcPolygon(Math.toRadians(45), Math.toRadians(90))

Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createSineStar(5, 2.3)

Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createHexagon(false)

Projection Recipes
The Projection classes are in the geoscript.proj package.
Creating Projections
Projection proj = new Projection("EPSG:4326")
println proj.wkt
GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4326"]]
Projection proj = new Projection("""GEOGCS["WGS 84",
DATUM["World Geodetic System 1984",
SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]],
UNIT["degree", 0.017453292519943295],
AXIS["Geodetic longitude", EAST],
AXIS["Geodetic latitude", NORTH],
AUTHORITY["EPSG","4326"]]""")
GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4326"]]
Projection proj = new Projection("Mollweide")
println proj.wkt
PROJCS["Mollweide", GEOGCS["WGS84", DATUM["WGS84", SPHEROID["WGS84", 6378137.0, 298.257223563]], PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH]], PROJECTION["Mollweide"], PARAMETER["semi-minor axis", 6378137.0], PARAMETER["False easting", 0.0], PARAMETER["False northing", 0.0], PARAMETER["Longitude of natural origin", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH]]
List<Projection> projections = Projection.projections()
EPSG:4326 EPSG:4269 EPSG:26918 EPSG:2263 EPSG:2927 ...
Getting Projection Properties
Projection proj = new Projection("EPSG:4326")
String id = proj.id
EPSG:4326
String srs = proj.srs
EPSG:4326
int epsg = proj.epsg
4326
String wkt = proj.wkt
GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4326"]]
Bounds bounds = proj.bounds
(-180.0,-90.0,180.0,90.0,EPSG:4326)
Bounds geoBounds = proj.geoBounds
(-180.0,-90.0,180.0,90.0,EPSG:4326)
Using Projections
Geometry epsg4326Geom = new Point(-122.440, 47.245)
Geometry epsg2927Geom = Projection.transform(epsg4326Geom, "EPSG:4326", "EPSG:2927")
println epsg2927Geom
POINT (1158609.2040371664 703068.0661327793)
Projection epsg4326 = new Projection("EPSG:4326")
Projection epsg2927 = new Projection("EPSG:2927")
Geometry epsg4326Geom = new Point(-122.440, 47.245)
Geometry epsg2927Geom = Projection.transform(epsg4326Geom, epsg4326, epsg2927)
println epsg2927Geom
POINT (1158609.2040371664 703068.0661327793)
Projection fromProj = new Projection("EPSG:4326")
Projection toProj = new Projection("EPSG:2927")
Geometry geom = new Point(-122.440, 47.245)
Geometry projectedGeom = fromProj.transform(geom, toProj)
println projectedGeom
POINT (1158609.2040371664 703068.0661327793)
Projection fromProj = new Projection("EPSG:4326")
Geometry geom = new Point(-122.440, 47.245)
Geometry projectedGeom = fromProj.transform(geom, "EPSG:2927")
println projectedGeom
POINT (1158609.2040371664 703068.0661327793)
Using Geodetic
Geodetic geodetic = new Geodetic("wgs84")
println geodetic
Geodetic [SPHEROID["WGS 84", 6378137.0, 298.257223563]]
Geodetic geodetic = new Geodetic("clrk66")
Point bostonPoint = new Point(-71.117, 42.25)
Point portlandPoint = new Point(-123.683, 45.52)
Map results = geodetic.inverse(bostonPoint, portlandPoint)
double forwardAzimuth = results.forwardAzimuth
println forwardAzimuth
-66.52547810974724
double backAzimuth = results.backAzimuth
println backAzimuth
75.65817457195088
double distance = results.distance
println distance
4164050.459880065
Geodetic geodetic = new Geodetic("clrk66")
Point bostonPoint = new Point(-71.117, 42.25)
Map results = geodetic.forward(bostonPoint, -66.531, 4164192.708)
Point point = results.point
println point
POINT (-123.6835797667373 45.51642779589723)
double azimuth = results.backAzimuth
println azimuth
75.65337425050723
Geodetic geodetic = new Geodetic("clrk66")
Point bostonPoint = new Point(-71.117, 42.25)
Point portlandPoint = new Point(-123.683, 45.52)
List<Point> points = geodetic.placePoints(bostonPoint, portlandPoint, 10)
points.each { Point point ->
println point.wkt
}
POINT (-75.41357382496236 43.52791689304304) POINT (-79.8828640042499 44.63747566950249) POINT (-84.51118758826816 45.565540142641005) POINT (-89.27793446221685 46.300124344169255) POINT (-94.15564606698499 46.83102721803566) POINT (-99.11079892605703 47.15045006457598) POINT (-104.10532353179985 47.25351783423774) POINT (-109.09873812691617 47.13862709798196) POINT (-114.05062990603696 46.80756425557422) POINT (-118.92312608779855 46.26537395700513)
Using Decimal Degrees
DecimalDegrees decimalDegrees = new DecimalDegrees(-122.525619, 47.212023)
println decimalDegrees
-122° 31' 32.2284" W, 47° 12' 43.2828" N
DecimalDegrees decimalDegrees = new DecimalDegrees(new Point(-122.525619,47.212023))
println decimalDegrees
POINT (-122.52561944444444 47.212022222222224)
DecimalDegrees decimalDegrees = new DecimalDegrees("-122.525619, 47.212023")
println decimalDegrees
-122° 31' 32.2284" W, 47° 12' 43.2828" N
DecimalDegrees decimalDegrees = new DecimalDegrees("122\u00B0 31' 32.23\" W", "47\u00B0 12' 43.28\" N")
println decimalDegrees
-122° 31' 32.2300" W, 47° 12' 43.2800" N
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31m 32.23s W", "47d 12m 43.28s N")
println decimalDegrees
-122° 31' 32.2300" W, 47° 12' 43.2800" N
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31m 32.23s W, 47d 12m 43.28s N")
println decimalDegrees
-122° 31' 32.2300" W, 47° 12' 43.2800" N
DecimalDegrees decimalDegrees = new DecimalDegrees("122\u00B0 31.5372' W, 47\u00B0 12.7213' N")
println decimalDegrees
-122° 31' 32.2320" W, 47° 12' 43.2780" N
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31.5372m W, 47d 12.7213m N")
println decimalDegrees
-122° 31' 32.2320" W, 47° 12' 43.2780" N
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31m 32.23s W", "47d 12m 43.28s N")
Map dms = decimalDegrees.dms
println "Degrees: ${dms.longitude.degrees}"
println "Minutes: ${dms.longitude.minutes}"
println "Seconds: ${dms.longitude.seconds}"
Degrees: -122 Minutes: 31 Seconds: 32.22999999998388
println "Degrees: ${dms.latitude.degrees}"
println "Minutes: ${dms.latitude.minutes}"
println "Seconds: ${dms.latitude.seconds}"
Degrees: 47 Minutes: 12 Seconds: 43.280000000006396
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31m 32.23s W", "47d 12m 43.28s N")
println decimalDegrees.toDms(true)
-122° 31' 32.2300" W, 47° 12' 43.2800" N
println decimalDegrees.toDms(false)
-122d 31m 32.2300s W, 47d 12m 43.2800s N
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31m 32.23s W", "47d 12m 43.28s N")
Map dms = decimalDegrees.ddm
println "Degrees: ${dms.longitude.degrees}"
println "Minutes: ${dms.longitude.minutes}"
Degrees: -122 Minutes: 31.537166666666398
println "Degrees: ${dms.latitude.degrees}"
println "Minutes: ${dms.latitude.minutes}"
Degrees: 47 Minutes: 12.72133333333344
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31m 32.23s W", "47d 12m 43.28s N")
println decimalDegrees.toDdm(true)
-122° 31.5372' W, 47° 12.7213' N
println decimalDegrees.toDdm(false)
-122d 31.5372m W, 47d 12.7213m N
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31m 32.23s W", "47d 12m 43.28s N")
Point point = decimalDegrees.point
POINT (-122.52561944444444 47.212022222222224)
Spatial Index Recipes
The Index classes are in the geoscript.index package.
Using STRtree
STRtree index = new STRtree()
index.insert(new Bounds(0,0,10,10), new Point(5,5))
index.insert(new Bounds(2,2,6,6), new Point(4,4))
index.insert(new Bounds(20,20,60,60), new Point(30,30))
index.insert(new Bounds(22,22,44,44), new Point(32,32))
int size = index.size
println size
4
List results = index.query(new Bounds(1,1,5,5))
results.each { Geometry geometry ->
println geometry
}
POINT (4 4) POINT (5 5)
Using HPRtree
HPRtree index = new HPRtree()
index.insert(new Bounds(0,0,10,10), new Point(5,5))
index.insert(new Bounds(2,2,6,6), new Point(4,4))
index.insert(new Bounds(20,20,60,60), new Point(30,30))
index.insert(new Bounds(22,22,44,44), new Point(32,32))
int size = index.size
println size
4
List results = index.query(new Bounds(1,1,5,5))
results.each { Geometry geometry ->
println geometry
}
POINT (5 5) POINT (4 4)
Using Quadtree
Quadtree index = new Quadtree()
index.insert(new Bounds(0,0,10,10), new Point(5,5))
index.insert(new Bounds(2,2,6,6), new Point(4,4))
index.insert(new Bounds(20,20,60,60), new Point(30,30))
index.insert(new Bounds(22,22,44,44), new Point(32,32))
int size = index.size
println size
4
List results = index.query(new Bounds(1,1,5,5))
results.each { Geometry geometry ->
println geometry
}
POINT (30 30) POINT (32 32) POINT (5 5) POINT (4 4)
List allResults = index.queryAll()
allResults.each { Geometry geometry ->
println geometry
}
POINT (30 30) POINT (32 32) POINT (5 5) POINT (4 4)
Geometry itemToRemove = allResults[0]
boolean removed = index.remove(itemToRemove.bounds, itemToRemove)
println "Removed? ${removed}"
println "Size = ${index.size}"
Removed = true Size = 3
Using GeoHash
GeoHash geohash = new GeoHash()
Point point = new Point(112.5584, 37.8324)
String hash = geohash.encode(point)
println hash
ww8p1r4t8
GeoHash geohash = new GeoHash()
Point point = geohash.decode("ww8p1r4t8")
println point
POINT (112.55838632583618 37.83238649368286)
GeoHash geohash = new GeoHash()
Point point = new Point(112.5584, 37.8324)
long hash = geohash.encodeLong(point)
println long
4064984913515641
GeoHash geohash = new GeoHash()
Point point = geohash.decode(4064984913515641)
println point
POINT (112.55839973688126 37.83240124583244)
GeoHash geohash = new GeoHash()
Bounds bounds = geohash.decodeBounds("ww8p1r4t8")
println bounds
(112.55836486816406,37.83236503601074,112.5584077835083,37.83240795135498)
GeoHash geohash = new GeoHash()
Bounds bounds = geohash.decodeBounds(4064984913515641)
println bounds
(112.55836486816406,37.83236503601074,112.5584077835083,37.83240795135498)
GeoHash geohash = new GeoHash()
String hash = "dqcjq"
String north = geohash.neighbor(hash, GeoHash.Direction.NORTH)
String northwest = geohash.neighbor(hash, GeoHash.Direction.NORTHWEST)
String west = geohash.neighbor(hash, GeoHash.Direction.WEST)
String southwest = geohash.neighbor(hash, GeoHash.Direction.SOUTHWEST)
String south = geohash.neighbor(hash, GeoHash.Direction.SOUTH)
String southeast = geohash.neighbor(hash, GeoHash.Direction.SOUTHEAST)
String east = geohash.neighbor(hash, GeoHash.Direction.EAST)
String northeast = geohash.neighbor(hash, GeoHash.Direction.NORTHEAST)
String str = """
| ${northwest} ${north} ${northeast}
| ${west} ${hash} ${east}
| ${southwest} ${south} ${southeast}
|""".stripMargin()
println str
dqcjt dqcjw dqcjx dqcjm dqcjq dqcjr dqcjj dqcjn dqcjp
GeoHash geohash = new GeoHash()
long hash = 1702789509
long north = geohash.neighbor(hash, GeoHash.Direction.NORTH)
long northwest = geohash.neighbor(hash, GeoHash.Direction.NORTHWEST)
long west = geohash.neighbor(hash, GeoHash.Direction.WEST)
long southwest = geohash.neighbor(hash, GeoHash.Direction.SOUTHWEST)
long south = geohash.neighbor(hash, GeoHash.Direction.SOUTH)
long southeast = geohash.neighbor(hash, GeoHash.Direction.SOUTHEAST)
long east = geohash.neighbor(hash, GeoHash.Direction.EAST)
long northeast = geohash.neighbor(hash, GeoHash.Direction.NORTHEAST)
String str = """
| ${northwest} ${north} ${northeast}
| ${west} ${hash} ${east}
| ${southwest} ${south} ${southeast}
|""".stripMargin()
println str
1702789434 1702789520 1702789522 1702789423 1702789509 1702789511 1702789422 1702789508 1702789510
GeoHash geohash = new GeoHash()
String hash = "dqcjq"
Map neighbors = geohash.neighbors(hash)
String north = neighbors[GeoHash.Direction.NORTH]
String northwest = neighbors[GeoHash.Direction.NORTHWEST]
String west = neighbors[GeoHash.Direction.WEST]
String southwest = neighbors[GeoHash.Direction.SOUTHWEST]
String south = neighbors[GeoHash.Direction.SOUTH]
String southeast = neighbors[GeoHash.Direction.SOUTHEAST]
String east = neighbors[GeoHash.Direction.EAST]
String northeast = neighbors[GeoHash.Direction.NORTHEAST]
String str = """
| ${northwest} ${north} ${northeast}
| ${west} ${hash} ${east}
| ${southwest} ${south} ${southeast}
|""".stripMargin()
println str
dqcjt dqcjw dqcjx dqcjm dqcjq dqcjr dqcjj dqcjn dqcjp
GeoHash geohash = new GeoHash()
long hash = 1702789509
Map neighbors = geohash.neighbors(hash)
long north = neighbors[GeoHash.Direction.NORTH]
long northwest = neighbors[GeoHash.Direction.NORTHWEST]
long west = neighbors[GeoHash.Direction.WEST]
long southwest = neighbors[GeoHash.Direction.SOUTHWEST]
long south = neighbors[GeoHash.Direction.SOUTH]
long southeast = neighbors[GeoHash.Direction.SOUTHEAST]
long east = neighbors[GeoHash.Direction.EAST]
long northeast = neighbors[GeoHash.Direction.NORTHEAST]
String str = """
| ${northwest} ${north} ${northeast}
| ${west} ${hash} ${east}
| ${southwest} ${south} ${southeast}
|""".stripMargin()
println str
1702789434 1702789520 1702789522 1702789423 1702789509 1702789511 1702789422 1702789508 1702789510
GeoHash geohash = new GeoHash()
List<String> bboxes = geohash.bboxes(new Bounds(120, 30, 120.0001, 30.0001), 8)
bboxes.each { String hash ->
println hash
}
wtm6dtm6 wtm6dtm7
GeoHash geohash = new GeoHash()
List<Long> bboxes = geohash.bboxesLong(new Bounds(120, 30, 120.0001, 30.0001), 40)
bboxes.each { long hash ->
println hash
}
989560464998 989560464999
Viewer Recipes
The Viewer classes are in the geoscript.viewer package.
Drawing geometries
Polygon polygon = new Polygon([[
[-101.35986328125, 47.754097979680026],
[-101.5576171875, 46.93526088057719],
[-100.12939453125, 46.51351558059737],
[-99.77783203125, 47.44294999517949],
[-100.45898437499999, 47.88688085106901],
[-101.35986328125, 47.754097979680026]
]])
Viewer.draw(polygon)

Polygon polygon = new Polygon([[
[-101.35986328125, 47.754097979680026],
[-101.5576171875, 46.93526088057719],
[-100.12939453125, 46.51351558059737],
[-99.77783203125, 47.44294999517949],
[-100.45898437499999, 47.88688085106901],
[-101.35986328125, 47.754097979680026]
]])
BufferedImage image = Viewer.drawToImage(polygon)

Polygon polygon = new Polygon([[
[-101.35986328125, 47.754097979680026],
[-101.5576171875, 46.93526088057719],
[-100.12939453125, 46.51351558059737],
[-99.77783203125, 47.44294999517949],
[-100.45898437499999, 47.88688085106901],
[-101.35986328125, 47.754097979680026]
]])
BufferedImage image = Viewer.drawToImage(
polygon,
size: [200,200],
drawCoords: true,
fillCoords: true,
fillPolys: true
)

Point point = new Point(-123.11, 47.23)
Geometry buffer = point.buffer(4)
Geometry bounds = buffer.bounds.geometry
BufferedImage image = Viewer.drawToImage(
[bounds, buffer, point],
size: [200,200],
drawCoords: true,
fillCoords: true,
fillPolys: true
)

Point point = new Point(-123.11, 47.23)
Geometry buffer = point.buffer(4)
File file = new File("geometry.png")
Viewer.drawToFile([buffer, point], file, size: [200,200])

Polygon polygon = new Polygon([[
[-101.35986328125, 47.754097979680026],
[-101.5576171875, 46.93526088057719],
[-100.12939453125, 46.51351558059737],
[-99.77783203125, 47.44294999517949],
[-100.45898437499999, 47.88688085106901],
[-101.35986328125, 47.754097979680026]
]])
String base64EncodedString = Viewer.drawToBase64EncodedString(polygon)
println base64EncodedString
image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADL1t+KAAAR/ElEQVR4Xu3bC47kxrVFUc1VA30z0JT8ELKvXXWU9UkyfiTXBhZg2SmpO8jk...
Plotting geometries
Polygon polygon = new Polygon([[
[-101.35986328125, 47.754097979680026],
[-101.5576171875, 46.93526088057719],
[-100.12939453125, 46.51351558059737],
[-99.77783203125, 47.44294999517949],
[-100.45898437499999, 47.88688085106901],
[-101.35986328125, 47.754097979680026]
]])
Viewer.plot(polygon)

Polygon polygon = new Polygon([[
[-101.35986328125, 47.754097979680026],
[-101.5576171875, 46.93526088057719],
[-100.12939453125, 46.51351558059737],
[-99.77783203125, 47.44294999517949],
[-100.45898437499999, 47.88688085106901],
[-101.35986328125, 47.754097979680026]
]])
BufferedImage image = Viewer.plotToImage(polygon)

Point point = new Point(-123.11, 47.23)
Geometry buffer = point.buffer(4)
Geometry bounds = buffer.bounds.geometry
BufferedImage image = Viewer.plotToImage(
[bounds, buffer, point],
size: [300,300],
drawCoords: true,
fillCoords: true,
fillPolys: true
)

Point point = new Point(-123.11, 47.23)
Geometry buffer = point.buffer(4)
File file = new File("geometry.png")
Viewer.plotToFile([buffer, point], file, size: [300,300])

Plot Recipes
The Plot classes are in the geoscript.plot package.
Processing Charts
List data = [
[1,10],[45,12],[23,3],[5,20]
]
Chart chart = Bar.xy(data)

Map data = [
"A":20,"B":45,"C":2,"D":14
]
Chart chart = Pie.pie(data)
BufferedImage image = chart.image

Map data = [
"A":[1,10,20],
"B":[45,39,10],
"C":[40,30,20],
"D":[14,25,19]
]
Chart chart = Box.box(data)
File file = new File("chart.png")
chart.save(file)

List data = [
[1,10],[45,12],[23,3],[5,20]
]
Chart chart1 = Bar.xy(data)
Chart chart2 = Curve.curve(data)
Chart chart3 = Regression.linear(data)
chart1.overlay([chart2,chart3])

Creating Bar Charts
List data = [
[1,10],[45,12],[23,3],[5,20]
]
Chart chart = Bar.xy(data)

Map data = [
"A":20,"B":45,"C":2,"D":14
]
Chart chart = Bar.category(data)

Map data = [
"A": ["B":50,"C":25,"D":25],
"F": ["G":75,"H":10,"I":15]
]
Chart chart = Bar.category(data, stacked: true)

Map data = [
"A":20,"B":45,"C":2,"D":14
]
Chart chart = Bar.category(data, trid: true)

Creating Pie Charts
Map data = [
"A":20,"B":45,"C":2,"D":14
]
Chart chart = Pie.pie(data)

Map data = [
"A":20,"B":45,"C":2,"D":14
]
Chart chart = Pie.pie(data, trid: true)

Creating Box Charts
Map data = [
"A":[1,10,20],
"B":[45,39,10],
"C":[40,30,20],
"D":[14,25,19]
]
Chart chart = Box.box(data)

Creating Curve Charts
List data = [
[1,10],[45,12],[23,3],[5,20]
]
Chart chart = Curve.curve(data)

List data = [
[1,10],[45,12],[23,3],[5,20]
]
Chart chart = Curve.curve(data, smooth: true)

List data = [
[1,10],[45,12],[23,3],[5,20]
]
Chart chart = Curve.curve(data, trid: true)

Creating Regression Charts
MultiPoint mulitPoint = Geometry.createRandomPoints(new Bounds(0,0,100,100).geometry, 10)
List data = mulitPoint.geometries.collect{ Point pt ->
[pt.x, pt.y]
}
Chart chart = Regression.linear(data)

MultiPoint mulitPoint = Geometry.createRandomPoints(new Bounds(0,0,100,100).geometry, 10)
List data = mulitPoint.geometries.collect{ Point pt ->
[pt.x, pt.y]
}
Chart chart = Regression.power(data)

Creating Scatter Plot Charts
MultiPoint mulitPoint = Geometry.createRandomPoints(new Bounds(0,0,100,100).geometry, 10)
List data = mulitPoint.geometries.collect{ Point pt ->
[pt.x, pt.y]
}
Chart chart = Scatter.scatterplot(data)

MultiPoint mulitPoint = Geometry.createRandomPoints(new Bounds(0,0,100,100).geometry, 10)
List data = mulitPoint.geometries.collect{ Point pt ->
[pt.x, pt.y]
}
Chart chart = Scatter.scatterplot(data, legend: false, xLabel: "X Coordinates", yLabel: "Y Coordinates")

Feature Recipes
The Feature classes are in the geoscript.feature package.
The major classes in this package include Field, Schema, and Feature.
A Field has a name and a type and describes a column of data.
A Schema is a collection of Fields together with a name. Schemas are used to create new Layers.
A Feature contains a geometry and a collection of attributes. A collection of Features is called a Layer.
Creating Fields
Field field = new Field("name", "String")
println field
name: String
Field field = new Field("geom", "Point", "EPSG:4326")
println field
geom: Point(EPSG:4326)
Field field = new Field(["geom", "Polygon", "EPSG:4326"])
println field
geom: Polygon(EPSG:4326)
Field field = new Field([
"name": "geom",
"type": "LineString",
"proj": new Projection("EPSG:4326")
])
println field
geom: LineString(EPSG:4326)
Field field = new Field("geom", "Point", "EPSG:4326")
println "Name = ${field.name}"
println "Type = ${field.typ}"
println "Projection = ${field.proj}"
println "Is Geometry = ${field.geometry}"
Name = geom Type = Point Projection = "EPSG:4326 Is Geometry = true
Creating Schemas
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
println schema
cities geom: Point(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("cities", [
["geom", "Point", "EPSG:4326"],
["id", "Integer"],
["name", "String"]
])
println schema
cities geom: Point(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("cities", [
[name: "geom", type: "Point", proj: "EPSG:4326"],
[name: "id", type: "Integer"],
[name: "name", type: "String"]
])
println schema
cities geom: Point(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("cities", "geom:Point:srid=4326,id:Integer,name:String")
println schema
cities geom: Point(EPSG:4326), id: Integer, name: String
Getting Schema Properties
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
], "https://github.com/jericks/geoscript-groovy-cookbook")
String name = schema.name
println name
cities
Field geomField = schema.geom
println geomField
geom: Point(EPSG:4326)
Projection proj = schema.proj
println proj
EPSG:4326
String uri = schema.uri
println uri
https://github.com/jericks/geoscript-groovy-cookbook
String spec = schema.spec
println spec
geom:Point:srid=4326,id:Integer,name:String
Getting Schema Fields
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
List<Field> fields = schema.fields
fields.each { Field field ->
println field
}
geom: Point(EPSG:4326) id: Integer name: String
Field nameField = schema.field("name")
println nameField
name: String
Field idField = schema.get("id")
println idField
id: Integer
boolean hasArea = schema.has("area")
println "Has area Field? ${hasArea}"
boolean hasGeom = schema.has("geom")
println "Has geom Field? ${hasGeom}"
false true
Modifying Schemas
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema reprojectedSchema = schema.reproject("EPSG:2927", "cities_spws")
cities_spws geom: Point(EPSG:2927), id: Integer, name: String
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema polyognSchema = schema.changeGeometryType("Polygon", "cities_buffer")
cities_buffer geom: Polygon(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema guidSchema = schema.changeField(schema.field('id'), new Field('guid','String'), 'cities_guid')
cities_guid geom: Point(EPSG:4326), guid: String, name: String
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema updatedSchema = schema.changeFields(
[
(schema.field('id')) : new Field('guid','String'),
(schema.field('name')) : new Field('description','String')
], 'cities_updated')
cities_updated geom: Point(EPSG:4326), guid: String, description: String
Schema schema = new Schema("countries", [
new Field("geom", "Polygon", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema updatedSchema = schema.addField(new Field("area", "Double"), "countries_area")
countries_area geom: Polygon(EPSG:4326), id: Integer, name: String, area: Double
Schema schema = new Schema("countries", [
new Field("geom", "Polygon", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema updatedSchema = schema.addFields([
new Field("area", "Double"),
new Field("perimeter", "Double"),
], "countries_areaperimeter")
countries_areaperimeter geom: Polygon(EPSG:4326), id: Integer, name: String, area: Double, perimeter: Double
Schema schema = new Schema("countries", [
new Field("geom", "Polygon", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("area", "Double")
])
Schema updatedSchema = schema.removeField(schema.field("area"), "countries_updated")
countries_updated geom: Polygon(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("countries", [
new Field("geom", "Polygon", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("area", "Double")
])
Schema updatedSchema = schema.removeFields([
schema.field("area"),
schema.field("name")
], "countries_updated")
countries_updated geom: Polygon(EPSG:4326), id: Integer
Schema schema = new Schema("countries", [
new Field("geom", "Polygon", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("area", "Double")
])
Schema updatedSchema = schema.removeFields([
schema.field("area"),
schema.field("name")
], "countries_updated")
countries_updated geom: Polygon(EPSG:4326), name: String
Combining Schemas
Combining two Schemas results in a Map with two values: schema and fields. The schema property contains the new Schema. The fields property is List of two Maps which both contain a mapping between the fields of the original Schema and the newly created Schema.
Optional arguments to the Schema.addSchema method are:
-
postfixAll: Whether to postfix all field names (true) or not (false). If true, all Fields from the this current Schema will have '1' at the end of their name while the other Schema’s Fields will have '2'. Defaults to false.
-
includeDuplicates: Whether or not to include duplicate fields names. Defaults to false. If a duplicate is found a '2' will be added.
-
maxFieldNameLength: The maximum new Field name length (mostly to support shapefiles where Field names can’t be longer than 10 characters
-
firstPostfix: The postfix string (default is '1') for Fields from the current Schema. Only applicable when postfixAll or includeDuplicates is true.
-
secondPostfix: The postfix string (default is '2') for Fields from the other Schema. Only applicable when postfixAll or includeDuplicates is true.
Schema shopSchema = new Schema("shops", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema cafeSchema = new Schema("cafes", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("address", "String")
])
Map result = shopSchema.addSchema(cafeSchema, "business")
Schema combinedSchema = result.schema
println combinedSchema
business geom: Point(EPSG:4326), id: Integer, name: String, address: String
Map<String,String> shopSchemaFieldMapping = result.fields[0]
println shopSchemaFieldMapping
[geom:geom, id:id, name:name]
Map<String,String> cafeSchemaSchemaFieldMapping = result.fields[1]
println cafeSchemaSchemaFieldMapping
[address:address]
Schema shopSchema = new Schema("shops", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Schema cafeSchema = new Schema("cafes", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("address", "String")
])
Map result = shopSchema.addSchema(cafeSchema, "business", postfixAll: true, includeDuplicates: false)
Schema combinedSchema = result.schema
println combinedSchema
business geom: Point(EPSG:4326), id1: Integer, name1: String, id2: Integer, name2: String, address2: String
Map<String,String> shopSchemaFieldMapping = result.fields[0]
println shopSchemaFieldMapping
[geom:geom, id:id1, name:name1]
Map<String,String> cafeSchemaSchemaFieldMapping = result.fields[1]
println cafeSchemaSchemaFieldMapping
[id:id2, name:name2, address:address2]
Creating Features from a Schema
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = schema.feature([
id: 1,
name: 'Seattle',
geom: new Point( -122.3204, 47.6024)
], "city.1")
println feature
cities.city.1 geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = schema.feature([
new Point( -122.3204, 47.6024),
1,
'Seattle'
], "city.1")
println feature
cities.city.1 geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature1 = new Feature([
id: 1,
name: 'Seattle',
geom: new Point( -122.3204, 47.6024)
], "city.1", schema)
println feature1
Feature feature2 = schema.feature(feature1)
println feature2
cities.city.1 geom: POINT (-122.3204 47.6024), id: 1, name: Seattle cities.city.1 geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = schema.feature()
println feature
cities.fid--1c8a8332_18ba0aee183_-4bf2 geom: null, id: null, name: null
Reading and Writing Schemas
The Schema IO classes are in the geoscript.feature.io package.
Finding Schema Writer and Readers
List<SchemaWriter> writers = SchemaWriters.list()
writers.each { SchemaWriter writer ->
println writer.class.simpleName
}
JsonSchemaWriter StringSchemaWriter XmlSchemaWriter
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
SchemaWriter writer = SchemaWriters.find("string")
String schemaStr = writer.write(schema)
println schemaStr
geom:Point:srid=4326,id:Integer,name:String
List<SchemaReader> readers = SchemaReaders.list()
readers.each { SchemaReader reader ->
println reader.class.simpleName
}
JsonSchemaReader StringSchemaReader XmlSchemaReader
SchemaReader reader = SchemaReaders.find("string")
Schema schema = reader.read("geom:Point:srid=4326,id:Integer,name:String")
println schema
layer geom: Point(EPSG:4326), id: Integer, name: String
String
StringSchemaReader reader = new StringSchemaReader()
Schema schema = reader.read("geom:Point:srid=4326,id:Integer,name:String", name: "points")
println schema
points geom: Point(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
StringSchemaWriter writer = new StringSchemaWriter()
String schemaStr = writer.write(schema)
println schemaStr
geom:Point:srid=4326,id:Integer,name:String
JSON
JsonSchemaReader reader = new JsonSchemaReader()
Schema schema = reader.read("""{
"name": "cities",
"projection": "EPSG:4326",
"geometry": "geom",
"fields": [
{
"name": "geom",
"type": "Point",
"geometry": true,
"projection": "EPSG:4326"
},
{
"name": "id",
"type": "Integer"
},
{
"name": "name",
"type": "String"
}
]
}""")
println schema
cities geom: Point(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
JsonSchemaWriter writer = new JsonSchemaWriter()
String schemaStr = writer.write(schema)
println schemaStr
{ "name": "cities", "projection": "EPSG:4326", "geometry": "geom", "fields": [ { "name": "geom", "type": "Point", "geometry": true, "projection": "EPSG:4326" }, { "name": "id", "type": "Integer" }, { "name": "name", "type": "String" } ] }
XML
XmlSchemaReader reader = new XmlSchemaReader()
Schema schema = reader.read("""<schema>
<name>cities</name>
<projection>EPSG:4326</projection>
<geometry>geom</geometry>
<fields>
<field>
<name>geom</name>
<type>Point</type>
<projection>EPSG:4326</projection>
</field>
<field>
<name>id</name>
<type>Integer</type>
</field>
<field>
<name>name</name>
<type>String</type>
</field>
</fields>
</schema>""")
println schema
cities geom: Point(EPSG:4326), id: Integer, name: String
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
XmlSchemaWriter writer = new XmlSchemaWriter()
String schemaStr = writer.write(schema)
println schemaStr
<schema> <name>cities</name> <projection>EPSG:4326</projection> <geometry>geom</geometry> <fields> <field> <name>geom</name> <type>Point</type> <projection>EPSG:4326</projection> </field> <field> <name>id</name> <type>Integer</type> </field> <field> <name>name</name> <type>String</type> </field> </fields> </schema>
Creating Features
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
id: 1,
name: "Seattle",
geom: new Point(-122.3204, 47.6024)
], "city.1", schema)
println feature
cities.city.1 geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
println feature
cities.city.1 geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
Feature feature = new Feature([
id: 1,
name: "Seattle",
geom: new Point(-122.3204, 47.6024)
], "city.1")
println feature
feature.city.1 id: 1, name: Seattle, geom: POINT (-122.3204 47.6024)
Getting Feature Properties
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String id = feature.id
println id
city.1
Geometry geometry = feature.geom
println geometry
POINT (-122.3204 47.6024)
Bounds bounds = feature.bounds
println bounds
(-122.3204,47.6024,-122.3204,47.6024,EPSG:4326)
Map attributes = feature.attributes
println attributes
[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]
Getting Feature Attributes
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
int id = feature.get("id")
println id
1
String name = feature.get(schema.field("name"))
println name
Seattle
feature.set("name", "Tacoma")
println feature["name"]
Tacoma
feature.set(schema.field("name"), "Mercer Island")
println feature["name"]
Mercer Island
feature.set([id: 2])
println feature["id"]
2
feature.geom = new Point(-122.2220, 47.5673)
println feature.geom
POINT (-122.222 47.5673)
Reading and Writing Features
The Feature IO classes are in the geoscript.feature.io package.
Finding Feature Writer and Readers
List<Writer> writers = Writers.list()
writers.each { Writer writer ->
println writer.class.simpleName
}
GeobufWriter GeoJSONWriter GeoRSSWriter GmlWriter GpxWriter KmlWriter YamlWriter
Writer writer = Writers.find("geojson")
println writer.class.simpleName
GeoJSONWriter
List<Reader> readers = Readers.list()
readers.each { Reader reader ->
println reader.class.simpleName
}
GeobufReader GeoJSONReader GeoRSSReader GmlReader GpxReader KmlReader YamlReader
Reader reader = Readers.find("geojson")
println reader.class.simpleName
GeoJSONReader
GeoJSON
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String geojson = feature.geoJSON
println geojson
{"type":"Feature","geometry":{"type":"Point","coordinates":[-122.3204,47.6024]},"properties":{"id":1,"name":"Seattle"},"id":"city.1"}
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
GeoJSONWriter writer = new GeoJSONWriter()
String geojson = writer.write(feature)
println geojson
{"type":"Feature","geometry":{"type":"Point","coordinates":[-122.3204,47.6024]},"properties":{"id":1,"name":"Seattle"},"id":"city.1"}
String geojson = '{"type":"Feature","geometry":{"type":"Point","coordinates":[-122.3204,47.6024]},"properties":{"id":1,"name":"Seattle"},"id":"city.1"}'
Feature feature = Feature.fromGeoJSON(geojson)
println feature
feature.city.1 id: 1, name: Seattle, geometry: POINT (-122.3204 47.6024)
GeoJSONReader reader = new GeoJSONReader()
String geojson = '{"type":"Feature","geometry":{"type":"Point","coordinates":[-122.3204,47.6024]},"properties":{"id":1,"name":"Seattle"},"id":"city.1"}'
Feature feature = reader.read(geojson)
println feature
feature.city.1 id: 1, name: Seattle, geometry: POINT (-122.3204 47.6024)
GeoBuf
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String geobuf = feature.geobuf
println geobuf
0a0269640a046e616d65100218062a2b0a0c08001a089fd8d374c0ebb22d5a06636974792e316a0218016a090a0753656174746c65720400000101
String geobuf = '0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65'
Feature feature = Feature.fromGeobuf(geobuf)
println feature
features. geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
GeobufWriter writer = new GeobufWriter()
String geobuf = writer.write(feature)
println geobuf
0a0269640a046e616d65100218062a2b0a0c08001a089fd8d374c0ebb22d5a06636974792e316a0218016a090a0753656174746c65720400000101
GeobufReader reader = new GeobufReader()
String geobuf = '0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65'
Feature feature = reader.read(geobuf)
println feature
features. geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
GeoRSS
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String georss = feature.geoRSS
println georss
<entry xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'><title>city.1</title><summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary><updated>Sun Nov 05 18:12:10 UTC 2023</updated><georss:point>47.6024 -122.3204</georss:point></entry>
String georss = """<entry xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'>
<title>city.1</title>
<summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary>
<updated>Sat Jan 28 15:51:47 PST 2017</updated>
<georss:point>47.6024 -122.3204</georss:point>
</entry>
"""
Feature feature = Feature.fromGeoRSS(georss)
println feature
georss.fid--1c8a8332_18ba0aee183_-4bf6 title: city.1, summary: [geom:POINT (-122.3204 47.6024), id:1, name:Seattle], updated: Sat Jan 28 15:51:47 PST 2017, geom: POINT (-122.3204 47.6024)
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
GeoRSSWriter writer = new GeoRSSWriter()
String georss = writer.write(feature)
println georss
<entry xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'><title>city.1</title><summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary><updated>Sun Nov 05 18:12:10 UTC 2023</updated><georss:point>47.6024 -122.3204</georss:point></entry>
GeoRSSReader reader = new GeoRSSReader()
String georss = """<entry xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'>
<title>city.1</title>
<summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary>
<updated>Sat Jan 28 15:51:47 PST 2017</updated>
<georss:point>47.6024 -122.3204</georss:point>
</entry>
"""
Feature feature = reader.read(georss)
println feature
georss.fid--1c8a8332_18ba0aee183_-4bf4 title: city.1, summary: [geom:POINT (-122.3204 47.6024), id:1, name:Seattle], updated: Sat Jan 28 15:51:47 PST 2017, geom: POINT (-122.3204 47.6024)
GML
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String gml = feature.gml
println gml
<gsf:cities xmlns:gsf="http://geoscript.org/feature" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" fid="city.1"> <gml:name>Seattle</gml:name> <gsf:geom> <gml:Point> <gml:coord> <gml:X>-122.3204</gml:X> <gml:Y>47.6024</gml:Y> </gml:coord> </gml:Point> </gsf:geom> <gsf:id>1</gsf:id> </gsf:cities>
String gml = """<gsf:cities xmlns:gsf="http://geoscript.org/feature" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" fid="city.1">
<gml:name>Seattle</gml:name>
<gsf:geom>
<gml:Point>
<gml:coord>
<gml:X>-122.3204</gml:X>
<gml:Y>47.6024</gml:Y>
</gml:coord>
</gml:Point>
</gsf:geom>
<gsf:id>1</gsf:id>
</gsf:cities>
"""
Feature feature = Feature.fromGml(gml)
println feature
feature.city.1 name: Seattle, id: 1, geom: POINT (-122.3204 47.6024)
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
GmlWriter writer = new GmlWriter()
String gml = writer.write(feature)
println gml
<gsf:cities xmlns:gsf="http://geoscript.org/feature" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" fid="city.1"> <gml:name>Seattle</gml:name> <gsf:geom> <gml:Point> <gml:coord> <gml:X>-122.3204</gml:X> <gml:Y>47.6024</gml:Y> </gml:coord> </gml:Point> </gsf:geom> <gsf:id>1</gsf:id> </gsf:cities>
GmlReader reader = new GmlReader()
String gml = """<gsf:cities xmlns:gsf="http://geoscript.org/feature" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" fid="city.1">
<gml:name>Seattle</gml:name>
<gsf:geom>
<gml:Point>
<gml:coord>
<gml:X>-122.3204</gml:X>
<gml:Y>47.6024</gml:Y>
</gml:coord>
</gml:Point>
</gsf:geom>
<gsf:id>1</gsf:id>
</gsf:cities>
"""
Feature feature = reader.read(gml)
println feature
feature.city.1 name: Seattle, id: 1, geom: POINT (-122.3204 47.6024)
GPX
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String gpx = feature.gpx
println gpx
<wpt lat='47.6024' lon='-122.3204' xmlns='http://www.topografix.com/GPX/1/1'><name>city.1</name></wpt>
String gpx = "<wpt lat='47.6024' lon='-122.3204' xmlns='http://www.topografix.com/GPX/1/1'><name>city.1</name></wpt>"
Feature feature = Feature.fromGpx(gpx)
println feature
gpx.fid--1c8a8332_18ba0aee183_-4bf3 geom: POINT (-122.3204 47.6024), name: city.1
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
GpxWriter writer = new GpxWriter()
String gpx = writer.write(feature)
println gpx
<wpt lat='47.6024' lon='-122.3204' xmlns='http://www.topografix.com/GPX/1/1'><name>city.1</name></wpt>
GpxReader reader = new GpxReader()
String gpx = "<wpt lat='47.6024' lon='-122.3204' xmlns='http://www.topografix.com/GPX/1/1'><name>city.1</name></wpt>"
Feature feature = reader.read(gpx)
println feature
gpx.fid--1c8a8332_18ba0aee183_-4bf5 geom: POINT (-122.3204 47.6024), name: city.1
KML
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String kml = feature.kml
println kml
<kml:Placemark xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1" id="city.1"><kml:name>Seattle</kml:name><kml:Point><kml:coordinates>-122.3204,47.6024</kml:coordinates></kml:Point></kml:Placemark>
String kml = """<kml:Placemark xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1" id="city.1">
<kml:name>Seattle</kml:name>
<kml:Point>
<kml:coordinates>-122.3204,47.6024</kml:coordinates>
</kml:Point>
</kml:Placemark>"""
Feature feature = Feature.fromKml(kml)
println feature
placemark.city.1 name: Seattle, description: null, Geometry: POINT (-122.3204 47.6024)
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
KmlWriter writer = new KmlWriter()
String kml = writer.write(feature)
println kml
<kml:Placemark xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1" id="city.1"><kml:name>Seattle</kml:name><kml:Point><kml:coordinates>-122.3204,47.6024</kml:coordinates></kml:Point></kml:Placemark>
KmlReader reader = new KmlReader()
String kml = """<kml:Placemark xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1" id="city.1">
<kml:name>Seattle</kml:name>
<kml:Point>
<kml:coordinates>-122.3204,47.6024</kml:coordinates>
</kml:Point>
</kml:Placemark>"""
Feature feature = reader.read(kml)
println feature
placemark.city.1 name: Seattle, description: null, Geometry: POINT (-122.3204 47.6024)
YAML
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
String yaml = feature.yaml
println yaml
--- type: Feature properties: id: 1 name: Seattle geometry: type: Point coordinates: - -122.3204 - 47.6024
String yaml = """---
type: "Feature"
properties:
id: 1
name: "Seattle"
geometry:
type: "Point"
coordinates:
- -122.3204
- 47.6024
"""
Feature feature = Feature.fromYaml(yaml)
println feature
feature.1 id: 1, name: Seattle, geom: POINT (-122.3204 47.6024)
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Feature feature = new Feature([
new Point(-122.3204, 47.6024),
1,
"Seattle"
], "city.1", schema)
YamlWriter writer = new YamlWriter()
String yml = writer.write(feature)
println yml
--- type: Feature properties: id: 1 name: Seattle geometry: type: Point coordinates: - -122.3204 - 47.6024
YamlReader reader = new YamlReader()
String yml = """---
type: "Feature"
properties:
id: 1
name: "Seattle"
geometry:
type: "Point"
coordinates:
- -122.3204
- 47.6024
"""
Feature feature = reader.read(yml)
println feature
feature.1 id: 1, name: Seattle, geom: POINT (-122.3204 47.6024)
Filter Recipes
The Filter classes are in the geoscript.filter package.
Creating Filters
Filter filter = new Filter("name='Seattle'")
println filter.toString()
[ name = Seattle ]
Filter filter = new Filter("<filter><PropertyIsEqualTo><PropertyName>soilType</PropertyName><Literal>Mollisol</Literal></PropertyIsEqualTo></filter>")
println filter.toString()
[ soilType = Mollisol ]
Filter filter = Filter.PASS
println filter.toString()
Filter.INCLUDE
Filter filter = Filter.FAIL
println filter.toString()
Filter.EXCLUDE
Filter filter = Filter.bbox(new Bounds(-102, 43.5, -100, 47.5))
println filter.toString()
[ the_geom bbox ReferencedEnvelope[-102.0 : -100.0, 43.5 : 47.5] ]
Filter filter = Filter.contains(Geometry.fromWKT("POLYGON ((-104 45, -95 45, -95 50, -104 50, -104 45))"))
println filter.toString()
[ the_geom contains POLYGON ((-104 45, -95 45, -95 50, -104 50, -104 45)) ]
Filter filter = Filter.dwithin("the_geom", Geometry.fromWKT("POINT (-100 47)"), 10.2, "feet")
println filter.toString()
[ the_geom dwithin POINT (-100 47), distance: 10.2 ]
Filter filter = Filter.crosses("the_geom", Geometry.fromWKT("LINESTRING (-104 45, -95 45)"))
println filter.toString()
[ the_geom crosses LINESTRING (-104 45, -95 45) ]
Filter filter = Filter.intersects(Geometry.fromWKT("POLYGON ((-104 45, -95 45, -95 50, -104 50, -104 45))"))
println filter.toString()
[ the_geom intersects POLYGON ((-104 45, -95 45, -95 50, -104 50, -104 45)) ]
Filter filter = Filter.id("points.1")
println filter.toString()
[ points.1 ]
Filter filter = Filter.ids(["points.1","points.2","points.3"])
println filter.toString()
[ points.1, points.2, points.3 ]
Filter filter = Filter.equals("name", "Washington")
println filter.toString()
[ name = Washington ]
Using Filters
Filter filter = new Filter("name='Seattle'")
String cql = filter.cql
println cql
name = 'Seattle'
String xml = filter.xml
println xml
<ogc:Filter xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> <ogc:PropertyIsEqualTo> <ogc:PropertyName>name</ogc:PropertyName> <ogc:Literal>Seattle</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:Filter>
Filter cityFilter = new Filter("city = 'Seattle'")
Filter stateFilter = new Filter("state = 'WA'")
Filter andFilter = cityFilter.and(stateFilter)
println andFilter
[[ city = Seattle ] AND [ state = WA ]]
Filter cityFilter = new Filter("city = 'Seattle'")
Filter stateFilter = new Filter("state = 'WA'")
Filter andFilter = cityFilter + stateFilter
println andFilter
[[ city = Seattle ] AND [ state = WA ]]
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter tacomaFilter = new Filter("city = 'Tacoma'")
Filter orFilter = seattleFilter.or(tacomaFilter)
println orFilter
[[ city = Seattle ] OR [ city = Tacoma ]]
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter notSeattleFilter = seattleFilter.not
println notSeattleFilter
[ NOT [ city = Seattle ] ]
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter notSeattleFilter = -seattleFilter
println notSeattleFilter
[ NOT [ city = Seattle ] ]
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter filter = (seattleFilter + Filter.PASS).simplify()
println filter
[ city = Seattle ]
Evaluating Filters
Feature feature = new Feature([
id: 1,
name: "Seattle",
geom: new Point(-122.3204, 47.6024)
], "city.1")
Filter isNameFilter = new Filter("name='Seattle'")
boolean isName = isNameFilter.evaluate(feature)
println isName
true
Filter isNotNameFilter = new Filter("name='Tacoma'") boolean isNotName = isNotNameFilter.evaluate(feature) println isNotName
false
Filter isIdFilter = Filter.id("city.1")
boolean isId = isIdFilter.evaluate(feature)
println isId
true
Filter isNotIdFilter = Filter.id("city.2") boolean isNotId = isNotIdFilter.evaluate(feature) println isNotId
false
Filter isInBboxFilter = Filter.bbox("geom", new Bounds(-132.539, 42.811, -111.796, 52.268))
boolean isInBbox = isInBboxFilter.evaluate(feature)
println isInBbox
true
Filter isNotInBboxFilter = Filter.bbox("geom", new Bounds(-12.656, 18.979, 5.273, 34.597)) boolean isNotInBbox = isNotInBboxFilter.evaluate(feature) println isNotInBbox
false
Creating Literals
Expression expression = new Expression(3.56)
println expression
3.56
Expression expression = new Expression("Seattle")
println expression
Seattle
Expression expression = new Expression(3.56)
double number = expression.evaluate()
println number
3.56
Creating Properties
Property property = new Property("name")
println property
name
Field field = new Field("geom", "Polygon")
Property property = new Property(field)
println property
geom
Evaluating Properties
Feature feature = new Feature([
id: 1,
name: "Seattle",
geom: new Point(-122.3204, 47.6024)
], "city.1")
Property idProperty = new Property("id")
int id = idProperty.evaluate(feature)
println id
1
Property nameProperty = new Property("name")
String name = nameProperty.evaluate(feature)
println name
Seattle
Property geomProperty = new Property("geom")
Geometry geometry = geomProperty.evaluate(feature)
println geometry
POINT (-122.3204 47.6024)
Creating Functions
Function function = new Function("centroid(the_geom)")
println function
centroid([the_geom])
Function function = new Function("centroid", new Property("the_geom"))
println function
centroid([the_geom])
Function function = new Function("my_centroid", {g-> g.centroid}, new Property("the_geom"))
println function
my_centroid([the_geom])
Function function = new Function("my_centroid(the_geom)", {g-> g.centroid})
println function
my_centroid([the_geom])
List<String> functionNames = Function.getFunctionNames()
println "There are ${functionNames.size()} Functions:"
functionNames.sort().subList(0,10).each { String name ->
println name
}
There are 318 Functions: And Area Categorize Collection_Average Collection_Bounds Collection_Count Collection_Max Collection_Median Collection_Min Collection_Nearest
Evaluating Functions
Feature feature = new Feature([
id: 1,
name: "Seattle",
geom: new Point(-122.3204, 47.6024)
], "city.1")
Function bufferFunction = new Function("buffer(geom, 10)")
Geometry polygon = bufferFunction.evaluate(feature)

Function lowerCaseFunction = new Function("strToLowerCase(name)")
String lowerCaseName = lowerCaseFunction.evaluate(feature)
println lowerCaseName
seattle
Process Functions
Process Functions are a combination of Functions and Processes that can be used to create rendering transformations.
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
Process process = new Process("convexhull",
"Create a convexhull around the features",
[features: geoscript.layer.Cursor],
[result: geoscript.layer.Cursor],
{ inputs ->
def geoms = new GeometryCollection(inputs.features.collect{ f -> f.geom})
def output = new Layer()
output.add([geoms.convexHull])
[result: output]
}
)
Function function = new Function(process, new Function("parameter", new Expression("features")))
Symbolizer symbolizer = new Transform(function, Transform.RENDERING) + new Fill("aqua", 0.75) + new Stroke("navy", 0.5)
places.style = symbolizer

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
Process process = new Process("bounds",
"Create a bounds around the features",
[features: geoscript.layer.Cursor],
[result: geoscript.layer.Cursor],
{ inputs ->
def geoms = new GeometryCollection(inputs.features.collect{ f -> f.geom})
def output = new Layer()
output.add([geoms.bounds.geometry])
[result: output]
}
)
ProcessFunction processFunction = new ProcessFunction(process, new Function("parameter", new Expression("features")))
Symbolizer symbolizer = new Transform(processFunction, Transform.RENDERING) + new Fill("aqua", 0.75) + new Stroke("navy", 0.5)
places.style = symbolizer

Creating Colors
Color color = new Color("0,255,0")

Color color = new Color("silver")

Color color = new Color("#0000ff")

Color color = new Color([255,0,0])

Color color = new Color([r: 5, g: 35, b:45])

Color color = new Color("rgb(0,128,128)")

Color color = new Color([h: 0, s: 1.0, l: 0.5])

Color color = new Color("hsl(0,1,0.5)")

Color color = Color.getRandom()

Color color = Color.getRandomPastel()

Color color = new Color("lightblue")
Color darkerColor = color.darker()

Color color = new Color("purple")
Color brigtherColor = color.brighter()

Getting Color Formats
Color color = new Color("wheat")

String hex = color.hex
println hex
#f5deb3
List rgb = color.rgb
println rgb
[245, 222, 179]
List hsl = color.hsl
println hsl
[0.10858585256755147, 0.7674419030001307, 0.8313725489999999]
java.awt.Color awtColor = color.asColor()
println awtColor
java.awt.Color[r=245,g=222,b=179]
Displaying Colors
Color color = new Color("pink")
BufferedImage image = Color.drawToImage(
[color.brighter(), color, color.darker()],
"vertical",
40
)

List<Color> colors = Color.getPaletteColors("YlOrBr")
Color.draw(colors, "horizontal", 50)

Using Color Palettes
List<String> allPalettes = Color.getPaletteNames("all")
allPalettes.each { String name ->
println name
}
PiYG RdGy Purples Reds BuPu Set1 PuBuGn Grays PuOr Accents YlGn YlOrBr RdPu PuRd RdYlGn Paired Set3 Set2 GnBu YlGnBu RdYlBu RdBu BuGn BrBG PRGn Blues Greens OrRd Dark2 Oranges Spectral Pastel2 Pastel1 PuBu YlOrRd BlueToOrange GreenToOrange BlueToRed GreenToRedOrange Sunset Green YellowToRedHeatMap BlueToYellowToRedHeatMap DarkRedToYellowWhiteHeatMap LightPurpleToDarkPurpleHeatMap BoldLandUse MutedTerrain BoldLandUse MutedTerrain
List<String> divergingPalettes = Color.getPaletteNames("diverging")
divergingPalettes.each { String name ->
println name
}
PiYG RdGy PuOr RdYlGn RdYlBu RdBu BrBG PRGn Spectral BlueToOrange GreenToOrange BlueToRed GreenToRedOrange
List<String> sequentialPalettes = Color.getPaletteNames("sequential")
sequentialPalettes.each { String name ->
println name
}
Purples Reds BuPu PuBuGn Grays YlGn YlOrBr RdPu PuRd GnBu YlGnBu BuGn Blues Greens OrRd Oranges PuBu YlOrRd Sunset Green YellowToRedHeatMap BlueToYellowToRedHeatMap DarkRedToYellowWhiteHeatMap LightPurpleToDarkPurpleHeatMap BoldLandUse MutedTerrain
List<String> qualitativePalettes = Color.getPaletteNames("qualitative")
qualitativePalettes.each { String name ->
println name
}
Set1 Accents Paired Set3 Set2 Dark2 Pastel2 Pastel1 BoldLandUse MutedTerrain
List colors = Color.getPaletteColors("BuGn")

colors = Color.getPaletteColors("Purples", 4)

colors = Color.getPaletteColors("MutedTerrain")

colors = Color.getPaletteColors("BlueToYellowToRedHeatMap")

Color startColor = new Color("red")
Color endColor = new Color("green")
List<Color> colors = startColor.interpolate(endColor, 10)

Color startColor = new Color("wheat")
Color endColor = new Color("lightblue")
List<Color> colors = Color.interpolate(startColor, endColor, 8)

Creating Expressions from CQL
Expression expression = Expression.fromCQL("12")
println expression
12
Expression expression = Expression.fromCQL("'Washington'")
println expression
Washington
Property property = Expression.fromCQL("NAME")
println property
NAME
Function function = Expression.fromCQL("centroid(the_geom)")
println function
centroid([the_geom])
Create Expression from static imports
import static geoscript.filter.Expressions.*
Expression literal = expression(1.2)
Expression color = color("wheat")
Expression property = property("ID")
Expression function = function("max(10,22)")
Process Recipes
The Process classes are in the geoscript.process package.
Execute a built-in Process
Process process = new Process("vec:Bounds")
String name = process.name
println name
vec:Bounds
String title = process.title
println title
Bounds
String description = process.description
println description
Computes the bounding box of the input features.
String version = process.version
println version
1.0.0
Map parameters = process.parameters
println parameters
[features:class geoscript.layer.Cursor]
Map results = process.results
println results
[bounds:class geoscript.geom.Bounds]
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("places")
Map executeResults = process.execute([features: layer])
Bounds bounds = executeResults.bounds

Listing built-in Processes
List<String> processes = Process.processNames
processes.each { String name ->
println name
}
vec:Aggregate vec:BarnesSurface vec:Bounds vec:BufferFeatureCollection vec:Centroid vec:ClassifyByRange vec:Clip vec:CollectGeometries vec:Count vec:Feature vec:FeatureClassStats vec:Grid vec:GroupCandidateSelection vec:Heatmap vec:InclusionFeatureCollection vec:IntersectionFeatureCollection vec:LRSGeocode vec:LRSMeasure vec:LRSSegment vec:Nearest vec:PointBuffers vec:PointStacker vec:Query vec:RectangularClip vec:Reproject vec:Simplify vec:Snap vec:Transform vec:UnionFeatureCollection vec:Unique vec:VectorToRaster vec:VectorZonalStatistics geo:getX geo:getY geo:union geo:difference geo:isValid geo:reproject geo:intersects geo:area geo:numGeometries geo:intersection geo:symDifference geo:splitPolygon geo:isClosed geo:within geo:touches geo:convexHull geo:crosses geo:boundary geo:centroid geo:interiorPoint geo:getGeometryN geo:overlaps geo:isSimple geo:isWithinDistance geo:relate geo:densify geo:simplify geo:startPoint geo:numPoints geo:dimension geo:exteriorRing geo:numInteriorRing geo:geometryType geo:envelope geo:equalsExact geo:polygonize geo:endPoint geo:isRing geo:relatePattern geo:equalsExactTolerance geo:pointN geo:interiorRingN geo:length geo:buffer geo:isEmpty geo:contains geo:distance geo:disjoint polygonlabelprocess:PolyLabeller centerLine:centerLine skeltonize:centerLine ras:AddCoverages ras:Affine ras:AreaGrid ras:BandMerge ras:BandSelect ras:Contour ras:ConvolveCoverage ras:CoverageClassStats ras:CropCoverage ras:Jiffle ras:MultiplyCoverages ras:NormalizeCoverage ras:PolygonExtraction ras:RangeLookup ras:RasterAsPointCollection ras:RasterZonalStatistics ras:RasterZonalStatistics2 ras:ScaleCoverage ras:StyleCoverage ras:TransparencyFill geoscript:convexhull geoscript:bounds
Executing a new Process
Process process = new Process("convexhull",
"Create a convexhull around the features",
[features: geoscript.layer.Cursor],
[result: geoscript.layer.Cursor],
{ inputs ->
def geoms = new GeometryCollection(inputs.features.collect{f -> f.geom})
def output = new Layer()
output.add([geoms.convexHull])
[result: output]
}
)
String name = process.name
println name
geoscript:convexhull
String title = process.title
println title
convexhull
String description = process.description
println description
Create a convexhull around the features
String version = process.version
println version
1.0.0
Map parameters = process.parameters
println parameters
[features:class geoscript.layer.Cursor]
Map results = process.results
println results
[result:class geoscript.layer.Cursor]
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("places")
Map executeResults = process.execute([features: layer.cursor])
Cursor convexHullCursor = executeResults.result

Process Functions
Process Functions are a combination of Functions and Processes that can be used to create rendering transformations.
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
Process process = new Process("convexhull",
"Create a convexhull around the features",
[features: geoscript.layer.Cursor],
[result: geoscript.layer.Cursor],
{ inputs ->
def geoms = new GeometryCollection(inputs.features.collect{ f -> f.geom})
println geoms
def output = new Layer()
output.add([geoms.convexHull])
[result: output]
}
)
Function function = new Function(process, new Function("parameter", new Expression("features")))
Symbolizer symbolizer = new Transform(function, Transform.RENDERING) + new Fill("aqua", 0.75) + new Stroke("navy", 0.5)
places.style = symbolizer

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
Process process = new Process("bounds",
"Create a bounds around the features",
[features: geoscript.layer.Cursor],
[result: geoscript.layer.Cursor],
{ inputs ->
def geoms = new GeometryCollection(inputs.features.collect{ f -> f.geom})
def output = new Layer()
output.add([geoms.bounds.geometry])
[result: output]
}
)
ProcessFunction processFunction = new ProcessFunction(process, new Function("parameter", new Expression("features")))
Symbolizer symbolizer = new Transform(processFunction, Transform.RENDERING) + new Fill("aqua", 0.75) + new Stroke("navy", 0.5)
places.style = symbolizer

Render Recipes
The Render classes are in the geoscript.render package.
Creating Maps
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
File file = new File("map.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
map.render("map.png")

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
map.render(outputStream)
}

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
BufferedImage image = map.renderToImage()

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
BufferedImage image = new BufferedImage(800, 300, BufferedImage.TYPE_INT_ARGB)
Graphics2D graphics = image.graphics
map.render(graphics)
graphics.dispose()

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
map.display()

Map Properties
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Map map = new Map(
width: 600,
height: 600,
backgroundColor: "#a5bfdd",
layers: [countries],
type: "png",
proj: "EPSG:3857",
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
fixAspectRatio: false
)
File file = new File("map.png")
map.render(file)

int width = map.width
int height = map.height
println "Width and Height = ${width} x ${height}"
Width and Height = 600 x 600
Bounds bounds = map.bounds
println "Bounds = ${bounds}"
Bounds = (-2.0037508342789244E7,-1.997186888040857E7,2.0037508342789244E7,1.9971868880408563E7,EPSG:3857)
Projection projection = map.proj
println "Projeciton = ${projection}"
Projeciton = EPSG:3857
List<Layer> layers = map.layers
println "Layers:"
layers.each { Layer layer ->
println " ${layer.name}"
}
Layers: countries
String type = map.type
println "Type = ${type}"
Type = png
boolean shouldFixAspectRation = map.fixAspectRatio
println "Fix Aspect Ratio = ${shouldFixAspectRation}"
Fix Aspect Ratio = false
String backgroundColor = map.backgroundColor
println "Background Color = ${backgroundColor}"
Background Color = #a5bfdd
double scale = map.scaleDenominator
println "Scale = ${scale}"
Scale = 2.385417659855862E8
Advanced Properties
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 400,
height: 300,
layers: [ocean, countries],
bounds: new Bounds(-162.070313,9.968851,-35.507813,58.995311, "EPSG:4326")
)
map.setScaleComputation("accurate")
File accurateFile = new File("map_accurate.png")
map.render(accurateFile)
map.setScaleComputation("ogc")
File ogcFile = new File("map_ogc.png")
map.render(ogcFile)
Accurate

OGC

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 400,
height: 300,
layers: [ocean, countries],
bounds: new Bounds(-162.070313,9.968851,-35.507813,58.995311, "EPSG:4326")
)
map.setAdvancedProjectionHandling(true)
File trueFile = new File("map_advancedproj_true.png")
map.render(trueFile)
map.setAdvancedProjectionHandling(false)
File falseFile = new File("map_advancedproj_false.png")
map.render(falseFile)
Yes

No

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 200,
layers: [ocean, countries]
)
map.setContinuousMapWrapping(true)
File trueFile = new File("map_continuouswrapping_true.png")
map.render(trueFile)
map.setContinuousMapWrapping(false)
File falseFile = new File("map_continuouswrapping_false.png")
map.render(falseFile)
Yes

No

Projections
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Mercator")
Bounds bounds = new Bounds(-179.99, -85.0511, 179.99, 85.0511, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 400,
height: 400,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_mercator.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WGS84")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_wgs84.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("EqualEarth")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_equalearth.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Mollweide")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_mollweide.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Aitoff")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_aitoff.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("EckertIV")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_eckertIV.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WagnerIV")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_wagnerIV.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Robinson")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_robinson.png")
map.render(file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WinkelTripel")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_winkeltripel.png")
map.render(file)

Workspace workspace = new Directory('src/main/resources/shapefiles')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WorldVanderGrintenI")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
width: 600,
height: 350,
proj: proj,
bounds: bounds,
layers: [ocean, countries, graticules]
)
File file = new File("map_worldVanderGrintenIMap.png")
map.render(file)

Map Cubes
Workspace workspace = new Directory("src/main/resources/shapefiles")
Layer countries = workspace.get("countries")
Layer ocean = workspace.get("ocean")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
ocean.style = new Fill("#a5bfdd")
MapCube mapCube = new MapCube(
drawOutline: true,
drawTabs: true,
tabSize: 30,
title: "World Cube",
source: "Nartual Earth",
imageType: "png"
)
File file = new File("target/map_cube_file.png")
mapCube.render([ocean, countries], file)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
MapCube mapCube = new MapCube()
byte[] bytes = mapCube.render([ocean, countries])

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
MapCube mapCube = new MapCube()
File file = new File("target/map_cube_stream.png")
file.withOutputStream { OutputStream outputStream ->
mapCube.render([ocean, countries], outputStream)
}

Rendering Maps
Finding Renderers
List<Renderer> renderers = Renderers.list()
renderers.each { Renderer renderer ->
println renderer.class.simpleName
}
ASCII Base64 GeoTIFF GIF JPEG Pdf PNG Svg
Renderer renderer = Renderers.find("png")
println renderer.class.simpleName
PNG
Image
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Image png = new Image("png")
BufferedImage image = png.render(map)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Image jpeg = new Image("jpeg")
File file = new File("map.jpeg")
FileOutputStream out = new FileOutputStream(file)
jpeg.render(map, out)
out.close()

PNG
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
PNG png = new PNG()
BufferedImage image = png.render(map)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
PNG png = new PNG()
File file = new File("map.png")
FileOutputStream out = new FileOutputStream(file)
png.render(map, out)
out.close()

JPEG
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
JPEG jpeg = new JPEG()
BufferedImage image = jpeg.render(map)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
JPEG jpeg = new JPEG()
File file = new File("map.jpeg")
FileOutputStream out = new FileOutputStream(file)
jpeg.render(map, out)
out.close()

GIF
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
GIF gif = new GIF()
BufferedImage image = gif.render(map)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
GIF gif = new GIF()
File file = new File("map.gif")
gif.render(map, new FileOutputStream(file))

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer states = workspace.get("states")
states.style = new Fill("") + new Stroke("black", 1.0)
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries, states]
)
GIF gif = new GIF()
List images = ["Washington","Oregon","California"].collect { String state ->
map.bounds = states.getFeatures("name = '${state}'")[0].bounds
def image = gif.render(map)
image
}
File file = new File("states.gif")
gif.renderAnimated(images, file, 500, true)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer states = workspace.get("states")
states.style = new Fill("") + new Stroke("black", 1.0)
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries, states]
)
GIF gif = new GIF()
List images = ["Washington","Oregon","California"].collect { String state ->
map.bounds = states.getFeatures("name = '${state}'")[0].bounds
def image = gif.render(map)
image
}
File file = new File("states.gif")
byte[] bytes = gif.renderAnimated(images, 500, true)
file.bytes = bytes

GeoTIFF
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
GeoTIFF geotiff = new GeoTIFF()
BufferedImage image = geotiff.render(map)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
GeoTIFF geotiff = new GeoTIFF()
File file = new File("map.tif")
geotiff.render(map, new FileOutputStream(file))

ASCII
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
ASCII ascii = new ASCII(width: 60)
String asciiStr = ascii.render(map)
println asciiStr
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((^(^(.(?......((((((((((((((^((((((((((((((((( .....:.^(^..!?^^!^:..!(^...(((((^.^((((...........:.^(^..!?^ .....(:((.........((.(((.((((((:(.................(:((...... !..(^((((((((^.........((((((.(..............!..(^((((((((^. .(((((((((((((^.......((((((((...:^.^?...^..:.(((((((((((((^ ((.((((((((((((.....:((((((((^^(((:!^((^.....((.(((((((((((( ((((((((((((((((.!(((((((((((................((((((((((((((( (((((((((((((((((.((.(((((((....:....((..((((((((((((((((((( (((((((((((((((((((.((((((((^.(...(((((.((^((((((((((((((((( ((((((((((((((((((((.!:((((((((.....(((((((((((((((((((((((( ((.(((((((((((((((((.....(((((((...((((((((((((.(((((((((((( (^((((((((((((((((((.....(((((((.^.(((((((((((^((((((((((((( ....(((((((((((((((((?...(((((((.((^((((((((^....((((((((((( ....(((((((((((((((((...((((((((^.((((((((((.....((((((((((( (((.(((((((((((((((((..(((((((((((((((((((((((((.((((((((((( (((((((((((((((((((((.(((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((^(((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ....(((((((((((((((((?((((((((((((?....(.........((((((((((( .....(((((...........(((((........................(((((..... .......^....................................................
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
ASCII ascii = new ASCII(width: 60)
File file = new File("map.txt")
FileOutputStream out = new FileOutputStream(file)
ascii.render(map, out)
out.close()
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((^(^(.(?......((((((((((((((^((((((((((((((((( .....:.^(^..!?^^!^:..!(^...(((((^.^((((...........:.^(^..!?^ .....(:((.........((.(((.((((((:(.................(:((...... !..(^((((((((^.........((((((.(..............!..(^((((((((^. .(((((((((((((^.......((((((((...:^.^?...^..:.(((((((((((((^ ((.((((((((((((.....:((((((((^^(((:!^((^.....((.(((((((((((( ((((((((((((((((.!(((((((((((................((((((((((((((( (((((((((((((((((.((.(((((((....:....((..((((((((((((((((((( (((((((((((((((((((.((((((((^.(...(((((.((^((((((((((((((((( ((((((((((((((((((((.!:((((((((.....(((((((((((((((((((((((( ((.(((((((((((((((((.....(((((((...((((((((((((.(((((((((((( (^((((((((((((((((((.....(((((((.^.(((((((((((^((((((((((((( ....(((((((((((((((((?...(((((((.((^((((((((^....((((((((((( ....(((((((((((((((((...((((((((^.((((((((((.....((((((((((( (((.(((((((((((((((((..(((((((((((((((((((((((((.((((((((((( (((((((((((((((((((((.(((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((^(((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ....(((((((((((((((((?((((((((((((?....(.........((((((((((( .....(((((...........(((((........................(((((..... .......^....................................................
Base64
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Base64 base64 = new Base64()
String base64Str = base64.render(map)
println base64Str
image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAEsC...
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Base64 base64 = new Base64()
File file = new File("map.txt")
base64.render(map, new FileOutputStream(file))
iVBORw0KGgoAAAANSUhEUgAAAyAAAAEsCAYAAAA7Ldc6AACAAE...
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Pdf pdf = new Pdf()
com.lowagie.text.Document document = pdf.render(map)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Pdf pdf = new Pdf()
File file = new File("map.pdf")
pdf.render(map, new FileOutputStream(file))

SVG
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Svg svg = new Svg()
org.w3c.dom.Document document = svg.render(map)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Svg svg = new Svg()
File file = new File("map.svg")
FileOutputStream out = new FileOutputStream(file)
svg.render(map, out)
out.close()

Displaying Maps
Finding Displayers
List<Displayer> displayers = Displayers.list()
displayers.each { Displayer displayer ->
println displayer.class.simpleName
}
MapWindow Window
Displayer displayer = Displayers.find("window")
println displayer.class.simpleName
Window
Window
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
Window window = new Window()
window.display(map)

MapWindow
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
width: 800,
height: 300,
layers: [ocean, countries]
)
MapWindow window = new MapWindow()
window.display(map)

Drawing
The Draw class is an easy way to quickly render a Geometry, a List of Geometries, a Feature, or a Layer to an Image, a File, an OutputStream, or a GUI.
Drawing to a File or GUI
All of the draw methods take a single required parameter but can also take the following optional parameters:
-
style = A Style
-
bounds = The Bounds
-
size = The size of the canvas ([400,350])
-
out = The OutputStream, File, or File name. If null (which is the default) a GUI will be opened.
-
format = The format ("jpeg", "png", "gif")
-
proj = The Projection
File file = new File("geometry.png")
Geometry geometry = new Point(-122.376, 47.587).buffer(0.5)
Draw.draw(geometry,
style: new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5),
bounds: new Bounds(-122.876,47.087,-121.876,48.087),
size: [400,400],
format: "png",
proj: "EPSG:4326",
backgroundColor: "#a5bfdd",
out: file
)

Point point = new Point(-122.376, 47.587)
List geometries = [1.5, 1.0, 0.5].collect { double distance ->
point.buffer(distance)
}
File file = new File("geometries.png")
OutputStream outputStream = new FileOutputStream(file)
Draw.draw(geometries, out: outputStream, format: "png")
outputStream.flush()
outputStream.close()

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
Feature feature = layer.first(filter: "name='Washington'")
Draw.draw(feature, bounds: feature.bounds, out: "feature.png")

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
layer.style = new Fill("LightSteelBlue") + new Stroke("LightSlateGrey", 0.25)
Draw.draw(layer, bounds: layer.bounds)

File file = new File("earth.png")
Raster raster = new geoscript.layer.GeoTIFF(new File('src/main/resources/earth.tif')).read()
Draw.draw(raster, bounds: raster.bounds, size: [400,200], out: file)

Drawing to an Image
All of the drawToImage methods take a single required parameter but can also take the following optional parameters:
-
style = A Style
-
bounds = The Bounds
-
size = The size of the canvas ([400,350])
-
imageType = The format ("jpeg", "png", "gif")
-
proj = The Projection
Geometry geometry = new Point(-122.376, 47.587).buffer(0.5)
BufferedImage image = Draw.drawToImage(geometry,
style: new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5),
bounds: new Bounds(-122.876,47.087,-121.876,48.087),
size: [400,400],
imageType: "png",
proj: "EPSG:4326",
backgroundColor: "#a5bfdd"
)

Point point = new Point(-122.376, 47.587)
List geometries = [1.5, 1.0, 0.5].collect { double distance ->
point.buffer(distance)
}
BufferedImage image = Draw.drawToImage(geometries)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
Feature feature = layer.first(filter: "name='Washington'")
BufferedImage image = Draw.drawToImage(feature, bounds: feature.bounds)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
layer.style = new Fill("LightSteelBlue") + new Stroke("LightSlateGrey", 0.25)
BufferedImage image = Draw.drawToImage(layer, bounds: layer.bounds)

Raster raster = new geoscript.layer.GeoTIFF(new File('src/main/resources/earth.tif')).read()
BufferedImage image = Draw.drawToImage(raster, bounds: raster.bounds, size: [400,200])

Plotting
Plotting to a File or GUI
The Plot module can plot a Geometry, a list of Geometries, a Feature, or a Layer to a File, a File name, an OutputStream, or a simple GUI.
File file = new File("geometry.png")
Geometry geometry = new Point(-122.376, 47.587).buffer(0.5)
Plot.plot(geometry, out: file)

Point point = new Point(-122.376, 47.587)
List geometries = [1.5, 1.0, 0.5].collect { double distance ->
point.buffer(distance)
}
File file = new File("geometries.png")
OutputStream outputStream = new FileOutputStream(file)
Plot.plot(geometries, out: outputStream)
outputStream.flush()
outputStream.close()

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
Feature feature = layer.first(filter: "name='Washington'")
Plot.plot(feature, out: "feature.png")

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
Plot.plot(layer)

Plotting to an Image
The Plot module can plot a Geometry, a list of Geometries, a Feature, or a Layer to an image.
Geometry geometry = new Point(-122.376, 47.587).buffer(0.5)
BufferedImage image = Plot.plotToImage(geometry, size: [400,400],)

Point point = new Point(-122.376, 47.587)
List geometries = [1.5, 1.0, 0.5].collect { double distance ->
point.buffer(distance)
}
BufferedImage image = Plot.plotToImage(geometries)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
Feature feature = layer.first(filter: "name='Washington'")
BufferedImage image = Plot.plotToImage(feature, bounds: feature.bounds)

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("states")
BufferedImage image = Plot.plotToImage(layer, bounds: layer.bounds)

Reading Maps
The IO module can read Maps from JSON or XML documents.
Finding Map Readers
List<MapReader> readers = MapReaders.list()
readers.each { MapReader reader ->
println reader.name
}
xml json yaml
MapReader reader = MapReaders.find("json")
println reader.name
json
JSON
{
"width": 400,
"height": 400,
"type": "png",
"backgroundColor": "blue",
"fixAspectRatio": true,
"proj": "EPSG:4326",
"bounds": {
"minX": -135.911779,
"minY": 36.993573,
"maxX": -96.536779,
"maxY": 51.405899
},
"layers": [
{"layertype": "layer", "file": "shps/states.shp"}
]
}
-
width = The map width is optional and defaults to 600.
-
height = The map height is optional and defaults to 400.
-
type = The image type (png, jpeg, gif) is optional and defaults to png.
-
backgroundColor = The map background color is optional and transparent by default.
-
fixAspectRatio = Whether to fix the aspect ratio or not. It is optional and the default is true.
-
proj = The optional map projection. The default is determined by the layers or the bounds.
-
bounds = The optional map bounds. The default is the full extent of the layers.
-
layers = The only required property. A list of layer configurations.
-
layertype = The layer type is required. Values can be layer (vector), raster, or tile.
-
layername = The name of the layer is optional and defaults to first layer.
-
style = The layer style is optional but can be a SLD or CSS file.
-
String json = """{
"width": 400,
"height": 400,
"type": "png",
"backgroundColor": "blue",
"proj": "EPSG:4326",
"bounds": {
"minX": -135.911779,
"minY": 36.993573,
"maxX": -96.536779,
"maxY": 51.405899
},
"layers": [
{
"layertype": "layer",
"dbtype": "geopkg",
"database": "src/main/resources/data.gpkg",
"layername": "ocean",
"style": "src/main/resources/ocean.sld"
},
{
"layertype": "layer",
"dbtype": "geopkg",
"database": "src/main/resources/data.gpkg",
"layername": "countries",
"style": "src/main/resources/countries.sld"
},
{
"layertype": "layer",
"dbtype": "geopkg",
"database": "src/main/resources/data.gpkg",
"layername": "states",
"style": "src/main/resources/states.sld"
}
]
}
"""
MapReader mapReader = new JsonMapReader()
Map map = mapReader.read(json)
BufferedImage image = map.renderToImage()

XML
String xml = """<map>
<width>400</width>
<height>400</height>
<type>png</type>
<proj>EPSG:4326</proj>
<backgroundColor>blue</backgroundColor>
<fixAspectRatio>true</fixAspectRatio>
<layers>
<layer>
<layertype>layer</layertype>
<dbtype>geopkg</dbtype>
<database>src/main/resources/data.gpkg</database>
<layername>ocean</layername>
<style>src/main/resources/ocean.sld</style>
</layer>
<layer>
<layertype>layer</layertype>
<dbtype>geopkg</dbtype>
<database>src/main/resources/data.gpkg</database>
<layername>countries</layername>
<style>src/main/resources/countries.sld</style>
</layer>
<layer>
<layertype>layer</layertype>
<dbtype>geopkg</dbtype>
<database>src/main/resources/data.gpkg</database>
<layername>states</layername>
<style>src/main/resources/states.sld</style>
</layer>
</layers>
<bounds>
<minX>-135.911779</minX>
<minY>36.993573</minY>
<maxX>-96.536779</maxX>
<maxY>51.405899</maxY>
</bounds>
</map>
"""
MapReader mapReader = new XmlMapReader()
Map map = mapReader.read(xml)
BufferedImage image = map.renderToImage()

Style Recipes
Styles are found in the geoscript.style package.
Styles are made up Symbolizers and Composites. A Symbolizer is a particular style like Stroke or Fill. Symbolizers also have methods for controlling the drawing order (zindex), the min and max scale (range), and filtering (where).
Creating Basic Styles
Fill fill = new Fill("#6B8E23")

A Composite is simply two or more Symbolizers. So, a Composite would be a combination of a Stroke symbolizer (to style the boundary) and a Fill Symbolizer (to style the interior).
Composite composite = new Fill("#6B8E23") + new Stroke("black", 0.75)

Fill fill = new Fill("#6B8E23").title("States")
println "${fill.title}"
Composite composite = new Fill("#6B8E23") + new Stroke("black", 0.75).title("States with Outline")
println "${composite.title}"
States States with Outline


Symbolizer symbolizer = new Fill("#ffffcc").where("POP_EST < 4504128.33") +
new Fill("#41b6c4").where("POP_EST BETWEEN 4504128.33 AND 16639804.33") +
new Fill("#253494").where("POP_EST > 16639804.33")

Symbolizer symbolizer = new Stroke("black", 2.0).zindex(0) + new Stroke("white", 0.1).zindex(1)

Symbolizer symbolizer = (new Fill("white") + new Stroke("black", 0.1)) + new Label("name")
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")
.range(max: 16000000)


Creating Strokes
Stroke stroke = new Stroke("#1E90FF")

Stroke stroke = new Stroke("#1E90FF", 0.5)

Symbolizer stroke = new Stroke(color: "#333333", width: 5, cap: "round").zindex(0) +
new Stroke(color: "#6699FF", width: 3, cap: "round").zindex(1)

Stroke stroke = new Stroke("#1E90FF", 0.75, [5,5], "round", "bevel")

Symbolizer stroke = new Stroke("#1E90FF", 1) + new Hatch("vertline", new Stroke("#1E90FF", 0.5), 6).zindex(1)

Symbolizer stroke = new Stroke(width: 0, dash: [4, 4]).shape(new Shape("#1E90FF", 6, "circle").stroke("navy", 0.75))

Symbolizer stroke = new Stroke("#0000FF", 1, [10,10]).zindex(0) + new Stroke(null, 0, [[5,15],7.5])
.shape(new Shape(null, 5, "circle").stroke("#000033",1)).zindex(1)

Creating Fills
Fill fill = new Fill("#6B8E23")

Symbolizer symbolizer = new Fill("#6B8E23") + new Stroke("black", 0.1)

Fill fill = new Fill("#6B8E23", 0.35)

Fill fill = new Fill(color: "wheat", opacity: 0.75)

Fill fill = new Fill("green").icon('src/main/resources/trees.png', 'image/png')

Fill fill = new Fill("green").hatch("slash", new Stroke("green", 0.25), 8)

Symbolizer symbolizer = new Fill("white").hatch("circle", new Fill("black"), 2).random(
random: "free",
seed: 0,
symbolCount: 50,
tileSize: 50,
rotation: "none"
) + new Stroke("black", 0.25)

Function recodeFunction = new Function("Recode(region," +
"'West','#B0C4DE'," +
"'South','#00FFFF'," +
"'Northeast','#9ACD32'," +
"'Midwest','#6495ED')")
Symbolizer symbolizer = new Fill(recodeFunction) + new Stroke("#999999",0.1) + new Label("postal").point([0.5,0.5])

Creating Shapes
Shape shape = new Shape("navy")

Shape shape = new Shape("#9370DB", 8, "triangle", 0.75, 45)

Shape shape = new Shape(color: "#8B4513", size: 10, type: "star", opacity: 1.0, rotation: 0)

Symbolizer symbolizer = new Shape("white", 10).stroke("navy", 0.5)

Creating Icons
Symbolizer symbolizer = new Icon("src/main/resources/place.png", "image/png", 12)

Symbolizer symbolizer = new Icon(url: "src/main/resources/place.png", format: "image/png", size: 10)

Creating Labels
Symbolizer symbolizer = new Shape("blue", 6).stroke("navy", 0.5) + new Label("NAME").point(
[0.5,0.5], (1)
[0, 5.0], (2)
0 (3)
)
1 | anchor |
2 | displacement |
3 | rotation |

Symbolizer symbolizer = new Shape("blue", 6).stroke("navy", 0.5) + new Label("NAME").point(
[0.5,0.5],
[0, 5.0],
0
) + new Font(
"normal", (1)
"bold", (2)
12, (3)
"Arial" (4)
)
1 | style (normal, italic, oblique) |
2 | weight (normal, bold) |
3 | size (8,12,16,ect..) |
4 | family (serif, arial, verdana) |

Symbolizer symbolizer = new Shape("blue", 6).stroke("navy", 0.5) + new Label("NAME").point(
[0.5,0.5],
[0, 5.0],
0
).fill(new Fill("white")) + new Halo(new Fill("navy"), 2.5)

Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.1) + new Label("name")
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")

Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.1) + new Label(Expression.fromCQL("strToLowerCase(name)"))
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")

Expression expression = Expression.fromCQL("Concatenate(z, '/', x, '/', y)")
Symbolizer symbolizer = new Stroke("black", 1.0) + new Label(expression)

Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.1) + new Label("name")
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")
.strikethrough(true)

Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.1) + new Label("name")
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")
.wordSpacing(8)
.characterSpacing(5)

Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.1) + new Label("name")
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")
.underline(true)

Symbolizer symbolizer = new Stroke("blue", 0.75) + new Label("name")
.fill(new Fill("navy"))
.linear(follow: true, offset: 50, displacement: 200, repeat: 150).maxDisplacement(400).maxAngleDelta(90)
.halo(new Fill("white"), 2.5)
.font(new Font(size: 10, weight: "bold"))

Creating Transforms
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
Symbolizer symbolizer = new Transform("centroid(the_geom)") +
new Shape(color: "red", size: 10, type: "star")
countries.style = symbolizer

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
Process process = new Process("convexhull",
"Create a convexhull around the features",
[features: geoscript.layer.Cursor],
[result: geoscript.layer.Cursor],
{ inputs ->
def geoms = new GeometryCollection(inputs.features.collect{ f -> f.geom})
def output = new Layer()
output.add([geoms.convexHull])
[result: output]
}
)
Function function = new Function(process, new Function("parameter", new Expression("features")))
Symbolizer symbolizer = new Transform(function, Transform.RENDERING) + new Fill("aqua", 0.75) + new Stroke("navy", 0.5)
places.style = symbolizer

Creating Gradients
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
Gradient gradient = new Gradient(countries, "POP_EST", "quantile", 8, "Greens")
countries.style = gradient

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
Gradient gradient = new Gradient(countries, "POP_EST", "equalinterval", 3, "Reds")
countries.style = gradient

Gradient gradient = new Gradient(
new Property("POP2020"),
[0, 10000, 20000, 30000],
[
new Shape("white", 4).stroke("black", 0.5),
new Shape("#b0d2e8", 8).stroke("black", 0.5),
new Shape("#3e8ec4", 16).stroke("black", 0.5),
new Shape("#08306b", 24).stroke("black", 0.5)
],
5,
"linear"
)

Creating Unique Values
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
UniqueValues uniqueValues = new UniqueValues(countries, "NAME")
countries.style = uniqueValues

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
UniqueValues uniqueValues = new UniqueValues(countries, "NAME", {int index, String value -> Color.getRandom()})
countries.style = uniqueValues

Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
UniqueValues uniqueValues = new UniqueValues(countries, "NAME", "LightPurpleToDarkPurpleHeatMap")
countries.style = uniqueValues

Workspace workspace = new Directory("src/main/resources/mars")
Layer marsGeology = workspace.get("geo_units_oc_dd")
File uniqueValuesFile = new File("src/main/resources/mars/I1802ABC_geo_units_RGBlut.txt")
UniqueValuesReader styleReader = new UniqueValuesReader("UnitSymbol", "polygon")
Symbolizer symbolizer = styleReader.read(uniqueValuesFile)
Unit,R,G,B AHa,175,0,111 AHat,192,54,22 AHcf,150,70,72 AHh,109,13,60 AHpe,232,226,82 AHt,99,0,95 AHt3,233,94,94 Aa1,255,236,207 Aa2,145,73,76 Aa3,254,212,164 Aa4,212,109,19 Aa5,175,66,28

Creating Color Maps
Format format = new GeoTIFF(new File('src/main/resources/pc.tif'))
Raster raster = format.read()
ColorMap colorMap = new ColorMap([
[color: "#9fd182", quantity:25],
[color: "#3e7f3c", quantity:470],
[color: "#133912", quantity:920],
[color: "#08306b", quantity:1370],
[color: "#fffff5", quantity:1820],
])
raster.style = colorMap

Format format = new GeoTIFF(new File('src/main/resources/pc.tif'))
Raster raster = format.read()
ColorMap colorMap = new ColorMap([
[color: "#9fd182", quantity:25],
[color: "#3e7f3c", quantity:470],
[color: "#133912", quantity:920],
[color: "#08306b", quantity:1370],
[color: "#fffff5", quantity:1820],
]).opacity(0.25)
raster.style = colorMap

Format format = new GeoTIFF(new File('src/main/resources/pc.tif'))
Raster raster = format.read()
ColorMap colorMap = new ColorMap(
25, (1)
1820, (2)
"MutedTerrain", (3)
5 (4)
)
println colorMap
raster.style = colorMap
1 | min value |
2 | max value |
3 | color palette name |
4 | number of categories |

Format format = new GeoTIFF(new File('src/main/resources/pc.tif'))
Raster raster = format.read()
ColorMap colorMap = new ColorMap([
[color: "#9fd182", quantity:25],
[color: "#3e7f3c", quantity:470],
[color: "#133912", quantity:920],
[color: "#08306b", quantity:1370],
[color: "#fffff5", quantity:1820],
], "intervals", true)
raster.style = colorMap

Creating Channel Selection and Contrast Enhancement
Format format = new GeoTIFF(new File('src/main/resources/pc.tif'))
Raster raster = format.read()
Symbolizer symbolizer = new ChannelSelection()
.gray("1", new ContrastEnhancement("normalize"))
raster.style = symbolizer

Format format = new GeoTIFF(new File('src/main/resources/pc.tif'))
Raster raster = format.read()
Symbolizer symbolizer = new ChannelSelection()
.gray("1", new ContrastEnhancement("histogram", 0.65))
raster.style = symbolizer

Reading and Writing Styles
Style Readers and Writers are found in the geoscript.style.io package.
Finding Style Readers and Writers
List<Writer> writers = Writers.list()
writers.each { Writer writer ->
println writer.class.simpleName
}
SLDWriter ColorTableWriter YSLDWriter
Writer writer = Writers.find("sld")
println writer.class.simpleName
SLDWriter
List<Reader> readers = Readers.list()
readers.each { Reader reader ->
println reader.class.simpleName
}
SLDReader CSSReader ColorTableReader YSLDReader SimpleStyleReader
Reader reader = Readers.find("sld")
println reader.class.simpleName
SLDReader
SLD
GeoScript Groovy can read and write Style Layer Descriptor (SLD) documents.
Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.5)
SLDWriter writer = new SLDWriter()
String sld = writer.write(symbolizer)
println sld
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" xmlns="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> <sld:UserLayer> <sld:LayerFeatureConstraints> <sld:FeatureTypeConstraint/> </sld:LayerFeatureConstraints> <sld:UserStyle> <sld:Name>Default Styler</sld:Name> <sld:FeatureTypeStyle> <sld:Name>name</sld:Name> <sld:Rule> <sld:PolygonSymbolizer> <sld:Fill> <sld:CssParameter name="fill">#ffffff</sld:CssParameter> </sld:Fill> </sld:PolygonSymbolizer> <sld:LineSymbolizer> <sld:Stroke> <sld:CssParameter name="stroke-width">0.5</sld:CssParameter> </sld:Stroke> </sld:LineSymbolizer> </sld:Rule> </sld:FeatureTypeStyle> </sld:UserStyle> </sld:UserLayer> </sld:StyledLayerDescriptor>
Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.5) SLDWriter writer = new SLDWriter() String sld = writer.write(symbolizer, type: "NamedLayer") (1) println sld
1 | type can be UserLayer (default) or NamedLayer |
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" xmlns="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> <sld:NamedLayer> <sld:Name/> <sld:UserStyle> <sld:Name>Default Styler</sld:Name> <sld:FeatureTypeStyle> <sld:Name>name</sld:Name> <sld:Rule> <sld:PolygonSymbolizer> <sld:Fill> <sld:CssParameter name="fill">#ffffff</sld:CssParameter> </sld:Fill> </sld:PolygonSymbolizer> <sld:LineSymbolizer> <sld:Stroke> <sld:CssParameter name="stroke-width">0.5</sld:CssParameter> </sld:Stroke> </sld:LineSymbolizer> </sld:Rule> </sld:FeatureTypeStyle> </sld:UserStyle> </sld:NamedLayer> </sld:StyledLayerDescriptor>
String sld = """<?xml version="1.0" encoding="UTF-8"?>
<sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" version="1.0.0">
<sld:UserLayer>
<sld:LayerFeatureConstraints>
<sld:FeatureTypeConstraint/>
</sld:LayerFeatureConstraints>
<sld:UserStyle>
<sld:Name>Default Styler</sld:Name>
<sld:FeatureTypeStyle>
<sld:Name>name</sld:Name>
<sld:Rule>
<sld:PolygonSymbolizer>
<sld:Fill>
<sld:CssParameter name="fill">#ffffff</sld:CssParameter>
</sld:Fill>
</sld:PolygonSymbolizer>
<sld:LineSymbolizer>
<sld:Stroke>
<sld:CssParameter name="stroke">#000000</sld:CssParameter>
<sld:CssParameter name="stroke-width">0.5</sld:CssParameter>
</sld:Stroke>
</sld:LineSymbolizer>
</sld:Rule>
</sld:FeatureTypeStyle>
</sld:UserStyle>
</sld:UserLayer>
</sld:StyledLayerDescriptor>
"""
SLDReader reader = new SLDReader()
Style style = reader.read(sld)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = style

CSS
GeoScript Groovy can only read CSS documents.
String css = """
* {
fill: #eeeeee;
fill-opacity: 1.0;
stroke: #000000;
stroke-width: 1.2;
}
"""
CSSReader reader = new CSSReader()
Style style = reader.read(css)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = style

YSLD
GeoScript Groovy can read and write YAML Style Layer Descriptors (YSLD) documents.
Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.5)
YSLDWriter writer = new YSLDWriter()
String ysld = writer.write(symbolizer)
println ysld
name: Default Styler feature-styles: - name: name rules: - scale: [min, max] symbolizers: - polygon: fill-color: '#FFFFFF' - line: stroke-color: '#000000' stroke-width: 0.5
String ysld = """
name: Default Styler
feature-styles:
- name: name
rules:
- scale: [min, max]
symbolizers:
- polygon:
fill-color: '#FFFFFF'
- line:
stroke-color: '#000000'
stroke-width: 0.5
"""
YSLDReader reader = new YSLDReader()
Style style = reader.read(ysld)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = style

Simple Style Reader
A SimpleStyleReader that can easily create simple Styles using Maps or Strings.
-
Fill properties
-
fill (color)
-
fill-opacity (0-1)
-
-
Stroke properties
-
stroke (color)
-
stroke-width (double)
-
stroke-opacity (0-1)
-
-
Shape properties
-
shape (color)
-
shape-size (double)
-
shape-type (circle, square, triangle, star, cross, or x)
-
-
Label properties
-
label The name of the Field
-
label-color (black)
-
label-size (12)
-
label-style (normal, italic, oblique)
-
label-weight (normal, bold)
-
label-family (serif, Arial, Verdana)
-
label-halo-color (white)
-
label-halo-radius (5)
-
label-placement (point, line)
-
label-point-anchor (0.5,0.5)
-
label-point-displace (1,2)
-
label-point-rotate (45)
-
label-line-offset (2)
-
label-line-gap (3)
-
label-line-igap (4)
-
label-line-align (true, false)
-
label-line-follow (true, false)
-
label-line-group (true, false)
-
label-line-displacement (4)
-
label-line-repeat (true, false)
-
String str = "fill=#555555 fill-opacity=0.6 stroke=#555555 stroke-width=0.5"
SimpleStyleReader reader = new SimpleStyleReader()
Style style = reader.read(str)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = style

String str = "fill=white stroke=navy label=NAME label-size=10"
SimpleStyleReader reader = new SimpleStyleReader()
Style style = reader.read(str)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = style

String str = "shape-type=circle shape-size=8 shape=orange"
SimpleStyleReader reader = new SimpleStyleReader()
Style style = reader.read(str)
println style
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
places.style = style

String str = "stroke=blue stroke-width=0.75 label=name label-color=navy label-placement=line" +
" label-line-follow=true label-line-offset=2 label-line-displacement=5 label-line-repeat=10" +
" label-maxdisplacement=6 label-maxangledelta=90" +
" label-halo-color=white label-halo-radius=2.5 label-size=10 label-weight=bold"
SimpleStyleReader reader = new SimpleStyleReader()
Style style = reader.read(str)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer rivers = workspace.get("rivers")
rivers.style = style

String str = "shape=blue shape-size=6 stroke=navy stroke-width=navy stroke-width=0.5 label=NAME label-placement=point" +
" label-point-anchor=0.5,0.5 label-point-displace=0,6 label-point-rotate=0"
SimpleStyleReader reader = new SimpleStyleReader()
Style style = reader.read(str)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
places.style = style

Map map = [
'fill': '#555555',
'fill-opacity': 0.6,
'stroke': '#555555',
'stroke-width': 0.5
]
SimpleStyleReader reader = new SimpleStyleReader()
Style style = reader.read(map)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = style

Color Table
GeoScript Groovy can read and write color table strings and files. This format can be used with ColorMaps to style Rasters.
ColorMap colorMap = new ColorMap(25, 1820, "BoldLandUse", 5)
ColorTableWriter writer = new ColorTableWriter()
String str = writer.write(colorMap)
println str
25.0 178 156 195 473.75 79 142 187 922.5 143 146 56 1371.25 193 132 55 1820.0 181 214 177
Format format = new GeoTIFF(new File('src/main/resources/pc.tif'))
Raster raster = format.read()
ColorTableReader reader = new ColorTableReader()
ColorMap colorMap = reader.read("""25.0 178 156 195
473.75 79 142 187
922.5 143 146 56
1371.25 193 132 55
1820.0 181 214 177
""")
raster.style = colorMap

Style Repositories
Style Repositories can be found in the geoscript.style package.
Style Repositories are useful for storing styles for layers in a directories or databases.
Flat Directory
All files are stored in a single directory.
File directory = new File("target/styles")
directory.mkdir()
File file = new File("src/main/resources/states.sld")
StyleRepository styleRepository = new DirectoryStyleRepository(directory)
styleRepository.save("states", "states", file.text)
String sld = styleRepository.getDefaultForLayer("states")
println sld
List<Map<String, String>> stylesForLayer = styleRepository.getForLayer("states")
println stylesForLayer
List<Map<String, String>> allStyles = styleRepository.getAll()
println stylesForLayer
styleRepository.delete("states","states")
Nested Directory
Files are stories in nested directories based on the layer name.
File directory = new File("target/styles")
directory.mkdir()
File file = new File("src/main/resources/states.sld")
StyleRepository styleRepository = new NestedDirectoryStyleRepository(directory)
styleRepository.save("states", "states", file.text)
String sld = styleRepository.getDefaultForLayer("states")
println sld
List<Map<String, String>> stylesForLayer = styleRepository.getForLayer("states")
println stylesForLayer
List<Map<String, String>> allStyles = styleRepository.getAll()
println stylesForLayer
styleRepository.delete("states","states")
PostGIS Database
File databaseFile = new File("target/styles_h2.db")
File file = new File("src/main/resources/states.sld")
Sql sql = Sql.newInstance("jdbc:postgres://localhost/world", "user", "pass", "org.postgresql.Driver")
StyleRepository styleRepository = DatabaseStyleRepository.forPostgres(sql)
styleRepository.save("states", "states", file.text)
String sld = styleRepository.getDefaultForLayer("states")
println sld
List<Map<String, String>> stylesForLayer = styleRepository.getForLayer("states")
println stylesForLayer
List<Map<String, String>> allStyles = styleRepository.getAll()
println stylesForLayer
styleRepository.delete("states","states")
SQLite Database
File databaseFile = new File("target/styles_sqlite.db")
File file = new File("src/main/resources/states.sld")
Sql sql = Sql.newInstance("jdbc:sqlite:${databaseFile.absolutePath}", "org.sqlite.JDBC")
StyleRepository styleRepository = DatabaseStyleRepository.forSqlite(sql)
styleRepository.save("states", "states", file.text)
String sld = styleRepository.getDefaultForLayer("states")
println sld
List<Map<String, String>> stylesForLayer = styleRepository.getForLayer("states")
println stylesForLayer
List<Map<String, String>> allStyles = styleRepository.getAll()
println stylesForLayer
styleRepository.delete("states","states")
H2 Database
File databaseFile = new File("target/styles_h2.db")
File file = new File("src/main/resources/states.sld")
H2 h2 = new H2(databaseFile)
Sql sql = h2.sql
StyleRepository styleRepository = DatabaseStyleRepository.forH2(sql)
styleRepository.save("states", "states", file.text)
String sld = styleRepository.getDefaultForLayer("states")
println sld
List<Map<String, String>> stylesForLayer = styleRepository.getForLayer("states")
println stylesForLayer
List<Map<String, String>> allStyles = styleRepository.getAll()
println stylesForLayer
styleRepository.delete("states","states")
Workspace Recipes
The Workspace classes are in the geoscript.workspace package.
A Workspace is a collection of Layers. You can create, add, remove, and get Layers. There are many different kinds of Workspaces in GeoScript including Memory, PostGIS, Directory (for Shapefiles), GeoPackage, and many more.
Using Workspaces
Workspace workspace = new Workspace()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
println layer
cities
boolean hasCities = workspace.has("cities")
println hasCities
true
Layer citiesLayer = workspace.get('cities')
println citiesLayer
cities
Schema statesSchema = new Schema("states", [
new Field("geom", "Polygon", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer statesLayer = new Layer("states", statesSchema)
workspace.add(statesLayer)
println workspace.has("states")
true
List<String> names = workspace.names
names.each { String name ->
println name
}
SQLite MySQL (JNDI) GeoPackage PostGIS (JNDI) FlatGeobuf Geobuf H2 (JNDI) H2 Properties Directory of spatial files (shapefiles) Shapefile MBTiles with vector tiles MySQL PostGIS Web Feature Server (NG)
workspace.remove("cities")
println workspace.has('cities')
false
workspace.close()
Creating an in Memory Workspace
Workspace workspace = new Workspace()
Layer layer = workspace.create("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
println layer
workspace.remove(layer)
println workspace.has(layer.name)
cities false
Add Layer’s Features in Chunks
Workspace workspace = new Memory()
Layer layer = workspace.create("points", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer")
])
Bounds bounds = new Bounds(-180,-90, 180,90, "EPSG:4326")
Geometry.createRandomPoints(bounds.geometry, 500).geometries.eachWithIndex { Geometry geom, int i ->
layer.add([geom: geom, id: i])
}
println "Original Layer has ${layer.count} features."
Layer copyOfLayer = workspace.add(layer, "random points", 100)
println "Copied Layer has ${copyOfLayer.count} features."
Original Layer has 500 features. Copied Layer has 500 features.

Using a Directory Workspace
A Directory Workspace is a directory of Shapefiles.
Directory directory = new Directory("src/main/resources/data")
println directory.toString()
Directory[/home/runner/work/geoscript-groovy-cookbook/geoscript-groovy-cookbook/src/main/resources/data]
String format = directory.format
println format
Directory
File file = directory.file
println file
/home/runner/work/geoscript-groovy-cookbook/geoscript-groovy-cookbook/src/main/resources/data
List names = directory.names
names.each { String name ->
println name
}
states
Layer layer = directory.get("states")
int count = layer.count
println "Layer ${layer.name} has ${count} Features."
Layer states has 49 Features.
directory.close()
Investigating Workspaces
List<String> names = Workspace.getWorkspaceNames()
names.each { String name ->
println name
}
SQLite MySQL (JNDI) GeoPackage PostGIS (JNDI) FlatGeobuf Geobuf H2 (JNDI) H2 Properties Directory of spatial files (shapefiles) Shapefile MBTiles with vector tiles MySQL PostGIS Web Feature Server (NG)
List<Map> parameters = Workspace.getWorkspaceParameters("GeoPackage")
parameters.each { Map param ->
println "Parameter = ${param.key} Type = ${param.type} Required? ${param.required}"
}
Parameter = dbtype Type = java.lang.String Required? true Parameter = database Type = java.io.File Required? true Parameter = passwd Type = java.lang.String Required? false Parameter = namespace Type = java.lang.String Required? false Parameter = Expose primary keys Type = java.lang.Boolean Required? false Parameter = fetch size Type = java.lang.Integer Required? false Parameter = Batch insert size Type = java.lang.Integer Required? false Parameter = Primary key metadata table Type = java.lang.String Required? false Parameter = Session startup SQL Type = java.lang.String Required? false Parameter = Session close-up SQL Type = java.lang.String Required? false Parameter = Callback factory Type = java.lang.String Required? false Parameter = read_only Type = java.lang.Boolean Required? false Parameter = memory map size Type = java.lang.Integer Required? false
Creating Workspaces
Creating a Workspace from a connection string
You can create a Workspace from a connection string that contains paramters in key=value format with optional single quotes.
String connectionString = "url='states.shp' 'create spatial index'=true"
Workspace workspace = Workspace.getWorkspace(connectionString)
connectionString = "dbtype=geopkg database=layers.gpkg"
workspace = Workspace.getWorkspace(connectionString)
connectionString = "dbtype=h2 database=layers.db"
workspace = Workspace.getWorkspace(connectionString)
Workspace.withWorkspace("dbtype=geopkg database=src/main/resources/data.gpkg") { Workspace workspace ->
println workspace.format
println "----------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
}
GeoPackage --------- countries (177) graticules (27) ocean (2) places (243) rivers (13) states (51)
Creating a Workspace from a connection map
You can create a Workspace from a connection map that contains paramters.
Map params = [dbtype: 'h2', database: 'test.db']
Workspace workspace = Workspace.getWorkspace(params)
params = [
dbtype : 'postgis',
database: 'postgres',
host : 'localhost',
port : 5432,
user : 'postgres',
passwd : 'postgres'
]
workspace = Workspace.getWorkspace(params)
params = [file: 'layers.pbf', precision: 6, dimension:2]
workspace = Workspace.getWorkspace(params)
Workspace.withWorkspace([dbtype: 'geopkg', database: 'src/main/resources/data.gpkg']) { Workspace workspace ->
println workspace.format
println "----------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
}
GeoPackage --------- countries (177) graticules (27) ocean (2) places (243) rivers (13) states (51)
Creating Directory Workspaces
Workspace workspace = new Directory("src/main/resources/shapefiles")
println workspace.format
println "---------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
Directory --------- ocean (2) countries (177) graticules (27)
Workspace workspace = new Directory(new File("src/main/resources/shapefiles"))
println workspace.format
println "---------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
Directory --------- ocean (2) countries (177) graticules (27)
Directory directory = Directory.fromURL(
new URL("http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_countries.zip"),
new File("naturalearth")
)
println directory.format
println "---------"
directory.names.each { String name ->
println "${name} (${directory.get(name).count})"
}
Directory --------- ne_110m_admin_0_countries (177)
Creating GeoPackage Workspaces
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
println workspace.format
println "----------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
GeoPackage ---------- countries (177) graticules (27) ocean (2) places (243) rivers (13) states (51)
Workspace workspace = new GeoPackage(new File("src/main/resources/data.gpkg"))
println workspace.format
println "----------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
GeoPackage ---------- countries (177) graticules (27) ocean (2) places (243) rivers (13) states (51)
Creating H2 Workspaces
Workspace workspace = new H2(new File("src/main/resources/h2/data.db"))
println workspace.format
println "--"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
H2 -- LAYER_STYLES (0) countries (177) ocean (2) places (326) states (52)
H2 h2 = new H2(
"database", (1)
"localhost", (2)
"5421", (3)
"geo", (4)
"user", (5)
"password" (6)
)
1 | Database name |
2 | Host name |
3 | Port |
4 | User name |
5 | Password |
H2 h2 = new H2("database",
"host": "localhost",
"port": "5412",
"schema": "geo",
"user": "user",
"password": "secret"
)
Creating Geobuf Workspaces
Workspace workspace = new Geobuf(new File("src/main/resources/geobuf"))
println workspace.format
println "------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
Geobuf ------ places (326) ocean (2) countries (177)
Creating Flatgeobuf Workspaces
Workspace workspace = new FlatGeobuf(new File("src/main/resources/flatgeobuf"))
println workspace.format
println "------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
FlatGeobuf ------ places (326) countries (177) ocean (2)
Creating Property Workspaces
Workspace workspace = new Property(new File("src/main/resources/property"))
println workspace.format
println "--------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
Property ------ circles (10) places (10)
Creating SQLite Workspaces
Workspace workspace = new Sqlite(new File("src/main/resources/data.sqlite"))
println workspace.format
println "--------"
workspace.names.each { String name ->
println "${name} (${workspace.get(name).count})"
}
Sqlite ------ countries (177) ocean (2) places (326) rivers (460) states (52)
Creating PostGIS Workspaces
PostGIS postgis = new PostGIS(
"database", (1)
"localhost", (2)
"5432", (3)
"public", (4)
"user", (5)
"password" (6)
)
1 | Database name |
2 | Host name |
3 | Port |
4 | Schema |
5 | User name |
6 | Password |
PostGIS postgis = new PostGIS(
"database", (1)
"localhost", (2)
"5432", (3)
"public", (4)
"user", (5)
"password", (6)
true, (7)
true, (8)
"OWNER geo TABLESPACE points" (9)
)
1 | Database name |
2 | Host name |
3 | Port |
4 | Schema |
5 | User name |
6 | Password |
7 | Estimated Extent |
8 | Create Database |
9 | Create Database Params |
PostGIS postgis = new PostGIS("database",
"host": "localhost",
"port": "5432",
"schema": "public",
"user": "user",
"password": "secret",
"estimatedExtent": false,
"createDatabase": false,
"createDatabaseParams": "OWNER geo TABLESPACE points"
)
PostGIS.deleteDatabase(
"database", (1)
"localhost", (2)
"5432", (3)
"user", (4)
"password" (5)
)
1 | Database name |
2 | Host name |
3 | Port |
4 | User name |
5 | Password |
PostGIS.deleteDatabase("database",
"host": "localhost",
"port": "5432",
"user": "user",
"password": "secret"
)
Creating MySQL Workspaces
MySQL mysql = new MySQL(
"database", (1)
"localhost", (2)
"3306", (3)
"user", (4)
"password" (5)
)
1 | Database name |
2 | Host name |
3 | Port |
4 | User name |
5 | Password |
MySQL mysql = new MySQL("database",
"host": "localhost",
"port": "3306",
"user": "user",
"password": "secret"
)
Creating SpatiaLite Workspaces
The SpatiaLite Workspace requires GDAL and OGR to be installed with Java support.
SpatiaLite spatialite = new SpatiaLite("db.sqlite")
File directory = new File("databases")
File file = new File("db.sqlite")
SpatiaLite spatialite = new SpatiaLite(file)
Creating WFS Workspaces
WFS wfs = new WFS("http://localhost:8080/geoserver/ows?service=wfs&version=1.1.0&request=GetCapabilities")
Creating OGR Workspaces
The OGR Workspace requires GDAL and OGR to be installed with Java support.
On Ubuntu, you can install GDAL and OGR with the following commands:
sudo apt-get install gdal-bin
sudo apt-get install libgdal-java
boolean isAvailable = OGR.isAvailable()
Set<String> drivers = OGR.drivers
File file = new File("states.shp")
OGR ogr = new OGR("ESRI Shapefile", file.absolutePath)
File file = new File("states.sqlite")
OGR ogr = new OGR("SQLite", file.absolutePath)
File file = new File("states.json")
OGR ogr = new OGR("GeoJSON", file.absolutePath)
Database Workspace
SQL
Database workspace = new H2(new File("src/main/resources/h2/data.db"))
Sql sql = workspace.sql
int numberOfPlaces = sql.firstRow("SELECT COUNT(*) as count FROM \"places\"").get("count") as int
println "# of Places = ${numberOfPlaces}"
# of Places = 326
GroovyRowResult result = sql.firstRow("SELECT MIN(ELEVATION) as min_elev, MAX(ELEVATION) as max_elev, AVG(ELEVATION) as avg_elev FROM \"places\"")
println "Mininum Elevation = ${result.get('min_elev')}"
println "Maximum Elevation = ${result.get('max_elev')}"
println "Average Elevation = ${result.get('avg_elev')}"
Mininum Elevation = 0.0 Maximum Elevation = 2320.0 Average Elevation = 30.085889570552148
List<String> names = []
sql.eachRow "SELECT TOP 10 \"NAME\" FROM \"places\" ORDER BY \"NAME\" DESC ", {
names.add(it["NAME"])
}
names.each { String name ->
println name
}
Zürich Zibo Zhengzhou Zagreb Yerevan Yaounde Yamoussoukro Xian Wuhan Windhoek
Workspace memory = new Memory()
Layer layer = memory.create("places_polys", [new Field("buffer", "Polygon"), new Field("name", "String")])
sql.eachRow "SELECT ST_Buffer(\"the_geom\", 10) as buffer, \"NAME\" as name FROM \"places\"", {row ->
Geometry poly = Geometry.fromWKB(row.buffer as byte[])
layer.add([buffer: poly, name: row.NAME])
}

View
Database workspace = new H2(new File("src/main/resources/h2/data.db"))
Layer layer = workspace.createView(
"megacities", (1)
"SELECT * FROM \"places\" WHERE \"MEGACITY\" = '%mega%'", (2)
new Field("the_geom","Point","EPSG:4326"), (3)
params: [['mega', '1']] (4)
)
boolean hasLayer1 = workspace.has("megacities")
println "Does layer exist? ${hasLayer1}"
1 | The layer name |
2 | The SQL Statement |
3 | The Geometry Field |
4 | Query Parameters |
Does layer exist? true

workspace.deleteView("megacities")
boolean hasLayer2 = workspace.has("megacities")
println "Does layer exist? ${hasLayer2}"
Does layer exist? false
Index
Database workspace = new H2(new File("src/main/resources/h2/data.db"))
workspace.createIndex("places","name_idx","NAME",true)
workspace.createIndex("places","megacity_idx","MEGACITY",false)
workspace.createIndex("places","a3_idx", ["SOV_A3", "ADM0_A3"],false)
List<Map> indexes = workspace.getIndexes("places")
indexes.each { Map index ->
println "Index name = ${index.name}, unique = ${index.unique}, attributes = ${index.attributes}"
}
Index name = PRIMARY_KEY_C, unique = true, attributes = [fid] Index name = name_idx, unique = true, attributes = [NAME] Index name = a3_idx, unique = false, attributes = [SOV_A3, ADM0_A3] Index name = megacity_idx, unique = false, attributes = [MEGACITY]
workspace.deleteIndex("places", "name_idx")
workspace.deleteIndex("places", "megacity_idx")
workspace.deleteIndex("places", "a3_idx")
Layer Recipes
The Layer classes are in the geoscript.layer package.
A Layer is a collection of Features.
Getting a Layer’s Properties
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("countries")
String name = layer.name
println "Name: ${name}"
Name: countries
String format = layer.format
println "Format: ${format}"
Format: GeoPackage
int count = layer.count
println "# of Features: ${count}"
# of Features: 177
Projection proj = layer.proj
println "Projection: ${proj}"
Projection: EPSG:4326
Bounds bounds = layer.bounds
println "Bounds: ${bounds}"
Bounds: (-180.0,-90.0,180.00000000000006,83.64513000000001,EPSG:4326)
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("places")
Map<String,Double> minMax = layer.minmax("POP2050")
println "Minimum Population in 2050 = ${minMax.min}"
println "Maximum Population in 2050 = ${minMax.max}"
Minimum Population in 2050 = 0 Maximum Population in 2050 = 36400
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("places")
List<List<Double>> values = layer.histogram("POP2050", 10)
values.each { List<Double> value ->
println "${value[0]} - ${value[1]}"
}
0.0 - 3640.0 3640.0 - 7280.0 7280.0 - 10920.0 10920.0 - 14560.0 14560.0 - 18200.0 18200.0 - 21840.0 21840.0 - 25480.0 25480.0 - 29120.0 29120.0 - 32760.0 32760.0 - 36400.0
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("places")
List<Double> values = layer.interpolate(
"POP2050", (1)
10, (2)
"linear" (3)
)
values.each { Double value ->
println value
}
1 | Field Name |
2 | Number of classes |
3 | Algorithm |
0.0 3640.0 7280.0 10920.0 14560.0 18200.0 21840.0 25480.0 29120.0 32760.0 36400.0
values = layer.interpolate(
"POP2050", (1)
8, (2)
"exp" (3)
)
values.each { Double value ->
println value
}
1 | Field Name |
2 | Number of classes |
3 | Algorithm |
0.0 2.7165430207384107 12.81269202499939 50.33546414312058 189.79046097748173 708.0809561693237 2634.3298787896188 9793.31686835896 36399.99999999998
values = layer.interpolate(
"POP2050", (1)
12, (2)
"exp" (3)
)
values.each { Double value ->
println value
}
1 | Field Name |
2 | Number of classes |
3 | Algorithm |
0.0 1.3993454247861767 4.75685846744236 12.81269202499939 32.14141941416279 78.51771304229133 189.79046097748173 456.77221963916656 1097.3536807854464 2634.3298787896188 6322.06668747619 15170.221127213848 36399.99999999998
Getting a Layer’s Features
Each Feature
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
layer.eachFeature { Feature feature ->
println feature["name"]
}
Minnesota Montana North Dakota Hawaii Idaho Washington Arizona California Colorado Nevada ...
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
layer.eachFeature("name LIKE 'M%'") { Feature feature ->
println feature["name"]
}
Minnesota Montana Missouri Massachusetts Mississippi Maryland Maine Michigan
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
layer.eachFeature(sort: ["name"], start: 0, max: 5, fields: ["name"], filter: "name LIKE 'M%'") { Feature feature ->
println feature["name"]
}
Maine Maryland Massachusetts Michigan Minnesota
Parameters
-
filter: The Filter or Filter String to limit the Features. Defaults to null.
-
sort: A List of Lists that define the sort order [[Field or Field name, "ASC" or "DESC"],…]. Not all Layers support sorting!
-
max: The maximum number of Features to include
-
start: The index of the record to start the cursor at. Together with maxFeatures this simulates paging. Not all Layers support the start index and paging!
-
fields: A List of Fields or Field names to include. Used to select only a subset of Fields.
Read all Features
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
List<Feature> features = layer.features
println "# Features = ${features.size()}"
features.each { Feature feature ->
println feature["name"]
}
# Features = 51 Minnesota Montana North Dakota Hawaii Idaho Washington Arizona California Colorado Nevada ...
Collect values
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
List<String> names = layer.collectFromFeature { Feature f ->
f["name"]
}.sort()
println "# Names = ${names.size()}"
names.each { String name ->
println name
}
# Names = 51 Alabama Alaska Arizona Arkansas California Colorado Connecticut Delaware District of Columbia Florida ...
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
List<String> names = layer.collectFromFeature(
sort: ["name"],
start: 0,
max: 5,
fields: ["name"],
filter: "name LIKE 'M%'") { Feature f ->
f["name"]
}
println "# Names = ${names.size()}"
names.each { String name ->
println name
}
# Names = 5 Maine Maryland Massachusetts Michigan Minnesota
First
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
Feature feature = layer.first(filter: "name='Washington'")
println feature.get("name")
Washington

Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
Feature featureAsc = layer.first(sort: "name ASC")
println featureAsc.get("name")
Feature featureDesc = layer.first(sort: "name DESC")
println featureDesc.get("name")
Alabama Wyoming
Filter

Workspace workspace = new Directory("target")
Layer layer = workspace.get("countries")
Layer disputedLayer = layer.filter("TYPE='Indeterminate'")

Cursor
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
Cursor cursor = layer.cursor
cursor.each { Feature feature ->
println feature["name"]
}
Minnesota Montana North Dakota Hawaii Idaho Washington Arizona California Colorado Nevada ...
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
Cursor cursor = layer.getCursor(filter: "name LIKE 'M%'")
while(cursor.hasNext()) {
Feature feature = cursor.next()
println feature["name"]
}
Minnesota Montana Missouri Massachusetts Mississippi Maryland Maine Michigan
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
layer.getCursor(sort: ["name"], start: 0, max: 5, fields: ["name"], filter: "name LIKE 'M%'").each { Feature feature ->
println feature["name"]
}
Maine Maryland Massachusetts Michigan Minnesota
Parameters
-
filter: The Filter or Filter String to limit the Features. Defaults to null.
-
sort: A List of Lists that define the sort order [[Field or Field name, "ASC" or "DESC"],…]. Not all Layers support sorting!
-
max: The maximum number of Features to include
-
start: The index of the record to start the cursor at. Together with maxFeatures this simulates paging. Not all Layers support the start index and paging!
-
fields: A List of Fields or Field names to include. Used to select only a subset of Fields.
Adding, Updating, and Deleting
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("state", "String")
])
Layer layer = workspace.create(schema)
// Add a Feature with a Map
Map attributes = [
geom: new Point(-122.333056, 47.609722),
id: 1,
name: "Seattle",
state: "WA"
]
layer.add(attributes)
// Add a Feature with a List
List values = [
new Point(-122.459444, 47.241389),
2,
"Tacoma",
"WA"
]
layer.add(values)
// Add a Feature
Feature feature = schema.feature([
id:3,
name: "Fargo",
state: "ND",
geom: new Point(-96.789444, 46.877222)
])
layer.add(feature)
// Add Features from a List of Maps
List<Map> features = [
[
geom: new Point(-100.778889, 46.813333),
id:4,
name: "Bismarck",
state: "ND"
],
[
geom: new Point(-100.891111, 46.828889),
id: 5,
name: "Mandan",
state: "ND"
]
]
layer.add(features)
id | name | state |
---|---|---|
1 |
Seattle |
WA |
2 |
Tacoma |
WA |
3 |
Fargo |
ND |
4 |
Bismarck |
ND |
5 |
Mandan |
ND |

Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("state", "String")
])
Layer layer = workspace.create(schema)
List<Map> features = [
[
geom: new Point(-122.333056, 47.609722),
id: 1,
name: "Seattle",
state: "WA"
],
[
geom: new Point(-122.459444, 47.241389),
id: 2,
name: "Tacoma",
state: "WA"
],
[
id:3,
name: "Fargo",
state: "ND",
geom: new Point(-96.789444, 46.877222)
],
[
geom: new Point(-100.778889, 46.813333),
id:4,
name: "Bismarck",
state: "ND"
],
[
geom: new Point(-100.891111, 46.828889),
id: 5,
name: "Mandan",
state: "ND"
]
]
layer.add(features)
layer.update(layer.schema.state, "North Dakota", "state='ND'")
layer.update(layer.schema.state, "Washington", "state='WA'")
id | name | state |
---|---|---|
1 |
Seattle |
Washington |
2 |
Tacoma |
Washington |
3 |
Fargo |
North Dakota |
4 |
Bismarck |
North Dakota |
5 |
Mandan |
North Dakota |

Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("state", "String")
])
Layer layer = workspace.create(schema)
List<Map> features = [
[
geom: new Point(-122.333056, 47.609722),
id: 1,
name: "",
state: ""
],
[
geom: new Point(-122.459444, 47.241389),
id: 2,
name: "",
state: ""
]
]
layer.add(features)
List<Feature> layerFeatures = layer.features
layerFeatures[0].set("name", "Seattle")
layerFeatures[0].set("state", "WA")
layerFeatures[1].set("name", "Tacoma")
layerFeatures[1].set("state", "WA")
layer.update()
id | name | state |
---|---|---|
1 |
Seattle |
WA |
2 |
Tacoma |
WA |

Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("state", "String")
])
Layer layer = workspace.create(schema)
List<Map> features = [
[
geom: new Point(-122.333056, 47.609722),
id: 1,
name: "Seattle",
state: "WA"
],
[
geom: new Point(-122.459444, 47.241389),
id: 2,
name: "Tacoma",
state: "WA"
],
[
id:3,
name: "Fargo",
state: "ND",
geom: new Point(-96.789444, 46.877222)
],
[
geom: new Point(-100.778889, 46.813333),
id:4,
name: "Bismarck",
state: "ND"
],
[
geom: new Point(-100.891111, 46.828889),
id: 5,
name: "Mandan",
state: "ND"
]
]
layer.add(features)
layer.delete("state='ND'")
id | name | state |
---|---|---|
1 |
Seattle |
WA |
2 |
Tacoma |
WA |

Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer")
])
Layer layer = workspace.create(schema)
Bounds bounds = new Bounds(-180,-90,180,90, "EPSG:4326")
MultiPoint points = Geometry.createRandomPoints(bounds.geometry, 100)
geoscript.layer.Writer writer = layer.writer
try {
points.geometries.eachWithIndex { Point point, int index ->
Feature feature = writer.newFeature
feature['id'] = index
feature['geom'] = point
writer.add(feature)
}
} finally {
writer.close()
}

Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer")
])
Layer layer = workspace.create(schema)
Bounds bounds = new Bounds(-180,-90,180,90, "EPSG:4326")
MultiPoint points = Geometry.createRandomPoints(bounds.geometry, 100)
layer.withWriter { geoscript.layer.Writer writer ->
points.geometries.eachWithIndex { Point point, int index ->
Feature feature = writer.newFeature
feature['id'] = index
feature['geom'] = point
writer.add(feature)
}
}

Shapefiles
Shapefiles are a very commonly used format for storing spatial data. So, instead of creating a Directory Workspace and getting the Layer from the Workspace, you can use the Shapefile class.
Read
Shapefile countries = new Shapefile("src/main/resources/shapefiles/countries.shp")
println "# Features in Countries = ${countries.count}"
Shapefile ocean = new Shapefile(new File("src/main/resources/shapefiles/ocean.shp"))
println "# Features in Ocean = ${ocean.count}"
# Features in Countries = 177 # Features in Ocean = 2

Create
Directory workspace = new Directory("target")
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("state", "String")
])
Layer layer = workspace.create(schema)
List<Map> features = [
[
geom: new Point(-122.333056, 47.609722),
id: 1,
name: "Seattle",
state: "WA"
],
[
geom: new Point(-122.459444, 47.241389),
id: 2,
name: "Tacoma",
state: "WA"
],
[
id:3,
name: "Fargo",
state: "ND",
geom: new Point(-96.789444, 46.877222)
],
[
geom: new Point(-100.778889, 46.813333),
id:4,
name: "Bismarck",
state: "ND"
],
[
geom: new Point(-100.891111, 46.828889),
id: 5,
name: "Mandan",
state: "ND"
]
]
layer.add(features)
id | name | state |
---|---|---|
1 |
Seattle |
WA |
2 |
Tacoma |
WA |
3 |
Fargo |
ND |
4 |
Bismarck |
ND |
5 |
Mandan |
ND |

Property
GeoScript can store spatial data in a simple plain text format. With the Property class you can access a single property file directly.
Read
geoscript.layer.Property circles = new geoscript.layer.Property("src/main/resources/property/circles.properties")
println "# Features in circles = ${circles.count}"
geoscript.layer.Property places = new geoscript.layer.Property(new File("src/main/resources/property/places.properties"))
println "# Features in places = ${places.count}"
# Features in circles = 10 # Features in places = 10

Create
geoscript.workspace.Property workspace = new geoscript.workspace.Property("target")
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String"),
new Field("state", "String")
])
Layer layer = workspace.create(schema)
List<Map> features = [
[
geom: new Point(-122.333056, 47.609722),
id: 1,
name: "Seattle",
state: "WA"
],
[
geom: new Point(-122.459444, 47.241389),
id: 2,
name: "Tacoma",
state: "WA"
],
[
id:3,
name: "Fargo",
state: "ND",
geom: new Point(-96.789444, 46.877222)
],
[
geom: new Point(-100.778889, 46.813333),
id:4,
name: "Bismarck",
state: "ND"
],
[
geom: new Point(-100.891111, 46.828889),
id: 5,
name: "Mandan",
state: "ND"
]
]
layer.add(features)
id | name | state |
---|---|---|
1 |
Seattle |
WA |
2 |
Tacoma |
WA |
3 |
Fargo |
ND |
4 |
Bismarck |
ND |
5 |
Mandan |
ND |

Geoprocessing
Reproject
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer states = workspace.get("states")
println "States = ${states.proj}"
Projection projection = new Projection("EPSG:3857")
Workspace outputWorkspace = new Memory()
Layer statesInWebMercator = states.reproject(projection, outputWorkspace, "states_3857")
println "Reprojected States = ${statesInWebMercator.proj}"
States = EPSG:4326 Reprojected States = EPSG:3857

Buffer
Workspace workspace = new GeoPackage(new File("src/main/resources/data.gpkg"))
Layer places = workspace.get("places")
Layer buffer = places.buffer(5)

Dissolve
Workspace workspace = new Directory(new File("src/main/resources/data"))
Layer states = workspace.get("states")
Layer regions = states.dissolve(states.schema.get("SUB_REGION"))

Merge
Workspace workspace = new Directory(new File("src/main/resources/data"))
Layer states = workspace.get("states")
Feature washington = states.first(filter: "STATE_NAME='Washington'")
Feature oregon = states.first(filter: "STATE_NAME='Oregon'")
Schema waSchema = new Schema("washington",[
new Field("geom","Point","EPSG:4326"),
new Field("id","int")
])
Layer waLayer = new Memory().create(waSchema)
waLayer.withWriter { geoscript.layer.Writer writer ->
Geometry.createRandomPoints(washington.geom, 50).points.eachWithIndex { Point pt, int index ->
writer.add(waSchema.feature([geom: pt, id: index]))
}
}
println "The Washington Layer has ${waLayer.count} features"
Schema orSchema = new Schema("oregon",[
new Field("geom","Point","EPSG:4326"),
new Field("id","int")
])
Layer orLayer = new Memory().create(orSchema)
orLayer.withWriter { geoscript.layer.Writer writer ->
Geometry.createRandomPoints(oregon.geom, 50).points.eachWithIndex { Point pt, int index ->
writer.add(orSchema.feature([geom: pt, id: index]))
}
}
println "The Oregon Layer has ${orLayer.count} features"
Layer mergedLayer = orLayer.merge(waLayer)
println "The merged Layer has ${mergedLayer.count} features"
The Washington Layer has 50 features The Oregon Layer has 50 features The merged Layer has 100 features

Split
Workspace workspace = new GeoPackage(new File("src/main/resources/data.gpkg"))
Layer rivers = workspace.get("rivers")
Workspace outWorkspace = new Memory()
rivers.split(rivers.schema.get("scalerank"), outWorkspace)
outWorkspace.layers.each { Layer layer ->
println "${layer.name} has ${layer.count} features"
}
rivers_1 has 6 features rivers_2 has 7 features

Schema schema = new Schema("grid",[
new Field("geom","Polygon","EPSG:4326"),
new Field("col","int"),
new Field("row","int"),
new Field("row_col","string")
])
Workspace gridWorkspace = new Directory("target")
Layer gridLayer = gridWorkspace.create(schema)
new Bounds(-180,-90,180,90,"EPSG:4326").generateGrid(2, 3, "polygon", {cell, col, row ->
gridLayer.add([
"geom": cell,
"col": col,
"row": row,
"row_col": "${row} ${col}"
])
})
Workspace workspace = new GeoPackage(new File("src/main/resources/data.gpkg"))
Layer countries = workspace.get("countries")
Workspace outWorkspace = new Memory()
countries.split(gridLayer,gridLayer.schema.get("row_col"),outWorkspace)
outWorkspace.layers.each { Layer layer ->
println "${layer.name} has ${layer.count} features"
}
countries_1_1 has 6 features countries_1_2 has 6 features countries_2_1 has 44 features countries_2_2 has 75 features countries_3_1 has 13 features countries_3_2 has 69 features

Transform
Workspace workspace = new Directory(new File("src/main/resources/data"))
Layer states = workspace.get("states")
Layer centroids = states.transform("centroids", [
geom: "centroid(the_geom)",
name: "strToUpperCase(STATE_NAME)",
ratio: "FEMALE / MALE"
])
centroids.eachFeature(max: 5) {Feature f ->
println "${f.geom} ${f['name']} = ${f['ratio']}"
}
ILLINOIS = 1.0587396098110435 DISTRICT OF COLUMBIA = 1.1447503268897763 DELAWARE = 1.0626439771122835 WEST VIRGINIA = 1.0817203227723509 MARYLAND = 1.0621588832568312

Raster
Workspace workspace = new Memory()
Layer layer = workspace.create("earthquake", [
new Field("geom", "Polygon", "EPSG:4326"),
new Field("intensity", "Double")
])
Point point = new Point(-122.387695, 47.572357)
double distance = 5.0
List<Geometry> geometries = (1..5).collect { int i ->
point.buffer(i * distance)
}
geometries.eachWithIndex { Geometry geometry, int i ->
if (i > 0) {
Geometry previousGeometry = geometries.get(i - 1)
geometry = geometry.difference(previousGeometry)
}
layer.add([
geom: geometry,
intensity: (i + 1) * 20
])
}
Raster raster = layer.getRaster(
"intensity", (1)
[400,400], (2)
layer.bounds, (3)
"intensity" (4)
)
1 | Field for values |
2 | Raster size (width and height) |
3 | Raster bounds |
4 | Name |
Layer

Raster

Layer Algebra
GeoScript can do layer algebra. All of the examples below use Layer A (red) and Layer B (green).

Clip
Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Layer layerC = layerA.clip(layerB)

Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Workspace outWorkspace = new Directory("target")
Layer layerC = layerB.clip(layerA, outWorkspace: outWorkspace, outLayer: "ba_clip")

Erase
Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Layer layerC = layerA.erase(layerB)

Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Workspace outWorkspace = new Directory("target")
Layer layerC = layerB.erase(layerA, outWorkspace: outWorkspace, outLayer: "ba_erase")

Identity
Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Layer layerC = layerA.identity(layerB)

Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Workspace outWorkspace = new Directory("target")
Layer layerC = layerB.identity(layerA, outWorkspace: outWorkspace, outLayer: "ba_identity")

Intersection
Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Layer layerC = layerA.intersection(layerB)

Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Workspace outWorkspace = new Directory("target")
Layer layerC = layerB.intersection(layerA, outWorkspace: outWorkspace, outLayer: "ba_intersection")

Symmetric Difference
Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Layer layerC = layerA.symDifference(layerB)

Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Workspace outWorkspace = new Directory("target")
Layer layerC = layerB.symDifference(layerA, outWorkspace: outWorkspace, outLayer: "ba_symdifference")

Update
Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Layer layerC = layerA.update(layerB)

Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Workspace outWorkspace = new Directory("target")
Layer layerC = layerB.update(layerA, outWorkspace: outWorkspace, outLayer: "ba_update")

Union
Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Layer layerC = layerA.union(layerB)

Workspace workspace = new GeoPackage(new File("src/main/resources/layeralgebra.gpkg"))
Layer layerA = workspace.get("a")
Layer layerB = workspace.get("b")
Workspace outWorkspace = new Directory("target")
Layer layerC = layerB.union(layerA, outWorkspace: outWorkspace, outLayer: "ba_union")

Reading and Writing Layers
The Layer IO classes are in the geoscript.layer.io package.
Finding Layer Writer and Readers
List<Writer> writers = Writers.list()
writers.each { Writer writer ->
println writer.class.simpleName
}
CsvWriter GeobufWriter GeoJSONWriter GeoRSSWriter GmlWriter GpxWriter KmlWriter MvtWriter YamlWriter
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
Writer writer = Writers.find("csv")
String csv = writer.write(layer)
println csv
"geom:Point:EPSG:4326","id:Integer","name:String" "POINT (-122.3204 47.6024)","1","Seattle" "POINT (-122.48416 47.2619)","2","Tacoma"
List<Reader> readers = Readers.list()
readers.each { Reader reader ->
println reader.class.simpleName
}
CsvReader GeobufReader GeoJSONReader GeoRSSReader GmlReader GpxReader KmlReader MvtReader YamlReader
Reader reader = Readers.find("csv")
Layer layer = reader.read(""""geom:Point:EPSG:4326","id:Integer","name:String"
"POINT (-122.3204 47.6024)","1","Seattle"
"POINT (-122.48416 47.2619)","2","Tacoma"
""")
println "# features = ${layer.count}"
# features = 2
GeoJSON
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
String geojson = layer.toJSONString()
println geojson
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ -122.3204, 47.6024 ] }, "properties": { "id": 1, "name": "Seattle" }, "id": "fid--1c8a8332_18ba0aee183_-363c" }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ -122.4842, 47.2619 ] }, "properties": { "id": 2, "name": "Tacoma" }, "id": "fid--1c8a8332_18ba0aee183_-363a" } ] }
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
GeoJSONWriter writer = new GeoJSONWriter()
String geojson = writer.write(layer)
println geojson
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ -122.3204, 47.6024 ] }, "properties": { "id": 1, "name": "Seattle" }, "id": "fid--1c8a8332_18ba0aee183_-49fa" }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ -122.4842, 47.2619 ] }, "properties": { "id": 2, "name": "Tacoma" }, "id": "fid--1c8a8332_18ba0aee183_-49f8" } ] }
String geoJson = """
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-122.3204,
47.6024
]
},
"properties": {
"id": 1,
"name": "Seattle"
},
"id": "1"
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-122.681944,
45.52
]
},
"properties": {
"id": 2,
"name": "Portland"
},
"id": "2"
}
]
}
"""
GeoJSONReader reader = new GeoJSONReader()
Layer layer = reader.read(geoJson)

GeoBuf
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
String geobuf = layer.toGeobufString()
println geobuf
0a0269640a046e616d6510021806228b010a440a0c08001a089fd8d374c0ebb22d5a1f6669642d2d31633861383333325f31386261306165653138335f2d343639626a0218016a090a0753656174746c657204000001010a430a0c08001a08ffd6e77498a3892d5a1f6669642d2d31633861383333325f31386261306165653138335f2d343639396a0218026a080a065461636f6d61720400000101
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.681944, 45.52),
id: 2,
name: "Portland"
])
GeobufWriter writer = new GeobufWriter()
String geobuf = writer.write(layer)
println geobuf
0a0269640a046e616d6510021806228d010a440a0c08001a089fd8d374c0ebb22d5a1f6669642d2d31633861383333325f31386261306165653138335f2d343630336a0218016a090a0753656174746c657204000001010a450a0c08001a08afe9ff7480d2b42b5a1f6669642d2d31633861383333325f31386261306165653138335f2d343630316a0218026a0a0a08506f72746c616e64720400000101
String geobuf = "0a0269640a046e616d6510021806223f0a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c650a1e0a0c08001a08afe9ff7480d2b42b6a0218026a0a0a08506f72746c616e64"
GeobufReader reader = new GeobufReader()
Layer layer = reader.read(geobuf)

GML
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
String gml = layer.toGMLString()
println gml
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"> <gml:boundedBy xmlns:gml="http://www.opengis.net/gml"> <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coord> <gml:X> -122.48416 </gml:X> <gml:Y> 47.2619 </gml:Y> </gml:coord> <gml:coord> <gml:X> -122.3204 </gml:X> <gml:Y> 47.6024 </gml:Y> </gml:coord> </gml:Box> </gml:boundedBy> <gml:featureMember xmlns:gml="http://www.opengis.net/gml"> <gsf:cities xmlns:gsf="http://geoscript.org/feature" fid="fid--1c8a8332_18ba0aee183_-3ea5"> <gml:name> Seattle </gml:name> <gsf:geom> <gml:Point> <gml:coord> <gml:X> -122.3204 </gml:X> <gml:Y> 47.6024 </gml:Y> </gml:coord> </gml:Point> </gsf:geom> <gsf:id> 1 </gsf:id> </gsf:cities> </gml:featureMember> <gml:featureMember xmlns:gml="http://www.opengis.net/gml"> <gsf:cities xmlns:gsf="http://geoscript.org/feature" fid="fid--1c8a8332_18ba0aee183_-3ea3"> <gml:name> Tacoma </gml:name> <gsf:geom> <gml:Point> <gml:coord> <gml:X> -122.48416 </gml:X> <gml:Y> 47.2619 </gml:Y> </gml:coord> </gml:Point> </gsf:geom> <gsf:id> 2 </gsf:id> </gsf:cities> </gml:featureMember> </wfs:FeatureCollection>
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
GmlWriter writer = new GmlWriter()
String gml = writer.write(layer)
println gml
<wfs:FeatureCollection xmlns:gsf="http://geoscript.org/feature" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> <gml:boundedBy> <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coord> <gml:X>-122.48416</gml:X> <gml:Y>47.2619</gml:Y> </gml:coord> <gml:coord> <gml:X>-122.3204</gml:X> <gml:Y>47.6024</gml:Y> </gml:coord> </gml:Box> </gml:boundedBy> <gml:featureMember> <gsf:cities fid="fid--1c8a8332_18ba0aee183_-3ecb"> <gml:name>Seattle</gml:name> <gsf:geom> <gml:Point> <gml:coord> <gml:X>-122.3204</gml:X> <gml:Y>47.6024</gml:Y> </gml:coord> </gml:Point> </gsf:geom> <gsf:id>1</gsf:id> </gsf:cities> </gml:featureMember> <gml:featureMember> <gsf:cities fid="fid--1c8a8332_18ba0aee183_-3ec9"> <gml:name>Tacoma</gml:name> <gsf:geom> <gml:Point> <gml:coord> <gml:X>-122.48416</gml:X> <gml:Y>47.2619</gml:Y> </gml:coord> </gml:Point> </gsf:geom> <gsf:id>2</gsf:id> </gsf:cities> </gml:featureMember> </wfs:FeatureCollection>
String gml = """
<wfs:FeatureCollection xmlns:gsf="http://geoscript.org/feature" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc">
<gml:boundedBy>
<gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:coord>
<gml:X>-122.48416</gml:X>
<gml:Y>47.2619</gml:Y>
</gml:coord>
<gml:coord>
<gml:X>-122.3204</gml:X>
<gml:Y>47.6024</gml:Y>
</gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<gsf:cities fid="fid-a7cd555_1634fc34503_-7fff">
<gml:name>Seattle</gml:name>
<gsf:geom>
<gml:Point>
<gml:coord>
<gml:X>-122.3204</gml:X>
<gml:Y>47.6024</gml:Y>
</gml:coord>
</gml:Point>
</gsf:geom>
<gsf:id>1</gsf:id>
</gsf:cities>
</gml:featureMember>
<gml:featureMember>
<gsf:cities fid="fid-a7cd555_1634fc34503_-7ffd">
<gml:name>Portland</gml:name>
<gsf:geom>
<gml:Point>
<gml:coord>
<gml:X>-122.681944</gml:X>
<gml:Y>45.52</gml:Y>
</gml:coord>
</gml:Point>
</gsf:geom>
<gsf:id>2</gsf:id>
</gsf:cities>
</gml:featureMember>
</wfs:FeatureCollection>
"""
GmlReader reader = new GmlReader()
Layer layer = reader.read(gml)

KML
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
String kml = layer.toKMLString()
println kml
<kml:kml xmlns:kml="http://www.opengis.net/kml/2.2"> <kml:Document> <kml:Folder> <kml:name> cities </kml:name> <kml:Schema kml:name="cities" kml:id="cities"> <kml:SimpleField kml:name="id" kml:type="Integer"/> <kml:SimpleField kml:name="name" kml:type="String"/> </kml:Schema> <kml:Placemark> <kml:name> fid--1c8a8332_18ba0aee183_-3747 </kml:name> <kml:Style> <kml:IconStyle> <kml:color> ff0000ff </kml:color> </kml:IconStyle> </kml:Style> <kml:ExtendedData> <kml:SchemaData kml:schemaUrl="#cities"> <kml:SimpleData kml:name="id"> 1 </kml:SimpleData> <kml:SimpleData kml:name="name"> Seattle </kml:SimpleData> </kml:SchemaData> </kml:ExtendedData> <kml:Point> <kml:coordinates> -122.3204,47.6024 </kml:coordinates> </kml:Point> </kml:Placemark> <kml:Placemark> <kml:name> fid--1c8a8332_18ba0aee183_-3745 </kml:name> <kml:Style> <kml:IconStyle> <kml:color> ff0000ff </kml:color> </kml:IconStyle> </kml:Style> <kml:ExtendedData> <kml:SchemaData kml:schemaUrl="#cities"> <kml:SimpleData kml:name="id"> 2 </kml:SimpleData> <kml:SimpleData kml:name="name"> Tacoma </kml:SimpleData> </kml:SchemaData> </kml:ExtendedData> <kml:Point> <kml:coordinates> -122.48416,47.2619 </kml:coordinates> </kml:Point> </kml:Placemark> </kml:Folder> </kml:Document> </kml:kml>
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
KmlWriter writer = new KmlWriter()
String kml = writer.write(layer)
println kml
<kml:kml xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1"> <kml:Document> <kml:Placemark id="fid--1c8a8332_18ba0aee183_-3ec3"> <kml:name>Seattle</kml:name> <kml:Point> <kml:coordinates>-122.3204,47.6024</kml:coordinates> </kml:Point> </kml:Placemark> <kml:Placemark id="fid--1c8a8332_18ba0aee183_-3ec1"> <kml:name>Tacoma</kml:name> <kml:Point> <kml:coordinates>-122.48416,47.2619</kml:coordinates> </kml:Point> </kml:Placemark> </kml:Document> </kml:kml>
String kml = """
<kml:kml xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1">
<kml:Document>
<kml:Placemark id="fid-61215c1b_1634ca279f5_-7fff">
<kml:name>Seattle</kml:name>
<kml:Point>
<kml:coordinates>-122.3204,47.6024</kml:coordinates>
</kml:Point>
</kml:Placemark>
<kml:Placemark id="fid-61215c1b_1634ca279f5_-7ffd">
<kml:name>Portland</kml:name>
<kml:Point>
<kml:coordinates>-122.681944,45.52</kml:coordinates>
</kml:Point>
</kml:Placemark>
</kml:Document>
</kml:kml>
"""
KmlReader reader = new KmlReader()
Layer layer = reader.read(kml)

YAML
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
String yaml = layer.toYamlString()
println yaml
--- type: FeatureCollection features: - properties: id: 1 name: Seattle geometry: type: Point coordinates: - -122.3204 - 47.6024 - properties: id: 2 name: Tacoma geometry: type: Point coordinates: - -122.48416 - 47.2619
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
YamlWriter writer = new YamlWriter()
String yaml = writer.write(layer)
println yaml
--- type: FeatureCollection features: - properties: id: 1 name: Seattle geometry: type: Point coordinates: - -122.3204 - 47.6024 - properties: id: 2 name: Tacoma geometry: type: Point coordinates: - -122.48416 - 47.2619
String yaml = """---
type: "FeatureCollection"
features:
- properties:
id: 1
name: "Seattle"
geometry:
type: "Point"
coordinates:
- -122.3204
- 47.6024
- properties:
id: 2
name: "Tacoma"
geometry:
type: "Point"
coordinates:
- -122.48416
- 47.2619
"""
YamlReader reader = new YamlReader()
Layer layer = reader.read(yaml)

CSV
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
CsvWriter writer = new CsvWriter()
String csv = writer.write(layer)
println csv
"geom:Point:EPSG:4326","id:Integer","name:String" "POINT (-122.3204 47.6024)","1","Seattle" "POINT (-122.48416 47.2619)","2","Tacoma"
String csv = """"geom:Point:EPSG:4326","id:Integer","name:String"
"POINT (-122.3204 47.6024)","1","Seattle"
"POINT (-122.681944 45.52)","2","Portland"
"""
CsvReader reader = new CsvReader()
Layer layer = reader.read(csv)

GeoRSS
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
GeoRSSWriter writer = new GeoRSSWriter()
String georss = writer.write(layer)
println georss
<?xml version="1.0" encoding="UTF-8"?><feed xmlns:georss="http://www.georss.org/georss" xmlns="http://www.w3.org/2005/Atom"> <title>cities</title> <subtitle>cities geom: Point(EPSG:4326), id: Integer, name: String</subtitle> <link>http://geoscript.org/feature</link> <entry> <title>fid--1c8a8332_18ba0aee183_-45ff</title> <summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary> <updated>Sun Nov 05 18:12:40 UTC 2023</updated> <georss:point>47.6024 -122.3204</georss:point> </entry> <entry> <title>fid--1c8a8332_18ba0aee183_-45fd</title> <summary>[geom:POINT (-122.48416 47.2619), id:2, name:Tacoma]</summary> <updated>Sun Nov 05 18:12:40 UTC 2023</updated> <georss:point>47.2619 -122.48416</georss:point> </entry> </feed>
String georss = """<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:georss="http://www.georss.org/georss" xmlns="http://www.w3.org/2005/Atom">
<title>cities</title>
<subtitle>cities geom: Point(EPSG:4326), id: Integer, name: String</subtitle>
<link>http://geoscript.org/feature</link>
<entry>
<title>Seattle</title>
<summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary>
<updated>Fri May 11 15:23:05 PDT 2018</updated>
<georss:point>47.6024 -122.3204</georss:point>
</entry>
<entry>
<title>Portland</title>
<summary>[geom:POINT (-122.681944 45.52), id:2, name:Portland]</summary>
<updated>Fri May 11 15:23:05 PDT 2018</updated>
<georss:point>45.52 -122.681944</georss:point>
</entry>
</feed>
"""
GeoRSSReader reader = new GeoRSSReader()
Layer layer = reader.read(georss)

GPX
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
GpxWriter writer = new GpxWriter()
String gpx = writer.write(layer)
println gpx
<?xml version="1.0" encoding="UTF-8"?><gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" creator="geoscript"> <wpt lat="47.6024" lon="-122.3204"> <name>fid--1c8a8332_18ba0aee183_-3ec7</name> </wpt> <wpt lat="47.2619" lon="-122.48416"> <name>fid--1c8a8332_18ba0aee183_-3ec5</name> </wpt> </gpx>
String gpx = """<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" creator="geoscript">
<wpt lat="47.6024" lon="-122.3204">
<name>Seattle</name>
</wpt>
<wpt lat="45.52" lon="-122.681944">
<name>Portland</name>
</wpt>
</gpx>
"""
GpxReader reader = new GpxReader()
Layer layer = reader.read(gpx)

MVT
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
MvtWriter writer = new MvtWriter()
String mvt = writer.write(layer.reproject(new Projection("EPSG:3857")))
println mvt
iU1WVAAAAGF4nGNgYGBiYGAQBWIGxoOZPw5M6bBa6xjOnRDd8rIcKCZZrZSZomRlqKOUl5ibqmSlFJyaWFKSk6pUi9CVxbjcy9Mh0zHsygrWwt2vgGISEF1GcF0hicn5uYlKtQBZLx7y
String mvt = "iU1WVAAAAGF4nGNgYGBiYGAQBWIGxoOZPw5M6bBa6xjOnRDd8rIcKCZZrZSZomRlqKOUl5ibqmSlFJyaWFKSk6pUi9CVxbjcy9Mh0zHsygrWwt2vgGISEF1GcF0hicn5uYlKtQBZLx7y="
MvtReader reader = new MvtReader()
Layer layer = reader.read(mvt)

PBF
Workspace workspace = new Memory()
Schema schema = new Schema("cities", [
new Field("geom", "Point", "EPSG:4326"),
new Field("id", "Integer"),
new Field("name", "String")
])
Layer layer = workspace.create(schema)
layer.add([
geom: new Point(-122.3204, 47.6024),
id: 1,
name: "Seattle"
])
layer.add([
geom: new Point(-122.48416, 47.2619),
id: 2,
name: "Tacoma"
])
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid(origin: Pyramid.Origin.TOP_LEFT)
Tile tile = new Tile(4,2,5)
Bounds bounds = pyramid.bounds(tile)
byte[] bytes = Pbf.write([layer], bounds)
println bytes.encodeBase64()
GlYKBmNpdGllcxIPEgQAAAEBGAEiBQmGJNIlEg8SBAACAQMYASIFCcojiicaAmlkGgRuYW1lIgIwAiIJCgdTZWF0dGxlIgIwBCIICgZUYWNvbWEogCB4Ag==
byte[] bytes = "GlYKBmNpdGllcxIPEgQAAAEBGAEiBQmGJNIlEg8SBAACAQMYASIFCcojiicaAmlkGgRuYW1lIgIwAiIJCgdTZWF0dGxlIgIwBCIICgZUYWNvbWEogCB4Ag".decodeBase64()
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid(origin: Pyramid.Origin.TOP_LEFT)
Tile tile = new Tile(4,2,5)
Bounds bounds = pyramid.bounds(tile)
List<Layer> layers = Pbf.read(bytes, bounds)

Graticules
Square
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
double length = 20
double spacing = 5
Layer layer = Graticule.createSquares(bounds, length, spacing)

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
double length = 30
double spacing = -1
Workspace workspace = new Directory("target")
Layer layer = Graticule.createSquares(bounds, length, spacing, workspace: workspace, layer: "squares")

Hexagon
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
double length = 20
double spacing = 5
String orientation = "flat"
Layer layer = Graticule.createHexagons(bounds, length, spacing, orientation)

Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
double length = 10
double spacing = 5
String orientation = "angled"
Layer layer = Graticule.createHexagons(bounds, length, spacing, orientation)

Layer states = new Shapefile("src/main/resources/data/states.shp")
Feature feature = states.first(filter: "STATE_NAME = 'Washington'")
Layer layer = Graticule.createHexagons(feature.bounds.expandBy(1.0), 0.2, -1.0, "flat", createFeature: { GridElement e ->
new Point(e.center.x, e.center.y).buffer(0.2).intersects(feature.geom)
})

Layer states = new Shapefile("src/main/resources/data/states.shp")
Schema schema = new Schema("hexagon", [
new Field("geom", "Polygon"),
new Field("color", "java.awt.Color")
])
Bounds b = states.bounds.expandBy(1)
Layer layer = Graticule.createHexagons(b, 2.0, -1.0, "flat", schema: schema, setAttributes: { GridElement e, Map attributes ->
attributes["color"] = Color.randomPastel.asColor()
})
layer.style = new Fill(new Property("color"), 0.5)

Line
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Layer layer = Graticule.createLines(bounds, [
[orientation: 'vertical', level: 2, spacing: 20],
[orientation: 'vertical', level: 1, spacing: 10 ],
[orientation: 'horizontal', level: 2, spacing: 20],
[orientation: 'horizontal', level: 1, spacing: 10 ]
], 2.0)

Rectangle
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
double width = 20
double height = 10
Layer layer = Graticule.createRectangles(bounds, width, height, -1)

Oval
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
double length = 20
Layer layer = Graticule.createOvals(bounds, length)

Layer states = new Shapefile("src/main/resources/data/states.shp")
Feature feature = states.first(filter: "STATE_NAME = 'Washington'")
Layer layer = Graticule.createOvals(feature.bounds.expandBy(1.0), 0.4, createFeature: { GridElement e ->
new Point(e.center.x, e.center.y).buffer(0.2).intersects(feature.geom)
})

Format Recipes
The Format classes are in the geoscript.layer package.
A Format is a collection of Rasters.
Get a Format
Get a Format from a File
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
println format.name
GeoTIFF
Get Names
Get names of the Rasters in a Format. Some Formats can contain more than one Raster.
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
List<String> names = format.names
names.each { String name ->
println name
}
earth
Read a Raster
Read a Raster from a File
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")

Write a Raster
Write a Raster to a File
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
File outFile = new File("target/earth.png")
Format outFormat = Format.getFormat(outFile)
outFormat.write(raster)
Raster outRaster = outFormat.read("earth")

Check for a Raster
Check to see if the Format has a Raster
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
boolean hasEarth = format.has("earth")
println "Has raster named earth? ${hasEarth}"
boolean hasWorld = format.has("world")
println "Has raster named world? ${hasWorld}"
Has raster named earth? true Has raster named world? false
GeoTIFF
Read
Read a GeoTIFF Raster from a File
File file = new File("src/main/resources/earth.tif")
GeoTIFF geotiff = new GeoTIFF(file)
Raster raster = geotiff.read("earth")

Write
Write a GeoTIFF Raster to an ArcGrid Raster
File file = new File("src/main/resources/earth.tif")
GeoTIFF geotiff = new GeoTIFF(file)
Raster raster = geotiff.read("earth")
File arcGridFile = new File("target/earth.asc")
ArcGrid arcGrid = new ArcGrid(arcGridFile)
arcGrid.write(raster)
Raster arcGridRaster = arcGrid.read("earth")

ArcGrid
Read
Read an ArcGrid Raster from a File
File file = new File("src/main/resources/raster.asc")
ArcGrid arcGrid = new ArcGrid(file)
Raster raster = arcGrid.read("raster")
Read a Grass ArcGrid Raster from a File
File file = new File("src/main/resources/grass.arx")
ArcGrid arcGrid = new ArcGrid(file)
Raster raster = arcGrid.read("grass")
Raster Recipes
The Raster classes are in the geoscript.layer package.
Raster Properties
Read a Raster from a File
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")

Get the Raster’s Bounds.
Bounds bounds = raster.bounds
println "Bounds: ${bounds}"
Bounds: (-179.99999999999997,-89.99999999998205,179.99999999996405,90.0,EPSG:4326)
Get the Raster’s Projection.
Projection projection = raster.proj
println "Projection: ${projection}"
Projection: EPSG:4326
Get the Raster’s Size.
List size = raster.size
println "Size: ${size[0]}x${size[1]}"
Size: 800x400
Get the Raster’s number of columns and rows.
int cols = raster.cols
int rows = raster.rows
println "Columns: ${cols} Rows: ${rows}"
Columns: 800 Rows: 400
Get the Raster’s Bands.
List<Band> bands = raster.bands
println "Bands:"
bands.each { Band band ->
println " ${band}"
}
Band: RED_BAND GREEN_BAND BLUE_BAND
Get the Raster’s block size.
List blockSize = raster.blockSize
println "Block size: ${blockSize[0]}x${blockSize[1]}"
Block size: 800x8
Get the Raster’s pixel size.
List pixelSize = raster.pixelSize
println "Pixel size: ${pixelSize[0]}x${pixelSize[1]}"
Pixel size: 0.44999999999995505x0.4499999999999551
Get more information about a Raster’s Bounds.
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
List<Band> bands = raster.bands
bands.each { Band band ->
println "${band}"
println " Min = ${band.min}"
println " Max = ${band.max}"
println " No Data = ${band.noData}"
println " Is No Data = ${band.isNoData(12.45)}"
println " Unit = ${band.unit}"
println " Scale = ${band.scale}"
println " Offset = ${band.offset}"
println " Type = ${band.type}"
}
RED_BAND Min = 0.0 Max = 255.0 No Data = [0.0] Is No Data = false Unit = null Scale = 1.0 Offset = 0.0 Type = byte GREEN_BAND Min = 0.0 Max = 255.0 No Data = [0.0] Is No Data = false Unit = null Scale = 1.0 Offset = 0.0 Type = byte BLUE_BAND Min = 0.0 Max = 255.0 No Data = [0.0] Is No Data = false Unit = null Scale = 1.0 Offset = 0.0 Type = byte
Get the minimum and maximum values from a Raster for a band
double minValue = raster.getMinValue(0)
double maxValue = raster.getMaxValue(0)
println "Min values: ${minValue} Max values: ${maxValue}"
Min values: 56.0 Max values: 255.0
Get the minimum and maximum values from a Raster for each band
Map extrema = raster.extrema
println "Min values: ${extrema.min} Max values: ${extrema.max}"
Min value: [56.0, 84.0, 91.0] Max value: [255.0, 255.0, 255.0]
Get a Point at the given pixel location.
Point point = raster.getPoint(7,9)
println "Geographic location at pixel 7,9 is ${point}"
Geographic location at pixel 7,9 is POINT (-176.625 85.7249984741211)
Get a Pixel location at the given Point.
List pixel = raster.getPixel(new Point(-176.625, 85.72499))
println "Pixel coordinates at POINT (-176.625 85.7249984741211) is ${pixel[0]}, ${pixel[1]}"
Pixel coordinates at POINT (-176.625 85.7249984741211) is 7.0, 9.0
Determine whether the Raster covers the given Point.
boolean containsPoint = raster.contains(new Point(-180, -90))
println "Does raster cover point? ${containsPoint}"
Does raster cover point? true
Determine whether the Raster covers the given Pixel.
boolean containsPixel = raster.contains(500,600)
println "Does raster cover pixel? ${containsPixel}"
Does raster cover pixel? false
Get a RenderedImage from the Raster
RenderedImage image = raster.image

Dispose of the Raster when you are done
raster.dispose()
Raster Bands
Create a Band
Band band = new Band(
"red", (1)
0, (2)
255 (3)
)
println "Band = ${band.toString()} Min = ${band.min} Max = ${band.max}"
1 | Description |
2 | Minimum value |
3 | Maximum value |
Band = red Min = 0.0 Max = 255.0
Create a Band with a no data value
Band band = new Band(
"red", (1)
0, (2)
255, (3)
255 (4)
)
println "Band = ${band.toString()} Min = ${band.min} Max = ${band.max} No Data = ${band.noData[0]}"
1 | Description |
2 | Minimum value |
3 | Maximum value |
4 | No data value |
Band = red Min = 0.0 Max = 255.0 No Data = 255.0
Create a new Raster from Bands and set values to a random color.
Raster raster = new Raster(
new Bounds(-180,-90,180,90,"EPSG:4326"),
400,300,
[
new Band("red", 0, 255, 256),
new Band("green", 0, 255, 256),
new Band("blue", 0, 255, 256)
]
)
// Set values of each pixel
raster.eachCell { double value, double x, double y ->
Color color = Color.randomPastel
raster.setValue([x,y], color.rgb[0], 0)
raster.setValue([x,y], color.rgb[1], 1)
raster.setValue([x,y], color.rgb[2], 2)
}

Raster Values
Get values from a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")

Get values from a Raster with a Point.
double elevation = raster.getValue(new Point(-121.799927,46.867703))
println elevation
3069.0
Get values from a Raster with a Pixel Location.
List pixel = [100,200]
elevation = raster.getValue(pixel)
println elevation
288.0
Get neighboring values from a Raster with a Point Location.
Map neighborsOfPoint = raster.getNeighbors(new Point(-176.625, 85.72499), 0)
println "Values neighboring POINT (-176.625 85.7249984741211) = ${neighborsOfPoint}"
Values neighboring POINT (-176.625 85.7249984741211) = [nw:103.0, n:104.0, ne:109.0, e:109.0, se:111.0, s:110.0, sw:110.0, w:108.0]
Get neighboring values from a Raster with a Pixel Location.
Map neighborsOfPixel = raster.getNeighbors([7,9], 0)
println "Values neighboring pixel 7,9 = ${neighborsOfPixel}"
Values neighboring pixel 7,9 = [nw:103.0, n:104.0, ne:109.0, e:109.0, se:111.0, s:110.0, sw:110.0, w:108.0]
Get values from a Raster for a range of pixels in a list of lists.
int x = 10
int y = 8
int w = 5
int h = 6
int band = 0
List values = raster.getValues(x, y, w, h, band, false)
println values
[[1032, 1186, 1340, 1435, 1301], [1143, 1143, 1193, 1224, 1313], [942, 938, 966, 982, 1129], [746, 835, 912, 949, 1028], [723, 948, 1130, 1244, 1211], [673, 890, 1100, 1133, 1024]]
Get values from a Raster for a range of pixels in a flat list.
List flatValues = raster.getValues(x, y, w, h, band, true)
println flatValues
[1032, 1186, 1340, 1435, 1301, 1143, 1143, 1193, 1224, 1313, 942, 938, 966, 982, 1129, 746, 835, 912, 949, 1028, 723, 948, 1130, 1244, 1211, 673, 890, 1100, 1133, 1024]
Get values from a Raster for a range of pixels as a pretty printed string.
String valuesAsString = raster.getValuesAsString(x, y, w, h, band, prettyPrint: true)
println valuesAsString
--------------------------------------------------- | 1032.00 | 1186.00 | 1340.00 | 1435.00 | 1301.00 | --------------------------------------------------- | 1143.00 | 1143.00 | 1193.00 | 1224.00 | 1313.00 | --------------------------------------------------- | 942.00 | 938.00 | 966.00 | 982.00 | 1129.00 | --------------------------------------------------- | 746.00 | 835.00 | 912.00 | 949.00 | 1028.00 | --------------------------------------------------- | 723.00 | 948.00 | 1130.00 | 1244.00 | 1211.00 | --------------------------------------------------- | 673.00 | 890.00 | 1100.00 | 1133.00 | 1024.00 | ---------------------------------------------------
Iterate over the cells in a Raster.
raster.eachCell(bounds: [0,0,5,5]) { double value, double pixelX, double pixelY ->
println "${pixelX},${pixelY} = ${value}"
}
0.0,0.0 = 1061.0 1.0,0.0 = 996.0 2.0,0.0 = 945.0 3.0,0.0 = 960.0 4.0,0.0 = 904.0 0.0,1.0 = 1167.0 1.0,1.0 = 1149.0 2.0,1.0 = 1085.0 3.0,1.0 = 966.0 4.0,1.0 = 862.0 0.0,2.0 = 1112.0 1.0,2.0 = 998.0 2.0,2.0 = 882.0 3.0,2.0 = 775.0 4.0,2.0 = 700.0 0.0,3.0 = 990.0 1.0,3.0 = 850.0 2.0,3.0 = 715.0 3.0,3.0 = 638.0 4.0,3.0 = 654.0 0.0,4.0 = 833.0 1.0,4.0 = 706.0 2.0,4.0 = 611.0 3.0,4.0 = 681.0 4.0,4.0 = 841.0
Iterate over a window of cells in a Raster.
raster.eachWindow (bounds: [0,0,8,8], window: [2,2]) { Number[][] windowsValues, double pixelX, double pixelY ->
println "${pixelX},${pixelY} = ${windowsValues}"
}
0.0,0.0 = [[1061, 996], [1167, 1149]] 1.0,0.0 = [[996, 945], [1149, 1085]] 2.0,0.0 = [[945, 960], [1085, 966]] 3.0,0.0 = [[960, 904], [966, 862]] 4.0,0.0 = [[904, 727], [862, 696]] 5.0,0.0 = [[727, 744], [696, 748]] 6.0,0.0 = [[744, 934], [748, 900]] 7.0,0.0 = [[934, 1099], [900, 1042]] 0.0,1.0 = [[1167, 1149], [1112, 998]] 1.0,1.0 = [[1149, 1085], [998, 882]] 2.0,1.0 = [[1085, 966], [882, 775]] 3.0,1.0 = [[966, 862], [775, 700]] 4.0,1.0 = [[862, 696], [700, 661]] 5.0,1.0 = [[696, 748], [661, 818]] 6.0,1.0 = [[748, 900], [818, 995]] 7.0,1.0 = [[900, 1042], [995, 1125]] 0.0,2.0 = [[1112, 998], [990, 850]] 1.0,2.0 = [[998, 882], [850, 715]] 2.0,2.0 = [[882, 775], [715, 638]] 3.0,2.0 = [[775, 700], [638, 654]] 4.0,2.0 = [[700, 661], [654, 826]] 5.0,2.0 = [[661, 818], [826, 945]] 6.0,2.0 = [[818, 995], [945, 922]] 7.0,2.0 = [[995, 1125], [922, 1078]] 0.0,3.0 = [[990, 850], [833, 706]] 1.0,3.0 = [[850, 715], [706, 611]] 2.0,3.0 = [[715, 638], [611, 681]] 3.0,3.0 = [[638, 654], [681, 841]] 4.0,3.0 = [[654, 826], [841, 949]] 5.0,3.0 = [[826, 945], [949, 1084]] 6.0,3.0 = [[945, 922], [1084, 1054]] 7.0,3.0 = [[922, 1078], [1054, 1093]] 0.0,4.0 = [[833, 706], [652, 618]] 1.0,4.0 = [[706, 611], [618, 548]] 2.0,4.0 = [[611, 681], [548, 631]] 3.0,4.0 = [[681, 841], [631, 694]] 4.0,4.0 = [[841, 949], [694, 877]] 5.0,4.0 = [[949, 1084], [877, 1018]] 6.0,4.0 = [[1084, 1054], [1018, 1142]] 7.0,4.0 = [[1054, 1093], [1142, 1172]] 0.0,5.0 = [[652, 618], [631, 579]] 1.0,5.0 = [[618, 548], [579, 506]] 2.0,5.0 = [[548, 631], [506, 483]] 3.0,5.0 = [[631, 694], [483, 556]] 4.0,5.0 = [[694, 877], [556, 686]] 5.0,5.0 = [[877, 1018], [686, 825]] 6.0,5.0 = [[1018, 1142], [825, 1004]] 7.0,5.0 = [[1142, 1172], [1004, 1053]] 0.0,6.0 = [[631, 579], [772, 766]] 1.0,6.0 = [[579, 506], [766, 627]] 2.0,6.0 = [[506, 483], [627, 529]] 3.0,6.0 = [[483, 556], [529, 473]] 4.0,6.0 = [[556, 686], [473, 556]] 5.0,6.0 = [[686, 825], [556, 669]] 6.0,6.0 = [[825, 1004], [669, 810]] 7.0,6.0 = [[1004, 1053], [810, 917]] 0.0,7.0 = [[772, 766], [900, 880]] 1.0,7.0 = [[766, 627], [880, 778]] 2.0,7.0 = [[627, 529], [778, 671]] 3.0,7.0 = [[529, 473], [671, 540]] 4.0,7.0 = [[473, 556], [540, 483]] 5.0,7.0 = [[556, 669], [483, 536]] 6.0,7.0 = [[669, 810], [536, 641]]
Set values on a Raster
File file = new File("src/main/resources/earth.tif")
GeoTIFF geotiff = new GeoTIFF(file)
Raster raster = geotiff.read("earth")
File arcGridFile = new File("target/earth.asc")
ArcGrid arcGrid = new ArcGrid(arcGridFile)
arcGrid.write(raster)
Raster arcGridRaster = arcGrid.read("earth")
arcGridRaster.eachCell {double value, double x, double y ->
double newValue = value + 100
arcGridRaster.setValue([x as int, y as int], newValue)
}
File arcGridAddFile = new File("target/earth_100.asc")
ArcGrid arcGridAdd = new ArcGrid(arcGridAddFile)
arcGridAdd.write(arcGridRaster)
Raster arcGridRasterAdd = arcGridAdd.read("earth_100")
List pixels = [
[92, 298],
[393.0, 343.0],
[795.0, 399.0]
]
pixels.each { List pixel ->
println "Original: ${raster.getValue(pixel)} New: ${arcGridRasterAdd.getValue(pixel)}"
}
Original: 97.0 New: 197.0 Original: 96.0 New: 196.0 Original: 237.0 New: 337.0


Raster Processing
Crop
Crop a Raster with a Bounds
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
Raster croppedRaster = raster.crop(new Bounds(-160.927734,6.751896,-34.716797,57.279043, "EPSG:4326"))

Project
Reproject a Raster to another Projection
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
Projection projection = new Projection("EPSG:3857")
Raster projectedRaster = raster.crop(projection.geoBounds).reproject(projection)

Transform
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Scale a Raster
Raster scaledRaster = raster.transform(scalex: 10, scaley: 10)

Shear a Raster
Raster shearedRaster = raster.transform(shearx: 10, sheary: 10)

Translate a Raster
Raster translatedRaster = raster.transform(translatex: 10.1, translatey: 12.6)

Transform a Raster with a combination of parameters
Raster transformedRaster = raster.transform(
scalex: 1.1, scaley: 2.1,
shearx: 0.4, sheary: 0.3,
translatex: 10.1, translatey: 12.6,
nodata: [-255],
interpolation: "NEAREST"
)

Select Bands
Extract a band from a Raster to create a new Raster
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
Raster band1 = raster.selectBands([0])
Raster band2 = raster.selectBands([1])
Raster band3 = raster.selectBands([2])
Band 1

Band 2

Band 3

Merge
Merge a List of Rasters representing different bands together to create a single Raster
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
Raster band1 = raster.selectBands([0])
Raster band2 = raster.selectBands([1])
Raster band3 = raster.selectBands([2])
Raster mergedRaster = Raster.merge([band1,band2,band3], transform: "FIRST")

Mosaic
Mosaic a List of Rasters together to create a single Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Bounds bounds = raster.bounds
List<Raster> rasters = bounds.tile(0.5).collect { Bounds b ->
raster.crop(b)
}
Raster mosaicedRaster = Raster.mosaic(rasters)


Contours
Create vector contours from a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
int band = 0
int interval = 300
boolean simplify = true
boolean smooth = true
Layer contours = raster.contours(band, interval, simplify, smooth)

Stylize
Stylize a Raster by baking in a style to create a new Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Raster stylizedRaster = raster.stylize(new ColorMap([
[color: "#9fd182", quantity:25],
[color: "#3e7f3c", quantity:470],
[color: "#133912", quantity:920],
[color: "#08306b", quantity:1370],
[color: "#fffff5", quantity:1820],
]))

Shaded Relief
Create a shaded relief Raster from another Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Raster shadedReliefRaster = raster.createShadedRelief(
1.0, (1)
25, (2)
260 (3)
)
1 | scale |
2 | altitude |
3 | azimuth |

Reclassify
Reclassify a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Raster reclassifiedRaster = raster.reclassify([
[min:0, max:0, value: 1],
[min:0, max:50, value: 2],
[min:50, max:200, value: 3],
[min:200, max:1000, value: 4],
[min:1000, max:1500, value: 5],
[min:1500, max:4000, value: 6]
])

Scale
Scale a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
println "Original Raster Size = ${raster.size[0]}x${raster.size[1]}"
Raster scaledRaster = raster.scale(0.5, 0.5)
println "Scaled Raster Size = ${scaledRaster.size[0]}x${scaledRaster.size[1]}"
Original Raster Size = 800x400 Scaled Raster Size = 400x200

Resample
Resample a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
println "Original Raster Bounds = ${raster.bounds}"
println "Original Raster Size = ${raster.size[0]}x${raster.size[1]}"
Raster resampledRaster = raster.resample(size: [400, 400], bbox: raster.bounds.scale(-2))
println "Resampled Raster Bounds = ${resampledRaster.bounds}"
println "Resampled Raster Size = ${resampledRaster.size[0]}x${resampledRaster.size[1]}"
Original Raster Bounds = (-123.55291606131708,46.25375026634816,-120.73958272798374,47.522916933014834,EPSG:4326) Original Raster Size = 800x400 Resampled Raster Bounds = (-124.95958272798374,45.619166933014824,-119.33291606131708,48.157500266348165,EPSG:4326) Resampled Raster Size = 400x400

Normalize
Normalize a Raster by diving all values by the maximum value.
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
println "Original Raster Min Max values = ${raster.extrema.min[0]} - ${raster.extrema.max[0]}"
Raster normalizedRaster = raster.normalize()
println "Normalized Raster Min Max values = ${normalizedRaster.extrema.min[0]} - ${normalizedRaster.extrema.max[0]}"
Original Raster Min Max values = -23.0 - 4370.0 Normalized Raster Min Max values = -0.005263158120214939 - 1.0

Convolve
Convolve a Raster with a radius.
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
println "Original Raster Min Max values = ${raster.extrema.min[0]} - ${raster.extrema.max[0]}"
Raster convolvedRaster = raster.convolve(2)
println "Convolved Raster Min Max values = ${convolvedRaster.extrema.min[0]} - ${convolvedRaster.extrema.max[0]}"
Original Raster Min Max values = -23.0 - 4370.0 Convolved Raster Min Max values = -32767.0 - 32767.0

Convolve a Raster with a width and height.
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
println "Original Raster Min Max values = ${raster.extrema.min[0]} - ${raster.extrema.max[0]}"
Raster convolvedRaster = raster.convolve(1,2)
println "Convolved Raster Min Max values = ${convolvedRaster.extrema.min[0]} - ${convolvedRaster.extrema.max[0]}"
Original Raster Min Max values = -23.0 - 4370.0 Convolved Raster Min Max values = -32767.0 - 8675.0

Invert
Invert the values of a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Raster invertedRaster = raster.invert()

Exponent
Calculate the exponent of the values of a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Raster expRaster = raster.exp()

Absolute
Calculate the absolute value of the values of a Raster
File file = new File("src/main/resources/absolute.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("absolute")
Raster absolute = raster.absolute()


Log
Calculate the log of the values of a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Raster logRaster = raster.log()

Vectorize
Create a Polygon Layer from a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Raster reclassifiedRaster = raster.reclassify([
[min:0, max:0, value: 1],
[min:0, max:50, value: 2],
[min:50, max:200, value: 3],
[min:200, max:1000, value: 4],
[min:1000, max:1500, value: 5],
[min:1500, max:4000, value: 6]
])
Layer layer = reclassifiedRaster.polygonLayer

Create a Point Layer from a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc").crop(new Bounds(-121.878548,46.808402,-121.636505,46.896097, "EPSG:4326"))
Layer layer = raster.pointLayer

Extract a foot print from a Raster
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
Layer layer = raster.extractFootPrint()

Calculate zonal statistics
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
Layer zones = new Memory().create("zones", [new Field("geom","Geometry","EPSG:4326")])
Bounds bounds = raster.bounds
bounds.tile(0.5).each{b -> zones.add([b.geometry])}
Layer stats = raster.zonalStatistics(0, zones)

count | min | max | sum | avg | stddev |
---|---|---|---|---|---|
79950 |
-3.0 |
1718.0 |
2.6618944E7 |
332.94489055659943 |
262.73459374414483 |
80000 |
254.0 |
4370.0 |
9.2963902E7 |
1162.0487749999913 |
439.0841907966851 |
71728 |
-23.0 |
1755.0 |
1.1585759E7 |
161.52351940664724 |
179.29389227723505 |
80000 |
24.0 |
2728.0 |
7.9051464E7 |
988.1433000000056 |
465.8407188458327 |
Histogram
Get histogram of the Raster
File file = new File("src/main/resources/earth.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("earth")
Histogram histogram = raster.getHistogram()
println "# of bands = ${histogram.numberOfBands}"
println "# Counts = ${histogram.counts().size()}"
println "# Bins = ${histogram.bins().size()}"
println "Count 25 = ${histogram.count(25)}"
println "Bin 45 = ${histogram.bin(45)}"
Chart chart = Bar.xy(histogram.counts(0).withIndex().collect {int count, int index -> [index, count]})
# of bands = 3 # Counts = 256 # Bins = 256 Count 25 = 0 Bin 45 = [45.0, 46.0]

Raster Algebra
Add
Add a constant value to a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
double elevation1 = raster.getValue(new Point(-121.799927,46.867703))
println elevation1
Raster higherRaster = raster.add(100.00)
double elevation2 = higherRaster.getValue(new Point(-121.799927,46.867703))
println elevation2
3069.0 3169.0

Add two Raster together
Raster lowRaster = Format.getFormat(new File("src/main/resources/low.tif")).read("low")
Raster highRaster = Format.getFormat(new File("src/main/resources/high.tif")).read("high")
Raster lowPlusHighRaster = lowRaster.add(highRaster)
Low

High

Low + High

Subtract
Subtract a constant value from a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
double elevation1 = raster.getValue(new Point(-121.799927,46.867703))
println elevation1
Raster lowerRaster = raster.minus(50.00)
double elevation2 = lowerRaster.getValue(new Point(-121.799927,46.867703))
println elevation2
3069.0 3019.0

Subtract the Raster from a constant value
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
double elevation1 = raster.getValue(new Point(-121.799927,46.867703))
println elevation1
Raster lowerRaster = raster.minusFrom(2000.0)
double elevation2 = lowerRaster.getValue(new Point(-121.799927,46.867703))
println elevation2
3069.0 -1069.0

Subtract a Raster from another Raster
Raster lowRaster = Format.getFormat(new File("src/main/resources/low.tif")).read("low")
Raster highRaster = Format.getFormat(new File("src/main/resources/high.tif")).read("high")
Raster highMinusLowRaster = highRaster.minus(lowRaster)
Low

High

High - Low

Multiply
Multiply a constant value against a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
double elevation1 = raster.getValue(new Point(-121.799927,46.867703))
println elevation1
Raster higherRaster = raster.multiply(2.0)
double elevation2 = higherRaster.getValue(new Point(-121.799927,46.867703))
println elevation2
3069.0 6138.0

Multiply a Raster with another Raster
Raster lowRaster = Format.getFormat(new File("src/main/resources/low.tif")).read("low")
Raster highRaster = Format.getFormat(new File("src/main/resources/high.tif")).read("high")
Raster multiplyRaster = highRaster.multiply(lowRaster)
Low

High

High * Low

Divide
Divide a constant value against a Raster
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
double elevation1 = raster.getValue(new Point(-121.799927,46.867703))
println elevation1
Raster lowerRaster = raster.divide(2.0)
double elevation2 = lowerRaster.getValue(new Point(-121.799927,46.867703))
println elevation2
3069.0 1534.5

Divide a Raster by another Raster
Raster lowRaster = Format.getFormat(new File("src/main/resources/low.tif")).read("low")
Raster highRaster = Format.getFormat(new File("src/main/resources/high.tif")).read("high")
Raster divideRaster = highRaster.divide(lowRaster)
Low

High

High / Low

World File
Create a world file from a Bounds and size.
File file = new File("target/worldfile.txt")
WorldFile worldFile = new WorldFile(new Bounds(-123.06, 46.66, -121.15, 47.48), [500,500], file)
println "Pixel Size = ${worldFile.pixelSize[0]} x ${worldFile.pixelSize[1]}"
println "Rotation = ${worldFile.rotation[0]} x ${worldFile.rotation[1]}"
println "Upper Left Coordinate = ${worldFile.ulc.x}, ${worldFile.ulc.y}"
println "File = ${file.text}"
Pixel Size = 0.003819999999999993 x -0.0016400000000000006 Rotation = 0.0 x 0.0 Upper Left Coordinate = -123.05809, 47.47918 File = 0.003819999999999993 0.0 0.0 -0.0016400000000000006 -123.05809 47.47918
Create a world file from an existing file.
File file = new File("src/main/resources/worldfile.txt")
WorldFile worldFile = new WorldFile(file)
println "Pixel Size = ${worldFile.pixelSize[0]} x ${worldFile.pixelSize[1]}"
println "Rotation = ${worldFile.rotation[0]} x ${worldFile.rotation[1]}"
println "Upper Left Coordinate = ${worldFile.ulc.x}, ${worldFile.ulc.y}"
Pixel Size = 0.003819999999999993 x -0.0016400000000000006 Rotation = 0.0 x 0.0 Upper Left Coordinate = -123.05809, 47.47918
Map Algebra
GeoScript uses Jiffle to perform map or raster algebra.
Add two Rasters together
Raster lowRaster = Format.getFormat(new File("src/main/resources/low.tif")).read("low")
Raster highRaster = Format.getFormat(new File("src/main/resources/high.tif")).read("high")
MapAlgebra mapAlgebra = new MapAlgebra()
Raster output = mapAlgebra.calculate("dest = raster1 + raster2;", [raster1: lowRaster, raster2: highRaster], size: [300, 200])
Low

High

High + Low

Generate a wave Raster
MapAlgebra algebra = new MapAlgebra()
String script = """
init {
// image centre coordinates
xc = width() / 2;
yc = height() / 2;
// constant term
C = M_PI * 8;
}
dx = (x() - xc) / xc;
dy = (y() - yc) / yc;
d = sqrt(dx*dx + dy*dy);
destImg = sin(C * d);
"""
Raster output = algebra.calculate(script, [:], outputName: "destImg")

Create a Raster of all cells greater than a given value
File file = new File("src/main/resources/pc.tif")
Format format = Format.getFormat(file)
Raster raster = format.read("pc")
println raster.size
MapAlgebra mapAlgebra = new MapAlgebra()
Raster output = mapAlgebra.calculate("dest = src > 1100;", [src: raster], size: [800, 400])
println output.extrema

WMS Recipes
The WMS classes are in the geoscript.layer package.
WMS Server
WMS wms = new WMS("https://lpdaacsvc.cr.usgs.gov/ogc/wms")
println "Name = ${wms.name}"
println "Title = ${wms.title}"
println "Abstract = ${wms.abstract}"
println "Keywords = ${wms.keywords.join(', ')}"
println "Online Resource = ${wms.onlineResource}"
println "Update Sequence = ${wms.updateSequence}"
println "Version = ${wms.version}"
println "Map Formats = ${wms.getMapFormats.join(', ')}"
Name = WMS Title = GeoServer Web Map Service Abstract = A compliant implementation of WMS plus most of the SLD extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS Keywords = WFS, WMS, GEOSERVER Online Resource = http://geoserver.sourceforge.net/html/index.php Update Sequence = 35327 Version = 1.3.0 Map Formats = image/png, application/atom+xml, application/pdf, application/rss+xml, application/vnd.google-earth.kml+xml, application/vnd.google-earth.kml+xml;mode=networklink, application/vnd.google-earth.kmz, image/geotiff, image/geotiff8, image/gif, image/jpeg, image/png; mode=8bit, image/svg+xml, image/tiff, image/tiff8, text/html; subtype=openlayers
WMS wms = new WMS("https://lpdaacsvc.cr.usgs.gov/ogc/wms")
wms.layers.subList(0,10).each { WMS.Layer layer ->
println layer
}
MODIS:MCD12Q1.2016001.006.LandCover MODIS:MOD09A1.2018073.006.SurRefl MODIS:MOD09A1.2018081.006.SurRefl MODIS:MOD09A1.2018089.006.SurRefl MODIS:MOD09A1.2018097.006.SurRefl MODIS:MOD09A1.2018105.006.SurRefl MODIS:MOD09A1.2018113.006.SurRefl MODIS:MOD09A1.2018121.006.SurRefl MODIS:MOD09A1.2018129.006.SurRefl MODIS:MOD09A1.2018137.006.SurRefl
WMS wms = new WMS("https://lpdaacsvc.cr.usgs.gov/ogc/wms")
WMS.Layer layer = wms.getLayer("MODIS:MOD09A1.2018185.006.SurRefl")
println "Name = ${layer.name}"
println "Title = ${layer.title}"
println "Bounds = ${layer.bounds}"
println "Lat/Lon Bounds = ${layer.latLonBounds}"
println "Queryable = ${layer.queryable}"
println "Min Scale = ${layer.minScale}"
println "Max Scale = ${layer.maxScale}"
Name = MODIS:MOD09A1.2018185.006.SurRefl Title = MOD09A1.2018185.006.SurRefl Bounds = [(-90.00000143999999,-180.0,90.0,180.00000287999998,EPSG:4326), (-180.0,-90.00000143999999,180.00000287999998,90.0,EPSG:4326)] Lat/Lon Bounds = (-180.0,-90.00000143999999,180.00000287999998,90.0,EPSG:4326) Queryable = true Min Scale = NaN Max Scale = NaN
WMS wms = new WMS("https://lpdaacsvc.cr.usgs.gov/ogc/wms")
Raster raster = wms.getRaster(["MODIS:MOD14A2.2018209.006.Fire"])

WMS wms = new WMS("https://lpdaacsvc.cr.usgs.gov/ogc/wms")
BufferedImage image = wms.getImage(["MODIS:MOD17A2H.2019041.006.GPP"])

WMSLayer
A WMSLayer is a way to draw one or more WMS layers on a Map.
WMS wms = new WMS("http://1maps.geo-solutions.it/geoserver/osm/wms?service=wms&version=1.1.1&request=GetCapabilities")
WMSLayer layer = new WMSLayer(wms, ["icesheet_polygons", "ne_10m_admin_0_countries"])
Map map = new Map(layers: [layer], backgroundColor: "#B0C4DE", bounds: new Bounds(-179, -85, 179, 85, "EPSG:4326").reproject("EPSG:3857"))
BufferedImage image = map.renderToImage()

Tile Recipes
The Tile classes are in the geoscript.layer package.
Tile
Tile Properties
Get a Tile’s Properties.
byte[] data = new File("src/main/resources/tile.png").bytes
Tile tile = new Tile(2,1,3,data)
println "Z = ${tile.z}"
println "X = ${tile.x}"
println "Y = ${tile.y}"
println "Tile = ${tile.toString()}"
println "# bytes = ${tile.data.length}"
println "Data as base64 encoded string = ${tile.base64String}"
Z = 2 X = 1 Y = 3 Tile = Tile(x:1, y:3, z:2) # bytes = 11738 Data as base64 encoded string = iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAtoU...
Grid
A Grid describes a level in a Pyramid of Tiles.
Grid Properties
Grid grid = new Grid(1, 2, 2, 78206.0, 78206.0)
println "Zoom Level: ${grid.z}"
println "Width / # Columns: ${grid.width}"
println "Height / # Rows: ${grid.height}"
println "Size / # Tiles: ${grid.size}"
println "X Resolution: ${grid.xResolution}"
println "Y Resolution: ${grid.yResolution}"
Zoom Level: 1 Width / # Columns: 2 Height / # Rows: 2 Size / # Tiles: 4 X Resolution: 78206.0 Y Resolution: 78206.0
Pyramid
Pyramid Properties
Get the Pyramid’s Bounds.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Bounds bounds = pyramid.bounds
println bounds
(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857)
Get the Pyramid’s projection.
Projection proj = pyramid.proj
println proj
EPSG:3857
Get the Pyramid’s Origin.
Pyramid.Origin origin = pyramid.origin
println origin
BOTTOM_LEFT
Get the Pyramid’s Tile Width and Height.
int tileWidth = pyramid.tileWidth
int tileHeight = pyramid.tileHeight
println "${tileWidth} x ${tileHeight}"
256 x 256
Create Pyramids
Create a Global Mercator Pyramid.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
println "Projection: ${pyramid.proj}"
println "Origin: ${pyramid.origin}"
println "Bounds: ${pyramid.bounds}"
println "Max Zoom: ${pyramid.maxGrid.z}"
Projection: EPSG:3857 Origin: BOTTOM_LEFT Bounds: (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) Max Zoom: 19
Create a Global Geodetic Pyramid.
Pyramid pyramid = Pyramid.createGlobalGeodeticPyramid()
println "Projection: ${pyramid.proj}"
println "Origin: ${pyramid.origin}"
println "Bounds: ${pyramid.bounds}"
println "Max Zoom: ${pyramid.maxGrid.z}"
Projection: EPSG:4326 Origin: BOTTOM_LEFT Bounds: (-179.99,-89.99,179.99,89.99,EPSG:4326) Max Zoom: 19
Create a Global Mercator Pyramid from a well known name.
Well known names include:
-
GlobalMercator
-
Mercator
-
GlobalMercatorBottomLeft
-
GlobalMercatorTopLeft
-
GlobalGeodetic
-
Geodetic
Pyramid pyramid = Pyramid.fromString("mercator")
println "Projection: ${pyramid.proj}"
println "Origin: ${pyramid.origin}"
println "Bounds: ${pyramid.bounds}"
println "Max Zoom: ${pyramid.maxGrid.z}"
Projection: EPSG:3857 Origin: BOTTOM_LEFT Bounds: (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) Max Zoom: 19
Get Bounds from a Pyramid
Get the Bounds for a Tile.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Tile tile = new Tile(2, 1, 1)
Bounds bounds = pyramid.bounds(tile)
println "The bounds of ${tile} is ${bounds}"
The bounds of Tile(x:1, y:1, z:2) is (-1.0018197573940655E7,-1.0018735602568535E7,0.0,-3.725290298461914E-9,EPSG:3857)

Get the Bounds for an area around a Point at a zoom level.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Point point = Projection.transform(new Point(22.1539306640625, 37.67077737288316), "EPSG:4326", "EPSG:3857")
int zoomLevel = 8
int width = 400
int height = 400
Bounds bounds = pyramid.bounds(point, zoomLevel, width, height)
println "The bounds around ${point} is ${bounds}"
The bounds around POINT (2466164.280592927 4533021.525424092) is (2343967.405592927,4410824.650424092,2588361.155592927,4655218.400424092,EPSG:3857)

Get a Grid from a Pyramid
Get a the min Grid.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Grid grid = pyramid.minGrid
println "Zoom Level: ${grid.z}"
println "Width / # Columns: ${grid.width}"
println "Height / # Rows: ${grid.height}"
println "Size / # Tiles: ${grid.size}"
println "X Resolution: ${grid.xResolution}"
println "Y Resolution: ${grid.yResolution}"
Zoom Level: 0 Width / # Columns: 1 Height / # Rows: 1 Size / # Tiles: 1 X Resolution: 156412.0 Y Resolution: 156412.0
Get a the max Grid.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Grid grid = pyramid.maxGrid
println "Zoom Level: ${grid.z}"
println "Width / # Columns: ${grid.width}"
println "Height / # Rows: ${grid.height}"
println "Size / # Tiles: ${grid.size}"
println "X Resolution: ${grid.xResolution}"
println "Y Resolution: ${grid.yResolution}"
Zoom Level: 19 Width / # Columns: 524288 Height / # Rows: 524288 Size / # Tiles: 274877906944 X Resolution: 0.29833221435546875 Y Resolution: 0.29833221435546875
Get a Grid from a Pyramid by Zoom Level.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Grid grid = pyramid.grid(1)
println "Zoom Level: ${grid.z}"
println "Width / # Columns: ${grid.width}"
println "Height / # Rows: ${grid.height}"
println "Size / # Tiles: ${grid.size}"
println "X Resolution: ${grid.xResolution}"
println "Y Resolution: ${grid.yResolution}"
Zoom Level: 1 Width / # Columns: 2 Height / # Rows: 2 Size / # Tiles: 4 X Resolution: 78206.0 Y Resolution: 78206.0
Get a Grid from a Pyramid by a Bounds and Resolution.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Bounds bounds = new Bounds(-123.09, 46.66, -121.13, 47.48, "EPSG:4326").reproject("EPSG:3857")
Grid grid = pyramid.grid(bounds, bounds.width / 400.0, bounds.height / 200.0)
println "Zoom Level: ${grid.z}"
println "Width / # Columns: ${grid.width}"
println "Height / # Rows: ${grid.height}"
println "Size / # Tiles: ${grid.size}"
println "X Resolution: ${grid.xResolution}"
println "Y Resolution: ${grid.yResolution}"
Zoom Level: 8 Width / # Columns: 256 Height / # Rows: 256 Size / # Tiles: 65536 X Resolution: 610.984375 Y Resolution: 610.984375
Get a Grid from a Pyramid by a Bounds and Size.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Bounds bounds = new Bounds(-123.09, 46.66, -121.13, 47.48, "EPSG:4326").reproject("EPSG:3857")
Grid grid = pyramid.grid(bounds, 400, 200)
println "Zoom Level: ${grid.z}"
println "Width / # Columns: ${grid.width}"
println "Height / # Rows: ${grid.height}"
println "Size / # Tiles: ${grid.size}"
println "X Resolution: ${grid.xResolution}"
println "Y Resolution: ${grid.yResolution}"
Zoom Level: 8 Width / # Columns: 256 Height / # Rows: 256 Size / # Tiles: 65536 X Resolution: 610.984375 Y Resolution: 610.984375
Get Tile Coordinates
Get the tile coordinates from a Pyramid by Bounds and zoom level
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Bounds bounds = new Bounds(-124.73142200000001, 24.955967, -66.969849, 49.371735, "EPSG:4326").reproject("EPSG:3857")
long zoomLevel = 4
Map<String, Integer> coords = pyramid.getTileCoordinates(bounds, zoomLevel)
println "Min X = ${coords.minX}"
println "Min Y = ${coords.minY}"
println "Max X = ${coords.maxX}"
println "Max Y = ${coords.maxY}"
Min X = 2 Min Y = 9 Max X = 5 Max Y = 10
Get the tile coordinates from a Pyramid by Bounds and Grid
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
Bounds bounds = new Bounds(20.798492,36.402494,22.765045,37.223768, "EPSG:4326").reproject("EPSG:3857")
Grid grid = pyramid.grid(10)
Map<String, Integer> coords = pyramid.getTileCoordinates(bounds, grid)
println "Min X = ${coords.minX}"
println "Min Y = ${coords.minY}"
println "Max X = ${coords.maxX}"
println "Max Y = ${coords.maxY}"
Min X = 571 Min Y = 623 Max X = 576 Max Y = 626
Reading and Writing Pyramids
The Pyramid IO classes are in the geoscript.layer.io package.
Finding Pyramid Writer and Readers
List<PyramidWriter> writers = PyramidWriters.list()
writers.each { PyramidWriter writer ->
println writer.class.simpleName
}
CsvPyramidWriter GdalTmsPyramidWriter JsonPyramidWriter XmlPyramidWriter
Pyramid pyramid = Pyramid.createGlobalGeodeticPyramid(maxZoom: 2)
PyramidWriter writer = PyramidWriters.find("csv")
String pyramidStr = writer.write(pyramid)
println pyramidStr
EPSG:4326 -179.99,-89.99,179.99,89.99,EPSG:4326 BOTTOM_LEFT 256,256 0,2,1,0.703125,0.703125 1,4,2,0.3515625,0.3515625 2,8,4,0.17578125,0.17578125
List<PyramidReader> readers = PyramidReaders.list()
readers.each { PyramidReader reader ->
println reader.class.simpleName
}
CsvPyramidReader GdalTmsPyramidReader JsonPyramidReader XmlPyramidReader
PyramidReader reader = PyramidReaders.find("csv")
Pyramid pyramid = reader.read("""EPSG:3857
-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857
BOTTOM_LEFT
256,256
0,1,1,156412.0,156412.0
1,2,2,78206.0,78206.0
2,4,4,39103.0,39103.0
3,8,8,19551.5,19551.5
4,16,16,9775.75,9775.75
""")
println pyramid
geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
JSON
Get a JSON String from a Pyramid.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid(maxZoom: 4)
String json = pyramid.json
println json
{ "proj": "EPSG:3857", "bounds": { "minX": -2.003639514788131E7, "minY": -2.0037471205137067E7, "maxX": 2.003639514788131E7, "maxY": 2.003747120513706E7 }, "origin": "BOTTOM_LEFT", "tileSize": { "width": 256, "height": 256 }, "grids": [ { "z": 0, "width": 1, "height": 1, "xres": 156412.0, "yres": 156412.0 }, { "z": 1, "width": 2, "height": 2, "xres": 78206.0, "yres": 78206.0 }, { "z": 2, "width": 4, "height": 4, "xres": 39103.0, "yres": 39103.0 }, { "z": 3, "width": 8, "height": 8, "xres": 19551.5, "yres": 19551.5 }, { "z": 4, "width": 16, "height": 16, "xres": 9775.75, "yres": 9775.75 } ] }
XML
Get a XML String from a Pyramid.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid(maxZoom: 4)
String xml = pyramid.xml
println xml
<pyramid> <proj>EPSG:3857</proj> <bounds> <minX>-2.003639514788131E7</minX> <minY>-2.0037471205137067E7</minY> <maxX>2.003639514788131E7</maxX> <maxY>2.003747120513706E7</maxY> </bounds> <origin>BOTTOM_LEFT</origin> <tileSize> <width>256</width> <height>256</height> </tileSize> <grids> <grid> <z>0</z> <width>1</width> <height>1</height> <xres>156412.0</xres> <yres>156412.0</yres> </grid> <grid> <z>1</z> <width>2</width> <height>2</height> <xres>78206.0</xres> <yres>78206.0</yres> </grid> <grid> <z>2</z> <width>4</width> <height>4</height> <xres>39103.0</xres> <yres>39103.0</yres> </grid> <grid> <z>3</z> <width>8</width> <height>8</height> <xres>19551.5</xres> <yres>19551.5</yres> </grid> <grid> <z>4</z> <width>16</width> <height>16</height> <xres>9775.75</xres> <yres>9775.75</yres> </grid> </grids> </pyramid>
CSV
Get a CSV String from a Pyramid.
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid(maxZoom: 4)
String csv = pyramid.csv
println csv
EPSG:3857 -2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857 BOTTOM_LEFT 256,256 0,1,1,156412.0,156412.0 1,2,2,78206.0,78206.0 2,4,4,39103.0,39103.0 3,8,8,19551.5,19551.5 4,16,16,9775.75,9775.75
GDAL XML
Write a Pyramid to a GDAL XML File
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid(maxZoom: 4)
GdalTmsPyramidWriter writer = new GdalTmsPyramidWriter()
String xml = writer.write(pyramid, serverUrl: 'https://myserver.com/${z}/${x}/${y}', imageFormat: 'png')
println xml
<GDAL_WMS> <Service name='TMS'> <ServerURL>https://myserver.com/${z}/${x}/${y}</ServerURL> <SRS>EPSG:3857</SRS> <ImageFormat>png</ImageFormat> </Service> <DataWindow> <UpperLeftX>-2.003639514788131E7</UpperLeftX> <UpperLeftY>2.003747120513706E7</UpperLeftY> <LowerRightX>2.003639514788131E7</LowerRightX> <LowerRightY>-2.0037471205137067E7</LowerRightY> <TileLevel>4</TileLevel> <TileCountX>1</TileCountX> <TileCountY>1</TileCountY> <YOrigin>bottom</YOrigin> </DataWindow> <Projection>EPSG:3857</Projection> <BlockSizeX>256</BlockSizeX> <BlockSizeY>256</BlockSizeY> <BandsCount>3</BandsCount> </GDAL_WMS>
Read a Pyramid from a GDAL XML File
String xml = '''<GDAL_WMS>
<Service name='TMS'>
<ServerURL>https://myserver.com/${z}/${x}/${y}</ServerURL>
<SRS>EPSG:3857</SRS>
<ImageFormat>png</ImageFormat>
</Service>
<DataWindow>
<UpperLeftX>-2.0036395147881314E7</UpperLeftX>
<UpperLeftY>2.003747120513706E7</UpperLeftY>
<LowerRightX>2.0036395147881314E7</LowerRightX>
<LowerRightY>-2.0037471205137067E7</LowerRightY>
<TileLevel>4</TileLevel>
<TileCountX>1</TileCountX>
<TileCountY>1</TileCountY>
<YOrigin>bottom</YOrigin>
</DataWindow>
<Projection>EPSG:3857</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>3</BandsCount>
</GDAL_WMS>'''
GdalTmsPyramidReader reader = new GdalTmsPyramidReader()
Pyramid pyramid = reader.read(xml)
geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Generating Tiles
Generating Image Tiles
MBTiles
Generate Image Tiles to a MBTiles file
File file = new File("target/world.mbtiles")
MBTiles mbtiles = new MBTiles(file, "World", "World Tiles")
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
ImageTileRenderer renderer = new ImageTileRenderer(mbtiles, [ocean, countries])
TileGenerator generator = new TileGenerator()
generator.generate(mbtiles, renderer, 0, 2)

Generate Image Tiles to a MBTiles file with metatiles
File file = new File("target/world_meta.mbtiles")
MBTiles mbtiles = new MBTiles(file, "World", "World Tiles")
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
ImageTileRenderer renderer = new ImageTileRenderer(mbtiles, [ocean, countries])
TileGenerator generator = new TileGenerator()
generator.generate(mbtiles, renderer,0, 2, metatile: [width:4, height: 4])

DBTiles
Generate Image Tiles to a MBTiles like JDBC Database.
File file = new File("target/world_tiles.db")
DBTiles dbtiles = new DBTiles("jdbc:h2:${file}","org.h2.Driver", "World", "World wide tiles")
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
ImageTileRenderer renderer = new ImageTileRenderer(dbtiles, [ocean, countries])
TileGenerator generator = new TileGenerator()
generator.generate(dbtiles, renderer, 0, 2)

GeoPackage
Generate Image Tiles to a GeoPackage file
File file = new File("target/world.gpkg")
geoscript.layer.GeoPackage geopackage = new geoscript.layer.GeoPackage(file, "World", Pyramid.createGlobalGeodeticPyramid())
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
ImageTileRenderer renderer = new ImageTileRenderer(geopackage, [ocean, countries])
TileGenerator generator = new TileGenerator()
generator.generate(geopackage, renderer, 0, 2)

TMS
Generate Image Tiles to a TMS directory
File directory = new File("target/tiles")
directory.mkdir()
TMS tms = new TMS("world", "png", directory, Pyramid.createGlobalMercatorPyramid())
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
ImageTileRenderer renderer = new ImageTileRenderer(tms, [ocean, countries])
TileGenerator generator = new TileGenerator()
generator.generate(tms, renderer, 0, 2)

UTFGrid
Generate UTFGrid tiles to a directory
File directory = new File("target/utfgrid")
directory.mkdir()
UTFGrid utf = new UTFGrid(directory)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
UTFGridTileRenderer renderer = new UTFGridTileRenderer(utf, countries, [countries.schema.get("NAME")])
TileGenerator generator = new TileGenerator()
generator.generate(utf, renderer, 0, 2)

Vector Tiles
Generate vector tiles to a directory
File directory = new File("target/pbf")
directory.mkdir()
Workspace workspace = new Directory("src/main/resources/shapefiles")
Layer countries = workspace.get("countries")
Layer ocean = workspace.get("ocean")
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
pyramid.origin = Pyramid.Origin.TOP_LEFT
VectorTiles vectorTiles = new VectorTiles(
"world",
directory,
pyramid,
"pbf",
style: [
"countries": new Fill("white") + new Stroke("black", 1),
"ocean": new Fill("blue")
]
)
PbfVectorTileRenderer renderer = new PbfVectorTileRenderer([countries, ocean], [
"countries": ["NAME"],
"ocean": ["FeatureCla"]
])
TileGenerator generator = new TileGenerator()
generator.generate(vectorTiles, renderer, 0, 2)

Generate vector tiles to a MBTiles file
File file = new File("target/vectortiles.mbtiles")
Workspace workspace = new Directory("src/main/resources/shapefiles")
Layer countries = workspace.get("countries")
Layer ocean = workspace.get("ocean")
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
pyramid.origin = Pyramid.Origin.TOP_LEFT
VectorTiles vectorTiles = new VectorTiles(
"world",
file,
pyramid,
"pbf",
style: [
"countries": new Fill("white") + new Stroke("black", 1),
"ocean": new Fill("blue")
]
)
PbfVectorTileRenderer renderer = new PbfVectorTileRenderer([countries, ocean], [
"countries": ["NAME"],
"ocean": ["FeatureCla"]
])
TileGenerator generator = new TileGenerator()
generator.generate(vectorTiles, renderer, 0, 2)

Tile Layer
Tile Layer Properties
Create a TileLayer from an MBTiles File.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Get the TileLayer’s name.
String name = mbtiles.name
println name
countries
Get the TileLayer’s Bounds.
Bounds bounds = mbtiles.bounds
println bounds
(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857)
Get the TileLayer’s Projection.
Projection proj = mbtiles.proj
println proj
EPSG:3857
Get the TileLayer’s Pyramid.
Pyramid pyramid = mbtiles.pyramid
println pyramid
geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Get a Tile from a TileLayer.
Tile tile = mbtiles.get(0, 0, 0)
println tile
Tile(x:0, y:0, z:0)

Get, put, and delete a Tile from a TileLayer
Get a Tile from a TileLayer.
MBTiles layer = new MBTiles(file)
ImageTile tile = layer.get(0,0,0)

Add a Tile to a TileLayer.
File newTileFile = new File("src/main/resources/yellowtile.png")
ImageTile newTile = new ImageTile(0,0,0, newTileFile.bytes)
layer.put(newTile)
newTile = layer.get(0,0,0)

Remove a Tile from a TileLayer.
layer.delete(newTile)
newTile = layer.get(0,0,0)
println "Image = ${newTile.image}"
Image = null
Close a TileLayer
layer.close()
Delete Tiles from a TileLayer
MBTiles layer = new MBTiles(file)
layer.tiles(1).each { Tile tile ->
println "${tile} = ${tile.image == null}"
}
Tile(x:0, y:0, z:1) = false Tile(x:1, y:0, z:1) = false Tile(x:0, y:1, z:1) = false Tile(x:1, y:1, z:1) = false
layer.delete(layer.tiles(1))
layer.tiles(1).each { Tile tile ->
println "${tile} = ${tile.image == null}"
}
Tile(x:0, y:0, z:1) = true Tile(x:1, y:0, z:1) = true Tile(x:0, y:1, z:1) = true Tile(x:1, y:1, z:1) = true
Tiles
Get a TileCursor from a TileLayer with all of the Tiles in a zoom level.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
long zoomLevel = 1
TileCursor tileCursor = mbtiles.tiles(zoomLevel)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 1 # of tiles: 4 Bounds: (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) Width / # Columns: 2 Height / # Rows: 2 MinX: 0, MinY: 0, MaxX: 1, MaxY: 1 Tiles: Tile(x:0, y:0, z:1) Tile(x:1, y:0, z:1) Tile(x:0, y:1, z:1) Tile(x:1, y:1, z:1)
Get a TileCursor from a TileLayer with Tiles from a zoom level between min and max x and y coordinates.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
long zoomLevel = 4
long minX = 2
long minY = 4
long maxX = 5
long maxY = 8
TileCursor tileCursor = mbtiles.tiles(zoomLevel, minX, minY, maxX, maxY)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 4 # of tiles: 20 Bounds: (-1.5027296360910982E7,-1.0018735602568535E7,-5009098.786970327,2504683.900642129,EPSG:3857) Width / # Columns: 4 Height / # Rows: 5 MinX: 2, MinY: 4, MaxX: 5, MaxY: 8 Tiles: Tile(x:2, y:4, z:4) Tile(x:3, y:4, z:4) Tile(x:4, y:4, z:4) Tile(x:5, y:4, z:4) Tile(x:2, y:5, z:4) Tile(x:3, y:5, z:4) Tile(x:4, y:5, z:4) Tile(x:5, y:5, z:4) Tile(x:2, y:6, z:4) Tile(x:3, y:6, z:4) Tile(x:4, y:6, z:4) Tile(x:5, y:6, z:4) Tile(x:2, y:7, z:4) Tile(x:3, y:7, z:4) Tile(x:4, y:7, z:4) Tile(x:5, y:7, z:4) Tile(x:2, y:8, z:4) Tile(x:3, y:8, z:4) Tile(x:4, y:8, z:4) Tile(x:5, y:8, z:4)
Get a TileCursor from a TileLayer for a zoom level and a given Bounds.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(-102.875977, 45.433154, -96.481934, 48.118434, "EPSG:4326").reproject("EPSG:3857")
int zoomLevel = 8
TileCursor tileCursor = mbtiles.tiles(bounds, zoomLevel)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 8 # of tiles: 24 Bounds: (-1.1583540944868883E7,5635538.7764447965,-1.0644334922311947E7,6261709.751605326,EPSG:3857) Width / # Columns: 6 Height / # Rows: 4 MinX: 54, MinY: 164, MaxX: 59, MaxY: 167 Tiles: Tile(x:54, y:164, z:8) Tile(x:55, y:164, z:8) Tile(x:56, y:164, z:8) Tile(x:57, y:164, z:8) Tile(x:58, y:164, z:8) Tile(x:59, y:164, z:8) Tile(x:54, y:165, z:8) Tile(x:55, y:165, z:8) Tile(x:56, y:165, z:8) Tile(x:57, y:165, z:8) Tile(x:58, y:165, z:8) Tile(x:59, y:165, z:8) Tile(x:54, y:166, z:8) Tile(x:55, y:166, z:8) Tile(x:56, y:166, z:8) Tile(x:57, y:166, z:8) Tile(x:58, y:166, z:8) Tile(x:59, y:166, z:8) Tile(x:54, y:167, z:8) Tile(x:55, y:167, z:8) Tile(x:56, y:167, z:8) Tile(x:57, y:167, z:8) Tile(x:58, y:167, z:8) Tile(x:59, y:167, z:8)
Get a TileCursor from a TileLayer for a zoom level and given x and y resolutions.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(-124.73142200000001, 24.955967, -66.969849, 49.371735, "EPSG:4326").reproject("EPSG:3857")
double resolutionX = bounds.width / 400
double resolutionY = bounds.height / 300
TileCursor tileCursor = mbtiles.tiles(bounds, resolutionX, resolutionY)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 4 # of tiles: 8 Bounds: (-1.5027296360910982E7,2504683.9006421305,-5009098.786970327,7514051.701926393,EPSG:3857) Width / # Columns: 4 Height / # Rows: 2 MinX: 2, MinY: 9, MaxX: 5, MaxY: 10 Tiles: Tile(x:2, y:9, z:4) Tile(x:3, y:9, z:4) Tile(x:4, y:9, z:4) Tile(x:5, y:9, z:4) Tile(x:2, y:10, z:4) Tile(x:3, y:10, z:4) Tile(x:4, y:10, z:4) Tile(x:5, y:10, z:4)
Get a TileCursor from a TileLayer for a Bounds and a given canvas width and height.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(-102.875977, 45.433154, -96.481934, 48.118434, "EPSG:4326").reproject("EPSG:3857")
int width = 400
int height = 400
TileCursor tileCursor = mbtiles.tiles(bounds, width, height)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 7 # of tiles: 6 Bounds: (-1.1583540944868883E7,5635538.7764447965,-1.0644334922311947E7,6261709.751605329,EPSG:3857) Width / # Columns: 3 Height / # Rows: 2 MinX: 27, MinY: 82, MaxX: 29, MaxY: 83 Tiles: Tile(x:27, y:82, z:7) Tile(x:28, y:82, z:7) Tile(x:29, y:82, z:7) Tile(x:27, y:83, z:7) Tile(x:28, y:83, z:7) Tile(x:29, y:83, z:7)
Get a TileCursor from a TileLayer around a Point at a given zoom level for a given canvas width and height.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Point point = Projection.transform(new Point(-102.875977, 45.433154), "EPSG:4326", "EPSG:3857")
int zoomLevel = 12
int width = 400
int height = 400
TileCursor tileCursor = mbtiles.tiles(point, zoomLevel, width, height)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 12 # of tiles: 9 Bounds: (-1.1466140192049265E7,5674674.46239233,-1.1436790003844362E7,5704026.226852979,EPSG:3857) Width / # Columns: 3 Height / # Rows: 3 MinX: 876, MinY: 2628, MaxX: 878, MaxY: 2630 Tiles: Tile(x:876, y:2628, z:12) Tile(x:877, y:2628, z:12) Tile(x:878, y:2628, z:12) Tile(x:876, y:2629, z:12) Tile(x:877, y:2629, z:12) Tile(x:878, y:2629, z:12) Tile(x:876, y:2630, z:12) Tile(x:877, y:2630, z:12) Tile(x:878, y:2630, z:12)
Get the tile coordinates from a TileLayer by Bounds and Grid
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(20.798492,36.402494,22.765045,37.223768, "EPSG:4326").reproject("EPSG:3857")
Grid grid = mbtiles.pyramid.grid(10)
Map<String, Integer> coords = mbtiles.getTileCoordinates(bounds, grid)
println "Min X = ${coords.minX}"
println "Min Y = ${coords.minY}"
println "Max X = ${coords.maxX}"
println "Max Y = ${coords.maxY}"
Min X = 571 Min Y = 623 Max X = 576 Max Y = 626
Get a Layer from a TileLayer representing the outline of the Tiles in the TileCursor.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Layer layer = mbtiles.getLayer(mbtiles.tiles(1))

id | z | x | y |
---|---|---|---|
0 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
2 |
1 |
0 |
1 |
3 |
1 |
1 |
1 |
Using Tile Layers
Get a TileLayer and make sure it is closed when done.
File file = new File("src/main/resources/tiles.mbtiles")
TileLayer.withTileLayer(new MBTiles(file)) { TileLayer tileLayer ->
println tileLayer.name
println tileLayer.proj
println tileLayer.bounds
}
countries EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857)
Get Tile Layer from a Map
Get an MBTiles TileLayer from a Map
TileLayer mbtiles = TileLayer.getTileLayer([type:'mbtiles', file: 'src/main/resources/tiles.mbtiles'])
println "${mbtiles.name} ${mbtiles.proj} ${mbtiles.bounds} ${mbtiles.pyramid}"
countries EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Get an GeoPackage TileLayer from a Map
TileLayer geopackage = TileLayer.getTileLayer([type: 'geopackage', name: 'world', file: 'src/main/resources/tiles.gpkg'])
println "${geopackage.name} ${geopackage.proj} ${geopackage.bounds} ${geopackage.pyramid}"
world EPSG:4326 (-179.99,-89.99,179.99,89.99,EPSG:4326) geoscript.layer.Pyramid(proj:EPSG:4326, bounds:(-179.99,-89.99,179.99,89.99,EPSG:4326), origin:TOP_LEFT, tileWidth:256, tileHeight:256)
Get an TMS TileLayer from a Map
TileLayer tms = TileLayer.getTileLayer([type: 'tms', file: 'src/main/resources/tms', format: 'png', pyramid: 'globalmercator'])
println "${tms.name} ${tms.proj} ${tms.bounds} ${tms.pyramid}"
tms EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Get an OSM TileLayer from a Map
TileLayer osm = TileLayer.getTileLayer([type: 'osm', url: 'http://a.tile.openstreetmap.org'])
println "${osm.name} ${osm.proj} ${osm.bounds} ${osm.pyramid}"
OSM EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:TOP_LEFT, tileWidth:256, tileHeight:256)
Get an PBF Vector TileLayer from a Map
TileLayer pbf = TileLayer.getTileLayer([type: 'vectortiles', name: 'world', file: 'src/main/resources/pbf', format: 'pbf', pyramid: 'GlobalMercator'])
println "${pbf.name} ${pbf.proj} ${pbf.bounds} ${pbf.pyramid}"
world EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Get an UTF TileLayer from a Map
TileLayer utf = TileLayer.getTileLayer([type: 'utfgrid', file: 'src/main/resources/utf'])
println "${utf.name} ${utf.proj} ${utf.bounds} ${utf.pyramid}"
utf EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:TOP_LEFT, tileWidth:256, tileHeight:256)
Get Tile Layer from a String
Get an MBTiles TileLayer from a String
TileLayer mbtiles = TileLayer.getTileLayer("type=mbtiles file=src/main/resources/tiles.mbtiles")
println "${mbtiles.name} ${mbtiles.proj} ${mbtiles.bounds} ${mbtiles.pyramid}"
countries EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Get an GeoPackage TileLayer from a String
TileLayer geopackage = TileLayer.getTileLayer("type=geopackage name=world file=src/main/resources/tiles.gpkg")
println "${geopackage.name} ${geopackage.proj} ${geopackage.bounds} ${geopackage.pyramid}"
world EPSG:4326 (-179.99,-89.99,179.99,89.99,EPSG:4326) geoscript.layer.Pyramid(proj:EPSG:4326, bounds:(-179.99,-89.99,179.99,89.99,EPSG:4326), origin:TOP_LEFT, tileWidth:256, tileHeight:256)
Get an TMS TileLayer from a String
TileLayer tms = TileLayer.getTileLayer("type=tms file=src/main/resources/tms format=png pyramid=globalmercator")
println "${tms.name} ${tms.proj} ${tms.bounds} ${tms.pyramid}"
tms EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Get an OSM TileLayer from a String
TileLayer osm = TileLayer.getTileLayer("type=osm url=http://a.tile.openstreetmap.org")
println "${osm.name} ${osm.proj} ${osm.bounds} ${osm.pyramid}"
OSM EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:TOP_LEFT, tileWidth:256, tileHeight:256)
Get an PBF Vector TileLayer from a String
TileLayer pbf = TileLayer.getTileLayer("type=vectortiles name=world file=src/main/resources/pbf format=pbf pyramid=GlobalMercator")
println "${pbf.name} ${pbf.proj} ${pbf.bounds} ${pbf.pyramid}"
world EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:BOTTOM_LEFT, tileWidth:256, tileHeight:256)
Get an UTF TileLayer from a String
TileLayer utf = TileLayer.getTileLayer("type=utfgrid file=src/main/resources/utf")
println "${utf.name} ${utf.proj} ${utf.bounds} ${utf.pyramid}"
utf EPSG:3857 (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857), origin:TOP_LEFT, tileWidth:256, tileHeight:256)
TileRenderer
TileRenderers know how to create a Tile for a given Bounds. GeoScript has TileRenderer for creating images, vector tiles, and utfgrids.
Get default TileRenderer
Get a default TileRenderer for a TileLayer
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
TileLayer tileLayer = TileLayer.getTileLayer([type:'mbtiles', file: 'target/countries.mbtiles'])
TileRenderer tileRenderer = TileLayer.getTileRenderer(tileLayer, [ocean, countries])
Pyramid pyramid = tileLayer.pyramid
Tile tile = tileLayer.get(0,0,0)
Bounds bounds = pyramid.bounds(tile)
tile.data = tileRenderer.render(bounds)
tileLayer.put(tile)

ImageTileRenderer
Use an ImageTileRenderer to create an image Tile.
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
TileLayer tileLayer = TileLayer.getTileLayer([type:'mbtiles', file: 'target/countries.mbtiles'])
ImageTileRenderer tileRenderer = new ImageTileRenderer(tileLayer, [ocean, countries])
Pyramid pyramid = tileLayer.pyramid
Tile tile = tileLayer.get(0,0,0)
Bounds bounds = pyramid.bounds(tile)
tile.data = tileRenderer.render(bounds)
tileLayer.put(tile)

RasterTileRenderer
Use an RasterTileRenderer to create a image Tiles from a single Raster.
File dir = new File("target/earthtiles")
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
TileLayer tileLayer = new TMS("Earth", "png", dir, pyramid)
Format format = new GeoTIFF(new File('src/main/resources/earth.tif'))
Raster raster = format.read()
// Resize and Reproject Raster to Web Mercator
Projection latLonProj = new Projection("EPSG:4326")
Projection mercatorProj = new Projection("EPSG:3857")
Bounds latLonBounds = new Bounds(-179.99, -85.0511, 179.99, 85.0511, latLonProj)
Raster webMercatorRaster = raster.resample(bbox: latLonBounds).reproject(mercatorProj)
RasterTileRenderer tileRenderer = new RasterTileRenderer(webMercatorRaster)
GeneratingTileLayer generatingTileLayer = new GeneratingTileLayer(tileLayer, tileRenderer)
Tile tile = generatingTileLayer.get(0, 0, 0)

VectorTileRenderer
Use an VectorTileRenderer to create a Vector Tile.
Workspace workspace = new Directory("src/main/resources/shapefiles")
Layer countries = workspace.get("countries")
File directory = new File("target/country_geojson_tiles")
directory.mkdir()
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
VectorTiles tileLayer = new VectorTiles(
"countries",
directory,
pyramid,
"geojson"
)
GeoJSONWriter writer = new GeoJSONWriter()
VectorTileRenderer tileRenderer = new VectorTileRenderer(writer, countries, [countries.schema.get("NAME")])
Tile tile = tileLayer.get(0,0,0)
Bounds bounds = pyramid.bounds(tile)
tile.data = tileRenderer.render(bounds)
tileLayer.put(tile)
{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[180,-16.0671],[180,-16.5552],[179.3641,-16.8014],[178.7251,-17.012],[178.5968,-16.6392],[179.0966,-16.434],[179.4135,-16.3791],[180,-16.0671]]],[[[178.1256,-17.5048],[178.3736,-17.3399],[178.7181,-17.6285],[178.5527,-18.1506],[177.9327,-18.288],[177.3815,-18.1643],[177.285,-17.7246],[177.6709,-17.3811],[178.1256,-17.5048]]],[[[-179.7933,-16.0209],[-179.9174,-16.5018],[-180,-16.5552],[-180,-16.0671],[-179.7933,-16.0209]]]]},"properties":{"NAME":"Fiji"},"id":"fid--1c8a8332_18ba0aee183_-3632"},{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[33.9037,-0.95],[34.0726,-1.0598],[37.6987,-3.097],[37.7669,-3.6771],[39.2022,-4.6768],[38.7405,-5.9089],[38.7998,-6.4757],[39.44,-6.84],[39.47,-7.1],[39.1947,-7.7039],[39.252,-8.0078],[39.1865,-8.4855],[39.5357,-9.1124],[39.
PbfVectorTileRenderer
Use an PbfVectorTileRenderer to create a Vector Tile.
Workspace workspace = new Directory("src/main/resources/shapefiles")
Layer countries = workspace.get("countries")
File directory = new File("target/country_pbf_tiles")
directory.mkdir()
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
pyramid.origin = Pyramid.Origin.TOP_LEFT
VectorTiles tileLayer = new VectorTiles(
"countries",
directory,
pyramid,
"pbf"
)
PbfVectorTileRenderer tileRenderer = new PbfVectorTileRenderer(countries, [countries.schema.get("NAME")])
Tile tile = tileLayer.get(0,0,0)
Bounds bounds = pyramid.bounds(tile)
tile.data = tileRenderer.render(bounds)
tileLayer.put(tile)
UTFGridTileRenderer
Use an UTFGridTileRenderer to create a UTFGrid Tile.
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
File directory = new File("target/countryUtfGrid")
directory.mkdir()
UTFGrid tileLayer = new UTFGrid(directory)
UTFGridTileRenderer tileRenderer = new UTFGridTileRenderer(tileLayer, countries, [countries.schema.get("NAME")])
Pyramid pyramid = tileLayer.pyramid
Tile tile = tileLayer.get(0,0,0)
Bounds bounds = pyramid.bounds(tile)
tile.data = tileRenderer.render(bounds)
tileLayer.put(tile)
{ "grid": [ " ", " ", " ", " ! ### ", " !!!!! ##### ", " !!!!!######### ", " !!!!!!######### $ ", " !!!!!######### %%% $ ", " ! !!! ######### %% $$ ", " ! !! !!########## %% $ ", " ! !!!!! ######### % $ $$ ", " !!!!!!! #######
TileCursor
A TileCursor is a way to get a collection of Tiles from a TileLayer.
Get a TileCursor with all of the Tiles from a TileLayer in a zoom level.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
long zoomLevel = 1
TileCursor tileCursor = new TileCursor(mbtiles, zoomLevel)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 1 # of tiles: 4 Bounds: (-2.003639514788131E7,-2.0037471205137067E7,2.003639514788131E7,2.003747120513706E7,EPSG:3857) Width / # Columns: 2 Height / # Rows: 2 MinX: 0, MinY: 0, MaxX: 1, MaxY: 1 Tiles: Tile(x:0, y:0, z:1) Tile(x:1, y:0, z:1) Tile(x:0, y:1, z:1) Tile(x:1, y:1, z:1)
Get a TileCursor with Tiles from a TileLayer in a zoom level between min and max x and y coordinates.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
long zoomLevel = 4
long minX = 2
long minY = 4
long maxX = 5
long maxY = 8
TileCursor tileCursor = new TileCursor(mbtiles, zoomLevel, minX, minY, maxX, maxY)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 4 # of tiles: 20 Bounds: (-1.5027296360910982E7,-1.0018735602568535E7,-5009098.786970327,2504683.900642129,EPSG:3857) Width / # Columns: 4 Height / # Rows: 5 MinX: 2, MinY: 4, MaxX: 5, MaxY: 8 Tiles: Tile(x:2, y:4, z:4) Tile(x:3, y:4, z:4) Tile(x:4, y:4, z:4) Tile(x:5, y:4, z:4) Tile(x:2, y:5, z:4) Tile(x:3, y:5, z:4) Tile(x:4, y:5, z:4) Tile(x:5, y:5, z:4) Tile(x:2, y:6, z:4) Tile(x:3, y:6, z:4) Tile(x:4, y:6, z:4) Tile(x:5, y:6, z:4) Tile(x:2, y:7, z:4) Tile(x:3, y:7, z:4) Tile(x:4, y:7, z:4) Tile(x:5, y:7, z:4) Tile(x:2, y:8, z:4) Tile(x:3, y:8, z:4) Tile(x:4, y:8, z:4) Tile(x:5, y:8, z:4)
Get a TileCursor with Tiles from a TileLayer in a zoom level for a given Bounds.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(-102.875977, 45.433154, -96.481934, 48.118434, "EPSG:4326").reproject("EPSG:3857")
int zoomLevel = 8
TileCursor tileCursor = new TileCursor(mbtiles, bounds, zoomLevel)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 8 # of tiles: 24 Bounds: (-1.1583540944868883E7,5635538.7764447965,-1.0644334922311947E7,6261709.751605326,EPSG:3857) Width / # Columns: 6 Height / # Rows: 4 MinX: 54, MinY: 164, MaxX: 59, MaxY: 167 Tiles: Tile(x:54, y:164, z:8) Tile(x:55, y:164, z:8) Tile(x:56, y:164, z:8) Tile(x:57, y:164, z:8) Tile(x:58, y:164, z:8) Tile(x:59, y:164, z:8) Tile(x:54, y:165, z:8) Tile(x:55, y:165, z:8) Tile(x:56, y:165, z:8) Tile(x:57, y:165, z:8) Tile(x:58, y:165, z:8) Tile(x:59, y:165, z:8) Tile(x:54, y:166, z:8) Tile(x:55, y:166, z:8) Tile(x:56, y:166, z:8) Tile(x:57, y:166, z:8) Tile(x:58, y:166, z:8) Tile(x:59, y:166, z:8) Tile(x:54, y:167, z:8) Tile(x:55, y:167, z:8) Tile(x:56, y:167, z:8) Tile(x:57, y:167, z:8) Tile(x:58, y:167, z:8) Tile(x:59, y:167, z:8)
Get a TileCursor with Tiles from a TileLayer in a zoom level for a given x and y resolution.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(-124.73142200000001, 24.955967, -66.969849, 49.371735, "EPSG:4326").reproject("EPSG:3857")
double resolutionX = bounds.width / 400
double resolutionY = bounds.height / 300
TileCursor tileCursor = new TileCursor(mbtiles, bounds, resolutionX, resolutionY)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 4 # of tiles: 8 Bounds: (-1.5027296360910982E7,2504683.9006421305,-5009098.786970327,7514051.701926393,EPSG:3857) Width / # Columns: 4 Height / # Rows: 2 MinX: 2, MinY: 9, MaxX: 5, MaxY: 10 Tiles: Tile(x:2, y:9, z:4) Tile(x:3, y:9, z:4) Tile(x:4, y:9, z:4) Tile(x:5, y:9, z:4) Tile(x:2, y:10, z:4) Tile(x:3, y:10, z:4) Tile(x:4, y:10, z:4) Tile(x:5, y:10, z:4)
Get a TileCursor with Tiles from a TileLayer within a Bounds for a given canvas width and height.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(-102.875977, 45.433154, -96.481934, 48.118434, "EPSG:4326").reproject("EPSG:3857")
int width = 400
int height = 400
TileCursor tileCursor = new TileCursor(mbtiles, bounds, width, height)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 7 # of tiles: 6 Bounds: (-1.1583540944868883E7,5635538.7764447965,-1.0644334922311947E7,6261709.751605329,EPSG:3857) Width / # Columns: 3 Height / # Rows: 2 MinX: 27, MinY: 82, MaxX: 29, MaxY: 83 Tiles: Tile(x:27, y:82, z:7) Tile(x:28, y:82, z:7) Tile(x:29, y:82, z:7) Tile(x:27, y:83, z:7) Tile(x:28, y:83, z:7) Tile(x:29, y:83, z:7)
Get a TileCursor with Tiles from a TileLayer around a Point at a given zoom level for a given canvas width and height.
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)
Bounds bounds = new Bounds(-102.875977, 45.433154, -96.481934, 48.118434, "EPSG:4326").reproject("EPSG:3857")
int width = 400
int height = 400
TileCursor tileCursor = new TileCursor(mbtiles, bounds, width, height)
println "Zoom Level: ${tileCursor.z}"
println "# of tiles: ${tileCursor.size}"
println "Bounds: ${tileCursor.bounds}"
println "Width / # Columns: ${tileCursor.width}"
println "Height / # Rows: ${tileCursor.height}"
println "MinX: ${tileCursor.minX}, MinY: ${tileCursor.minY}, MaxX: ${tileCursor.maxX}, MaxY: ${tileCursor.maxY}"
println "Tiles:"
tileCursor.each { Tile t ->
println t
}
Zoom Level: 7 # of tiles: 6 Bounds: (-1.1583540944868883E7,5635538.7764447965,-1.0644334922311947E7,6261709.751605329,EPSG:3857) Width / # Columns: 3 Height / # Rows: 2 MinX: 27, MinY: 82, MaxX: 29, MaxY: 83 Tiles: Tile(x:27, y:82, z:7) Tile(x:28, y:82, z:7) Tile(x:29, y:82, z:7) Tile(x:27, y:83, z:7) Tile(x:28, y:83, z:7) Tile(x:29, y:83, z:7)
TMS
Access a TileLayer from an TMS directory
File dir = new File("src/main/resources/tms")
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
TMS tms = new TMS(
"world", (1)
"png", (2)
dir, (3)
pyramid (4)
)
1 | Name |
2 | Image type |
3 | Directory |
4 | Pyramid |

MBTiles
Access a TileLayer from an MBTiles file
File file = new File("src/main/resources/tiles.mbtiles")
MBTiles mbtiles = new MBTiles(file)

DBTiles
Access a TileLayer from an DBTiles H2 database
File file = new File("src/main/resources/h2dbtiles/world_tiles.db")
DBTiles dbtiles = new DBTiles("jdbc:h2:${file}","org.h2.Driver", "World", "World wide tiles")

GeoPackage
Access a TileLayer with a Global Geodetic Pyramid from an GeoPackage file
File file = new File("src/main/resources/data.gpkg")
geoscript.layer.GeoPackage geopackage = new geoscript.layer.GeoPackage(file, "world")

Access a TileLayer with a Global Mercator Pyramid from an GeoPackage file
File file = new File("src/main/resources/data.gpkg")
geoscript.layer.GeoPackage geopackage = new geoscript.layer.GeoPackage(file, "world_mercator")

UTFGrid
Access a TileLayer from an UTFGrid directory
File dir = new File("src/main/resources/utf")
UTFGrid utfGrid = new UTFGrid(dir)

VectorTiles
Access a TileLayer from an VectorTiles directory
File dir = new File("src/main/resources/pbf")
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
VectorTiles vectorTiles = new VectorTiles(
"World", (1)
dir, (2)
pyramid, (3)
"pbf" (4)
)
1 | Name |
2 | Directory |
3 | Pyramid |
4 | Type |

Access a TileLayer from an VectorTiles MBTiles file
File file = new File("src/main/resources/vectortiles.mbtiles")
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
VectorTiles vectorTiles = new VectorTiles(
"World", (1)
file, (2)
pyramid, (3)
"pbf" (4)
)
1 | Name |
2 | MBTiles File |
3 | Pyramid |
4 | Type |

Generating TileLayer
A GeneratingTileLayer can create tiles on demand when they are accessed.
File dir = new File("target/worldtiles")
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
TileLayer tileLayer = new TMS("World", "png", dir, pyramid)
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
TileRenderer tileRenderer = new ImageTileRenderer(tileLayer, [ocean, countries])
GeneratingTileLayer generatingTileLayer = new GeneratingTileLayer(tileLayer, tileRenderer)
Tile tile = generatingTileLayer.get(0, 0, 0)

OSM
Create a TileLayer for OSM tiles.
OSM osm = new OSM()

Create a TileLayer for OSM tiles with custom urls.
OSM osm = new OSM("OSM", [
"http://a.tile.openstreetmap.org",
"http://b.tile.openstreetmap.org",
"http://c.tile.openstreetmap.org"
])

Carto Recipes
The Carto classes are in the geoscript.carto package.
The Carto package contains classes for creating cartographic documents. All items are added to the document with x and y coordinates whose origin is the upper left and width and a height.
Items
Adding a Map
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(20, 20, pageSize.width - 40, pageSize.height - 40).map(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
map |
geoscript.render.Map |
The Map to display |
Adding an Overview Map
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-166.436348,6.574916,-12.451973,60.715022, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
Map overViewMap = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(20, 20, pageSize.width - 40, pageSize.height - 40).map(map))
.rectangle(new RectangleItem(20, 20, pageSize.width - 40, pageSize.height - 40))
.overViewMap(new OverviewMapItem(40, pageSize.height - 240, 200, 200)
.linkedMap(map)
.overviewMap(overViewMap)
.zoomIntoBounds(false)
)
.rectangle(new RectangleItem(40, pageSize.height - 240, 200,200))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
overviewMap |
geoscript.render.Map |
The overview Map |
linkedMap |
geoscript.render.Map |
The Map the overview Map is linked to |
areaStyle |
geoscript.style.Style |
The GeoScript style to display the rectangle |
zoomIntoBounds |
boolean |
Whether to zoom into the bounds of the linked Map or not |
scaleFactor |
double |
The scale factor for expanding the linked Map Bounds |
Adding a Text
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.text(new TextItem(20,20, pageSize.width - 40, 60)
.text("World Map")
.font(new Font("Arial", Font.BOLD, 42))
.verticalAlign(VerticalAlign.MIDDLE)
.horizontalAlign(HorizontalAlign.CENTER)
)
.map(new MapItem(20, 80, pageSize.width - 40, pageSize.height - 100).map(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
text |
String |
The text to display |
color |
java.awt.Color |
The text Color |
font |
java.awt.Font |
The text font |
horizontalAlign |
HorizontalAlign (LEFT, CENTER, RIGHT) |
The horizontal alignment |
verticalAlign |
VerticalAlign (TOP, MIDDLE, BOTTOM) |
The vertical alignment |
Adding a Rectangle
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.rectangle(new RectangleItem(10,10, pageSize.width - 20, pageSize.height - 20))
.rectangle(new RectangleItem(20,20, pageSize.width - 40, 60))
.rectangle(new RectangleItem(20,90, pageSize.width - 40, pageSize.height - 110))
.text(new TextItem(20,20, pageSize.width - 40, 60)
.text("World Map")
.font(new Font("Arial", Font.BOLD, 32))
.verticalAlign(VerticalAlign.MIDDLE)
.horizontalAlign(HorizontalAlign.CENTER)
)
.map(new MapItem(30, 100, pageSize.width - 60, pageSize.height - 120).map(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
strokeColor |
java.awt.Color |
The outline Color |
fillColor |
java.awt.Color |
The fill Color |
strokeWidth |
float |
The width of the stroke |
Adding a North Arrow
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(20, 20, pageSize.width - 40, pageSize.height - 40).map(map))
.northArrow(new NorthArrowItem(pageSize.width - 60, pageSize.height - 100, 40, 80)
.font(new Font("Arial", Font.BOLD, 24))
.drawText(true))
.build(outputStream)
}

Adding a NESW North Arrow
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(20, 20, pageSize.width - 40, pageSize.height - 40).map(map))
.northArrow(new NorthArrowItem(pageSize.width - 100, pageSize.height - 100, 80, 80)
.style(NorthArrowStyle.NorthEastSouthWest)
.font(new Font("Arial", Font.BOLD, 14))
.drawText(true))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
fillColor1 |
java.awt.Color |
The first Fill Color |
strokeColor1 |
java.awt.Color |
The first Stroke Color |
fillColor2 |
java.awt.Color |
The second Fill Color |
strokeColor2 |
java.awt.Color |
The second Stroke Color |
strokeWidth |
float |
The width of the stroke |
drawText |
boolean |
Whether to draw text (n,s,e,w) or not |
font |
java.awt.Font |
The Font for the text |
textColor |
java.awt.Color |
The text Color |
style |
NorthArrowStyle |
The North Arrow style (North or NorthEastSouthWest) |
Adding a Legend
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Layer places = workspace.get("places")
places.style = new Shape("red", 8, "star")
Layer rivers = workspace.get("rivers")
rivers.style = new Stroke("blue", 1)
Map map = new Map(
layers: [ocean, countries, rivers, places],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(220, 20, pageSize.width - 240, pageSize.height - 40).map(map))
.legend(new LegendItem(20, 20, 200, pageSize.height - 40).addMap(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
backgroudColor |
java.awt.Color |
The background Color |
title |
String |
The legend title |
titleFont |
java.awt.Font |
The title Font |
titleColor |
java.awt.Color |
The title Color |
textFont |
java.awt.Font |
The text Font |
textColor |
java.awt.Color |
The text Color |
entries |
List of LegendEntry instances |
Legend entries |
legendEntryWidth |
int |
The width of individual entries |
legendEntryHeight |
int |
The height of individual entries |
gapBetweenEntries |
int |
The gap between entries |
numberFormat |
String |
The number format (#.##) |
Adding a Date
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.text(new TextItem(20,15, pageSize.width - 40, 60)
.text("World Map")
.font(new Font("Arial", Font.BOLD, 42))
.verticalAlign(VerticalAlign.TOP)
.horizontalAlign(HorizontalAlign.CENTER)
)
.dateText(new DateTextItem(20,58, pageSize.width - 40, 20)
.font(new Font("Arial", Font.ITALIC, 18))
.verticalAlign(VerticalAlign.BOTTOM)
.horizontalAlign(HorizontalAlign.CENTER)
)
.map(new MapItem(20, 80, pageSize.width - 40, pageSize.height - 100).map(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
format |
String |
The date format (MM/dd/yyyy) |
date |
Date |
The Date to display |
color |
java.awt.Color |
The text Color |
font |
java.awt.Font |
The text Font |
horizontalAlign |
HorizontalAlign |
The horizontal alingment of the text |
verticalAlign |
VerticalAlign |
The vertical alingment of the text |
Adding Scale Text
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.text(new TextItem(20,15, pageSize.width - 40, 60)
.text("World Map")
.font(new Font("Arial", Font.BOLD, 42))
.verticalAlign(VerticalAlign.TOP)
.horizontalAlign(HorizontalAlign.CENTER)
)
.scaleText(new ScaleTextItem(20,58, pageSize.width - 40, 20)
.map(map)
.format("#")
.prefixText("Scale: ")
.font(new Font("Arial", Font.ITALIC, 18))
.verticalAlign(VerticalAlign.BOTTOM)
.horizontalAlign(HorizontalAlign.CENTER)
)
.map(new MapItem(20, 80, pageSize.width - 40, pageSize.height - 100).map(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
map |
geoscript.render.Map |
The Map to get the scale from |
color |
java.awt.Color |
The text Color |
font |
java.awt.Font |
The text Font |
horizontalAlign |
HorizontalAlign |
The horizontal alingment of the text |
verticalAlign |
VerticalAlign |
The vertical alingment of the text |
format |
String |
The number format for displaying the scale |
prefixText |
String |
The text to display before the scale (Scale: …) |
Adding Scale Bar
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.text(new TextItem(20,15, pageSize.width - 40, 60)
.text("World Map")
.font(new Font("Arial", Font.BOLD, 42))
.verticalAlign(VerticalAlign.TOP)
.horizontalAlign(HorizontalAlign.CENTER)
)
.map(new MapItem(20, 80, pageSize.width - 40, pageSize.height - 100).map(map))
.scaleBar(new ScaleBarItem(20,pageSize.height - 40, 300, 20)
.map(map)
.units(ScaleBarItem.Units.METRIC)
.barStrokeColor(Color.BLACK)
.barStrokeWidth(1.4f)
.strokeColor(Color.DARK_GRAY)
.strokeWidth(1.0f)
.textColor(Color.DARK_GRAY)
)
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
map |
geoscript.render.Map |
The Map to get the scale from |
strokeColor |
java.awt.Color |
The stroke Color |
fillColor |
java.awt.Color |
The fill Color |
strokeWidth |
float |
The stroke width |
barStrokeColor |
java.awt.Color |
The bar stroke Color |
barStrokeWidth |
float |
The bar stroke width |
font |
java.awt.Font |
The text Font |
textColor |
java.awt.Color |
The text Color |
border |
int |
The border padding |
units |
Units |
The units (metric or us) |
Adding a Line
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.text(new TextItem(20,20, pageSize.width - 40, 60)
.text("World Map")
.font(new Font("Arial", Font.BOLD, 42))
.verticalAlign(VerticalAlign.MIDDLE)
.horizontalAlign(HorizontalAlign.CENTER)
)
.line(new LineItem(20, 70, pageSize.width - 40, 1)
.strokeWidth(2)
.strokeColor(Color.DARK_GRAY)
)
.map(new MapItem(20, 80, pageSize.width - 40, pageSize.height - 100).map(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
map |
geoscript.render.Map |
The Map to get the scale from |
strokeColor |
java.awt.Color |
The stroke Color |
strokeWidth |
float |
The stroke width |
Adding a Grid
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.grid(new GridItem(0,0,pageSize.width, pageSize.height)
.size(20)
.strokeColor(Color.GRAY)
.strokeWidth(1.0)
)
.text(new TextItem(20,20, pageSize.width - 40, 60)
.text("World Map")
.font(new Font("Arial", Font.BOLD, 42))
.verticalAlign(VerticalAlign.MIDDLE)
.horizontalAlign(HorizontalAlign.CENTER)
)
.map(new MapItem(20, 80, pageSize.width - 40, pageSize.height - 100).map(map))
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
size |
int |
The cell size |
strokeColor |
java.awt.Color |
The stroke Color |
strokeWidth |
float |
The stroke width |
Adding a Paragraph
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(20, 20, pageSize.width - 40, pageSize.height - 100).map(map))
.paragraph(new ParagraphItem(20, pageSize.height - 60, pageSize.width - 40, 60)
.font(new Font("Arial", Font.PLAIN, 12))
.color(Color.BLACK)
.text("""Natural Earth is a public domain map dataset available at 1:10m, 1:50m, and 1:110 million scales.
Featuring tightly integrated vector and raster data, with Natural Earth you can make a variety of visually pleasing,
well-crafted maps with cartography or GIS software.
""")
)
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
text |
String |
The paragraph text |
font |
java.awt.Font |
The text Font |
color |
java.awt.Color |
The text Color |
Adding an Image
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(20, 20, pageSize.width - 40, pageSize.height - 40).map(map))
.image(new ImageItem(pageSize.width - 100, pageSize.height - 100, 80, 80)
.path(new File("src/main/resources/image.png"))
)
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
path |
File or URL |
The source path of the image |
Adding a Table
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer states = workspace.get("states")
states.style = new SLDReader().read(new File('src/main/resources/states.sld'))
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries, states],
bounds: new Bounds(-135.225466,36.256870,-95.850466,50.746340, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
PageSize pageSize = PageSize.LETTER_LANDSCAPE
CartoFactories.findByName("png")
.create(pageSize)
.rectangle(new RectangleItem(0, 0, pageSize.width - 1, pageSize.height - 1)
.fillColor(Color.WHITE)
)
.map(new MapItem(20, 20, pageSize.width - 40, pageSize.height - 140).map(map))
.table(new TableItem(20, pageSize.height - 100, pageSize.width - 40, 80)
.columns(["Name", "Abbreviation"])
.row([[Name: "Washington", Abbreviation: "WA"]])
.row([[Name: "Oregon", Abbreviation: "OR"]])
.row([[Name: "California", Abbreviation: "CA"]])
)
.build(outputStream)
}

Property | Type | Description |
---|---|---|
x |
int |
The number of pixels from left |
y |
int |
The number of pixels from top |
width |
int |
The width of the item in pixels |
height |
int |
The height of the item in pixels |
columns |
List of Strings |
The column names |
row |
A Maps of values |
One row of values where the keys are the column names. |
rows |
A List of Maps |
The data as a List of Maps where the keys are the column names. |
columnRowStyle |
TableItem.RowStyle |
backGroudColor, font, textColor, strokeColor for columns |
evenRowStyle |
TableItem.RowStyle |
backGroudColor, font, textColor, strokeColor for even rows |
oddRowStyle |
TableItem.RowStyle |
backGroudColor, font, textColor, strokeColor for odd rows |
Builders
CartoBuilders write cartographic documents to different formats. Images, PDFs, and SVGs are currently supported.
ImageCartoBuilder
The ImageCartoBuilder can produce PNG or JPEG images.
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
new ImageCartoBuilder(PageSize.LETTER_LANDSCAPE, ImageCartoBuilder.ImageType.PNG)
.rectangle(new RectangleItem(0, 0, 792, 612).strokeColor(Color.WHITE).fillColor(Color.WHITE))
.rectangle(new RectangleItem(10, 10, 772, 592))
.rectangle(new RectangleItem(20, 20, 752, 80))
.text(new TextItem(30, 50, 200, 20).text("Map Title").font(new Font("Arial", Font.BOLD, 36)))
.dateText(new DateTextItem(30, 85, 200, 10).font(new Font("Arial", Font.ITALIC, 14)))
.scaleText(new ScaleTextItem(150, 85, 200, 10).map(map).font(new Font("Arial", Font.ITALIC, 14)))
.paragraph(new ParagraphItem(250, 30, 380, 70).text("""Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
""").font(new Font("Arial", Font.PLAIN, 8)))
.line(new LineItem(710, 30, 1, 60))
.image(new ImageItem(640, 30, 60, 60).path(new File(getClass().getClassLoader().getResource("image.png").toURI())))
.northArrow(new NorthArrowItem(720, 30, 40, 60))
.map(new MapItem(20, 110, 752, 480).map(map))
.rectangle(new RectangleItem(20, 110, 752, 480))
.build(outputStream)
}

PdfCartoBuilder
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.pdf")
file.withOutputStream { OutputStream outputStream ->
new PdfCartoBuilder(PageSize.LETTER_LANDSCAPE)
.rectangle(new RectangleItem(0, 0, 792, 612).strokeColor(Color.WHITE).fillColor(Color.WHITE))
.rectangle(new RectangleItem(10, 10, 772, 592))
.rectangle(new RectangleItem(20, 20, 752, 80))
.text(new TextItem(30, 50, 200, 20).text("Map Title").font(new Font("Arial", Font.BOLD, 36)))
.dateText(new DateTextItem(30, 85, 200, 10).font(new Font("Arial", Font.ITALIC, 14)))
.scaleText(new ScaleTextItem(150, 85, 200, 10).map(map).font(new Font("Arial", Font.ITALIC, 14)))
.paragraph(new ParagraphItem(250, 30, 380, 70).text("""Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
""").font(new Font("Arial", Font.PLAIN, 8)))
.line(new LineItem(710, 30, 1, 60))
.image(new ImageItem(640, 30, 60, 60).path(new File(getClass().getClassLoader().getResource("image.png").toURI())))
.northArrow(new NorthArrowItem(720, 30, 40, 60))
.map(new MapItem(20, 110, 752, 480).map(map))
.rectangle(new RectangleItem(20, 110, 752, 480))
.build(outputStream)
}

SvgCartoBuilder
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File('src/main/resources/countries.sld'))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File('src/main/resources/ocean.sld'))
Map map = new Map(
layers: [ocean, countries],
bounds: new Bounds(-180,-85,180,85, "EPSG:4326").reproject("EPSG:3857"),
projection: new Projection("EPSG:3857")
)
File file = new File("map.svg")
file.withOutputStream { OutputStream outputStream ->
new SvgCartoBuilder(PageSize.LETTER_LANDSCAPE)
.rectangle(new RectangleItem(0, 0, 792, 612).strokeColor(Color.WHITE).fillColor(Color.WHITE))
.rectangle(new RectangleItem(10, 10, 772, 592))
.rectangle(new RectangleItem(20, 20, 752, 80))
.text(new TextItem(30, 50, 200, 20).text("Map Title").font(new Font("Arial", Font.BOLD, 36)))
.dateText(new DateTextItem(30, 85, 200, 10).font(new Font("Arial", Font.ITALIC, 14)))
.scaleText(new ScaleTextItem(150, 85, 200, 10).map(map).font(new Font("Arial", Font.ITALIC, 14)))
.paragraph(new ParagraphItem(250, 30, 380, 70).text("""Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
""").font(new Font("Arial", Font.PLAIN, 8)))
.line(new LineItem(710, 30, 1, 60))
.image(new ImageItem(640, 30, 60, 60).path(new File(getClass().getClassLoader().getResource("image.png").toURI())))
.northArrow(new NorthArrowItem(720, 30, 40, 60))
.map(new MapItem(20, 110, 752, 480).map(map))
.rectangle(new RectangleItem(20, 110, 752, 480))
.build(outputStream)
}

Reading CartoBuilders
The IO module can read a CartoBuilder from JSON or XML documents.
Finding Carto Readers
List<CartoReader> readers = CartoReaders.list()
readers.each { CartoReader reader ->
println reader.name
}
json xml yaml
CartoReader reader = CartoReaders.find("json")
println reader.name
json
JSON
String json = """{
"type": "png",
"width": 400,
"height": 400,
"items": [
{
"x": 0,
"y": 0,
"width": 400,
"height": 400,
"type": "rectangle",
"fillColor": "white",
"strokeColor": "white"
},
{
"x": 10,
"y": 10,
"width": 380,
"height": 380,
"type": "rectangle"
},
{
"x": 20,
"y": 20,
"width": 360,
"height": 360,
"type": "map",
"name": "mainMap",
"proj": "EPSG:4326",
"bounds": {
"minX": -135.911779,
"minY": 36.993573,
"maxX": -96.536779,
"maxY": 51.405899
},
"layers": [
{
"layertype": "layer",
"dbtype": "geopkg",
"database": "src/main/resources/data.gpkg",
"layername": "ocean",
"style": "src/main/resources/ocean.sld"
},
{
"layertype": "layer",
"dbtype": "geopkg",
"database": "src/main/resources/data.gpkg",
"layername": "countries",
"style": "src/main/resources/countries.sld"
},
{
"layertype": "layer",
"dbtype": "geopkg",
"database": "src/main/resources/data.gpkg",
"layername": "states",
"style": "src/main/resources/states.sld"
}
]
},
{
"x": 20,
"y": 20,
"width": 30,
"height": 40,
"type": "northarrow"
},
{
"x": 260,
"y": 20,
"width": 50,
"height": 200,
"type": "legend",
"map": "mainMap"
},
{
"x": 70,
"y": 20,
"width": 170,
"height": 50,
"type": "text",
"text": "Western US",
"font": {
"name": "Arial",
"style": "BOLD",
"size": 24
},
"horizontalAlign": "CENTER",
"verticalAlign": "MIDDLE"
}
]
}
"""
CartoReader cartoReader = new JsonCartoReader()
CartoBuilder cartoBuilder = cartoReader.read(json)
File file = new File("target/carto_from_json.png")
file.withOutputStream { OutputStream outputStream ->
cartoBuilder.build(outputStream)
}

XML
String json = """<carto>
<type>png</type>
<width>400</width>
<height>400</height>
<items>
<item>
<x>0</x>
<y>0</y>
<width>400</width>
<height>400</height>
<type>rectangle</type>
<fillColor>white</fillColor>
<strokeColor>white</strokeColor>
</item>
<item>
<x>10</x>
<y>10</y>
<width>380</width>
<height>380</height>
<type>rectangle</type>
</item>
<item>
<x>20</x>
<y>20</y>
<width>360</width>
<height>360</height>
<type>map</type>
<name>mainMap</name>
<proj>EPSG:4326</proj>
<bounds>
<minX>-135.911779</minX>
<minY>36.993573</minY>
<maxX>-96.536779</maxX>
<maxY>51.40589</maxY>
</bounds>
<layers>
<layer>
<layertype>layer</layertype>
<dbtype>geopkg</dbtype>
<database>src/main/resources/data.gpkg</database>
<layername>ocean</layername>
<style>src/main/resources/ocean.sld</style>
</layer>
<layer>
<layertype>layer</layertype>
<dbtype>geopkg</dbtype>
<database>src/main/resources/data.gpkg</database>
<layername>countries</layername>
<style>src/main/resources/countries.sld</style>
</layer>
<layer>
<layertype>layer</layertype>
<dbtype>geopkg</dbtype>
<database>src/main/resources/data.gpkg</database>
<layername>states</layername>
<style>src/main/resources/states.sld</style>
</layer>
</layers>
</item>
<item>
<x>20</x>
<y>20</y>
<width>30</width>
<height>40</height>
<type>northarrow</type>
</item>
<item>
<x>260</x>
<y>20</y>
<width>50</width>
<height>200</height>
<type>legend</type>
<map>mainMap</map>
</item>
<item>
<x>70</x>
<y>20</y>
<width>170</width>
<height>50</height>
<type>text</type>
<text>Western US</text>
<font>
<name>Arial</name>
<style>BOLD</style>
<size>24</size>
</font>
<horizontalAlign>CENTER</horizontalAlign>
<verticalAlign>MIDDLE</verticalAlign>
</item>
</items>
</carto>
"""
CartoReader cartoReader = new XmlCartoReader()
CartoBuilder cartoBuilder = cartoReader.read(json)
File file = new File("target/carto_from_xml.png")
file.withOutputStream { OutputStream outputStream ->
cartoBuilder.build(outputStream)
}

YAML
String yaml = """---
type: png
width: 400
height: 400
items:
- x: 0
y: 0
width: 400
height: 400
type: rectangle
fillColor: white
strokeColor: white
- x: 10
y: 10
width: 380
height: 380
type: rectangle
- x: 20
y: 20
width: 360
height: 360
type: map
name: mainMap
proj: EPSG:4326
bounds:
minX: -135.911779
minY: 36.993573
maxX: -96.536779
maxY: 51.405899
layers:
- layertype: layer
dbtype: geopkg
database: src/main/resources/data.gpkg
layername: ocean
style: src/main/resources/ocean.sld
- layertype: layer
dbtype: geopkg
database: src/main/resources/data.gpkg
layername: countries
style: src/main/resources/countries.sld
- layertype: layer
dbtype: geopkg
database: src/main/resources/data.gpkg
layername: states
style: src/main/resources/states.sld
- x: 20
y: 20
width: 30
height: 40
type: northarrow
- x: 260
y: 20
width: 50
height: 200
type: legend
map: mainMap
- x: 70
y: 20
width: 170
height: 50
type: text
text: Western US
font:
name: Arial
style: BOLD
size: 24
horizontalAlign: CENTER
verticalAlign: MIDDLE
"""
CartoReader cartoReader = new YamlCartoReader()
CartoBuilder cartoBuilder = cartoReader.read(yaml)
File file = new File("target/carto_from_yaml.png")
file.withOutputStream { OutputStream outputStream ->
cartoBuilder.build(outputStream)
}
