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"
Library
Maven
<repositories>
<repository>
<id>boundless</id>
<name>Boundless Maven Repository</name>
<url>https://repo.boundlessgeo.com/main</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependency>
<groupId>org.geoscript</groupId>
<artifactId>geoscript-groovy</artifactId>
<version>1.14.0</version>
</dependency>
Gradle
repositories {
maven {
url "https://repo.boundlessgeo.com/main"
}
maven {
url "http://download.osgeo.org/webdav/geotools/"
}
}
dependencies {
compile("org.geoscript:geoscript-groovy:1.14.0")
}
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.4550237920096 47.23410579860605, -122.4348780833765 47.21113402059009, -122.41190630536055 47.19098831195699, -122.38650151145254 47.17401337136692, -122.3590983847198 47.16049964475972, -122.33016580025833 47.15067835574435, -122.30019880260986 47.144717549298825, -122.26971013541258 47.1427192164741, -122.2392214682153 47.144717549298825, -122.20925447056683 47.15067835574435, -122.18032188610536 47.16049964475972, -122.15291875937262 47.17401337136692, -122.12751396546462 47.19098831195699, -122.10454218744866 47.21113402059009, -122.08439647881556 47.23410579860605, -122.06742153822549 47.259510592514054, -122.05390781161829 47.28691371924678, -122.04408652260291 47.31584630370827, -122.0381257161574 47.34581330135674, -122.03612738333267 47.37630196855401, -122.03613281249999 47.37789454155521, -122.0381257161574 47.40679063575128, -122.04408652260291 47.43675763339975, -122.05390781161829 47.46569021786124, -122.06742153822549 47.493093344593966, -122.08439647881556 47.51849813850197, -122.10454218744866 47.54146991651793, -122.12751396546462 47.56161562515103, -122.15291875937262 47.5785905657411, -122.18032188610536 47.5921042923483, -122.20925447056683 47.60192558136367, -122.2392214682153 47.607886387809195, -122.26971013541258 47.60988472063392, -122.30019880260986 47.607886387809195, -122.33016580025833 47.60192558136367, -122.3590983847198 47.5921042923483, -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.4550237920096 47.23410579860605, -122.4348780833765 47.21113402059009, -122.41190630536055 47.19098831195699, -122.38650151145254 47.17401337136692, -122.3590983847198 47.16049964475972, -122.33016580025833 47.15067835574435, -122.30019880260986 47.144717549298825, -122.26971013541258 47.1427192164741, -122.2392214682153 47.144717549298825, -122.20925447056683 47.15067835574435, -122.18032188610536 47.16049964475972, -122.15291875937262 47.17401337136692, -122.12751396546462 47.19098831195699, -122.10454218744866 47.21113402059009, -122.08439647881556 47.23410579860605, -122.06742153822549 47.259510592514054, -122.05390781161829 47.28691371924678, -122.04408652260291 47.31584630370827, -122.0381257161574 47.34581330135674, -122.03612738333267 47.37630196855401, -122.03613281249999 47.37789454155521, -122.0381257161574 47.40679063575128, -122.04408652260291 47.43675763339975, -122.05390781161829 47.46569021786124, -122.06742153822549 47.493093344593966, -122.08439647881556 47.51849813850197, -122.10454218744866 47.54146991651793, -122.12751396546462 47.56161562515103, -122.15291875937262 47.5785905657411, -122.18032188610536 47.5921042923483, -122.20925447056683 47.60192558136367, -122.2392214682153 47.607886387809195, -122.26971013541258 47.60988472063392, -122.30019880260986 47.607886387809195, -122.33016580025833 47.60192558136367, -122.3590983847198 47.5921042923483, -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.58869123015452 41.901774579059115, -118.91479847512254 43.54122641035517, -119.02412442253558 45.209218040904574, -118.91479847512252 46.877209671453976, -118.58869123015451 48.516661502750026, -118.05138247300694 50.09952205941734, -117.31206570548474 51.59870815847947, -116.38339084245754 52.98856831012856, -115.28124776830906 54.245321621827856, -114.02449445660976 55.347464695976335, -112.63463430496067 56.27613955900354, -111.13544820589854 57.01545632652574, -109.6875 57.51582286553883, -109.55258764923123 57.552765083673314, -107.91313581793517 57.87887232864133, -106.24514418738576 57.98819827605437, -104.57715255683635 57.87887232864133, -102.9377007255403 57.552765083673314, -101.35484016887298 57.01545632652574, -99.85565406981085 56.27613955900354, -98.46579391816176 55.347464695976335, -97.20904060646247 54.245321621827856, -96.10689753231398 52.98856831012856, -95.17822266928678 51.59870815847947, -94.43890590176458 50.09952205941733, -93.901597144617 48.51666150275002, -93.575489899649 46.87720967145396, -93.46616395223595 45.20921804090456, -93.575489899649 43.54122641035516, -93.8671875 42.032974332441405, -92.52944589377746 42.87620255408929, -90.13998424943787 44.0545546346726, -87.61715897053445 44.91093841996455, -85.00413629704853 45.43070094596436, -82.34562577139025 45.60494893174677, -79.68711524573196 45.43070094596437, -77.07409257224604 44.910938419964566, -74.55126729334262 44.05455463467261, -72.16180564900301 42.876202554089296, -69.94659199044581 41.396044109014326, -67.9435292375422 39.639405220820365, -66.18689034934823 37.63634246791675, -64.70673190427325 35.42112880935955, -63.528379823689946 33.03166716501995, -62.67199603839799 30.50884188611652, -62.57812500000001 30.14512718337613, -62.15223351239818 27.895819212630613, -61.97798552661578 25.237308686972327, -62.15223351239818 22.578798161314037, -62.671996038397985 19.965775487828132, -63.52837982368993 17.442950208924703, -64.70673190427325 15.0534885645851, -66.18689034934822 12.838274906027902, -67.94352923754218 10.835212153124278, -69.9465919904458 9.078573264930323, -72.16180564900299 7.598414819855346, -74.55126729334259 6.42006273927203, -77.07409257224602 5.563678953980077, -79.68711524573193 5.0439164279802675, -82.34562577139022 4.869668442197863, -85.00413629704852 5.043916427980264, -87.61715897053442 5.5636789539800695, -90.13998424943784 6.420062739272023, -92.10937499999999 7.36246686553575, -94.00832592648507 5.722586433241059, -96.3693387982898 4.1450080684486466, -98.91606817456314 2.88910012519991, -101.60493880959022 1.9763515366073037, -104.38994338130999 1.4223796840833636, -107.22342968935115 1.2366631796147907, -110.05691599739232 1.4223796840833813, -112.84192056911208 1.9763515366073356, -115.53079120413916 2.8891001251999597, -118.07752058041248 4.1450080684487105, -120.43853345221721 5.722586433241133, -122.57343223472037 7.594842416368293, -124.4456882178475 9.729741198871439, -126.02326658263992 12.09075407067618, -127.265625 14.604847155053898, -127.27917452588866 14.637483446949503, -128.19192311448128 17.326354081976593, -128.7458949670052 20.111358653696357, -128.9316114714738 22.944844961737523, -128.7458949670052 25.77833126977869, -128.19192311448126 28.56333584149845, -127.27917452588864 31.252206476525537, -126.02326658263989 33.798935852798856, -124.44568821784746 36.159948724603595, -122.57343223472031 38.29484750710673, -120.43853345221717 40.16710349023388, -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.58869123015452 41.901774579059115, -118.91479847512254 43.54122641035517, -119.02412442253558 45.209218040904574, -118.91479847512252 46.877209671453976, -118.58869123015451 48.516661502750026, -118.05138247300694 50.09952205941734, -117.31206570548474 51.59870815847947, -116.38339084245754 52.98856831012856, -115.28124776830906 54.245321621827856, -114.02449445660976 55.347464695976335, -112.63463430496067 56.27613955900354, -111.13544820589854 57.01545632652574, -109.6875 57.51582286553883, -109.55258764923123 57.552765083673314, -107.91313581793517 57.87887232864133, -106.24514418738576 57.98819827605437, -104.57715255683635 57.87887232864133, -102.9377007255403 57.552765083673314, -101.35484016887298 57.01545632652574, -99.85565406981085 56.27613955900354, -98.46579391816176 55.347464695976335, -97.20904060646247 54.245321621827856, -96.10689753231398 52.98856831012856, -95.17822266928678 51.59870815847947, -94.43890590176458 50.09952205941733, -93.901597144617 48.51666150275002, -93.575489899649 46.87720967145396, -93.46616395223595 45.20921804090456, -93.575489899649 43.54122641035516, -93.8671875 42.032974332441405, -92.52944589377746 42.87620255408929, -90.13998424943787 44.0545546346726, -87.61715897053445 44.91093841996455, -85.00413629704853 45.43070094596436, -82.34562577139025 45.60494893174677, -79.68711524573196 45.43070094596437, -77.07409257224604 44.910938419964566, -74.55126729334262 44.05455463467261, -72.16180564900301 42.876202554089296, -69.94659199044581 41.396044109014326, -67.9435292375422 39.639405220820365, -66.18689034934823 37.63634246791675, -64.70673190427325 35.42112880935955, -63.528379823689946 33.03166716501995, -62.67199603839799 30.50884188611652, -62.57812500000001 30.14512718337613, -62.15223351239818 27.895819212630613, -61.97798552661578 25.237308686972327, -62.15223351239818 22.578798161314037, -62.671996038397985 19.965775487828132, -63.52837982368993 17.442950208924703, -64.70673190427325 15.0534885645851, -66.18689034934822 12.838274906027902, -67.94352923754218 10.835212153124278, -69.9465919904458 9.078573264930323, -72.16180564900299 7.598414819855346, -74.55126729334259 6.42006273927203, -77.07409257224602 5.563678953980077, -79.68711524573193 5.0439164279802675, -82.34562577139022 4.869668442197863, -85.00413629704852 5.043916427980264, -87.61715897053442 5.5636789539800695, -90.13998424943784 6.420062739272023, -92.10937499999999 7.36246686553575, -94.00832592648507 5.722586433241059, -96.3693387982898 4.1450080684486466, -98.91606817456314 2.88910012519991, -101.60493880959022 1.9763515366073037, -104.38994338130999 1.4223796840833636, -107.22342968935115 1.2366631796147907, -110.05691599739232 1.4223796840833813, -112.84192056911208 1.9763515366073356, -115.53079120413916 2.8891001251999597, -118.07752058041248 4.1450080684487105, -120.43853345221721 5.722586433241133, -122.57343223472037 7.594842416368293, -124.4456882178475 9.729741198871439, -126.02326658263992 12.09075407067618, -127.265625 14.604847155053898, -127.27917452588866 14.637483446949503, -128.19192311448128 17.326354081976593, -128.7458949670052 20.111358653696357, -128.9316114714738 22.944844961737523, -128.7458949670052 25.77833126977869, -128.19192311448126 28.56333584149845, -127.27917452588864 31.252206476525537, -126.02326658263989 33.798935852798856, -124.44568821784746 36.159948724603595, -122.57343223472031 38.29484750710673, -120.43853345221717 40.16710349023388, -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.022331449414295 23.8488525605847, 25.524767337284196 22.84821221194479, 23.909405319245263 22.051603821364203, 22.203884687289108 21.472657579267334, 20.43738737228815 21.12127941637069, 18.64013863306764 21.00348151046186, 16.842889893847133 21.1212794163707, 15.076392578846175 21.472657579267356, 13.370871946890022 22.051603821364232, 11.755509928851094 22.848212211944833, 10.257945816720998 23.848852560584746, 8.903803347661494 25.036403633488835, 7.716252274757412 26.390546102548342, 6.715611926117504 27.88811021467844, 5.919003535536911 29.50347223271737, 5.340057293440038 31.20899286467353, 4.988679130543391 32.97549017967449, 4.8708812246345605 34.772738918894994, 4.988679130543396 36.5699876581155, 5.340057293440047 38.336484973116455, 5.9190035355369215 40.04200560507262, 5.9765625 40.17887331434696, 6.715611926117516 41.65736762311154, 7.71625227475743 43.15493173524164, 8.903803347661514 44.50907420430114, 10.257945816721021 45.69662527720523, 11.755509928851117 46.69726562584515, 13.37087194689005 47.49387401642574, 15.076392578846209 48.07282025852261, 16.84288989384717 48.42419842141926, 18.64013863306768 48.5419963273281, 20.437387372288192 48.42419842141926, 22.20388468728915 48.07282025852261, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138724 48.953451060440116, 74.12646468490568 48.43073090444654, 75.58494601643167 47.71148750685245, 76.93706973601537 46.80802732160263, 78.15970063193521 45.735808802953194, 79.23191915058464 44.513177907033366, 80.13537933583446 43.16105418744966, 80.85462273342854 41.70257285592367, 81.37734288942212 40.162688932405224, 81.5625 39.36827914916011, 81.69459591702075 38.567750257762206, 81.80095352896302 36.9450466749183, 81.69459591702075 35.3223430920744, 81.37734288942212 33.72740441743138, 80.85462273342854 32.187520493912935, 80.13537933583446 30.729039162386947, 79.23191915058464 29.376915442803238, 78.15970063193521 28.15428454688341, 76.93706973601537 27.082066028233974, 75.58494601643167 26.178605842984155, 74.12646468490568 25.459362445390067, 72.58658076138724 24.936642289396488, 70.99164208674422 24.61938926179787, 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.022331449414295 23.8488525605847, 25.524767337284196 22.84821221194479, 23.909405319245263 22.051603821364203, 22.203884687289108 21.472657579267334, 20.43738737228815 21.12127941637069, 18.64013863306764 21.00348151046186, 16.842889893847133 21.1212794163707, 15.076392578846175 21.472657579267356, 13.370871946890022 22.051603821364232, 11.755509928851094 22.848212211944833, 10.257945816720998 23.848852560584746, 8.903803347661494 25.036403633488835, 7.716252274757412 26.390546102548342, 6.715611926117504 27.88811021467844, 5.919003535536911 29.50347223271737, 5.340057293440038 31.20899286467353, 4.988679130543391 32.97549017967449, 4.8708812246345605 34.772738918894994, 4.988679130543396 36.5699876581155, 5.340057293440047 38.336484973116455, 5.9190035355369215 40.04200560507262, 5.9765625 40.17887331434696, 6.715611926117516 41.65736762311154, 7.71625227475743 43.15493173524164, 8.903803347661514 44.50907420430114, 10.257945816721021 45.69662527720523, 11.755509928851117 46.69726562584515, 13.37087194689005 47.49387401642574, 15.076392578846209 48.07282025852261, 16.84288989384717 48.42419842141926, 18.64013863306768 48.5419963273281, 20.437387372288192 48.42419842141926, 22.20388468728915 48.07282025852261, 22.5 47.98992166741417) LINESTRING (22.5 47.98992166741417, 71.71875 49.15296965617039) LINESTRING (71.71875 49.15296965617039, 72.58658076138724 48.953451060440116, 74.12646468490568 48.43073090444654, 75.58494601643167 47.71148750685245, 76.93706973601537 46.80802732160263, 78.15970063193521 45.735808802953194, 79.23191915058464 44.513177907033366, 80.13537933583446 43.16105418744966, 80.85462273342854 41.70257285592367, 81.37734288942212 40.162688932405224, 81.5625 39.36827914916011, 81.69459591702075 38.567750257762206, 81.80095352896302 36.9450466749183, 81.69459591702075 35.3223430920744, 81.37734288942212 33.72740441743138, 80.85462273342854 32.187520493912935, 80.13537933583446 30.729039162386947, 79.23191915058464 29.376915442803238, 78.15970063193521 28.15428454688341, 76.93706973601537 27.082066028233974, 75.58494601643167 26.178605842984155, 74.12646468490568 25.459362445390067, 72.58658076138724 24.936642289396488, 70.99164208674422 24.61938926179787, 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.022331449414295 23.8488525605847, 25.524767337284196 22.84821221194479, 23.909405319245263 22.051603821364203, 22.203884687289108 21.472657579267334, 20.43738737228815 21.12127941637069, 18.64013863306764 21.00348151046186, 16.842889893847133 21.1212794163707, 15.076392578846175 21.472657579267356, 13.370871946890022 22.051603821364232, 11.755509928851094 22.848212211944833, 10.257945816720998 23.848852560584746, 8.903803347661494 25.036403633488835, 7.716252274757412 26.390546102548342, 6.715611926117504 27.88811021467844, 5.919003535536911 29.50347223271737, 5.340057293440038 31.20899286467353, 4.988679130543391 32.97549017967449, 4.8708812246345605 34.772738918894994, 4.988679130543396 36.5699876581155, 5.340057293440047 38.336484973116455, 5.9190035355369215 40.04200560507262, 5.9765625 40.17887331434696, 6.715611926117516 41.65736762311154, 7.71625227475743 43.15493173524164, 8.903803347661514 44.50907420430114, 10.257945816721021 45.69662527720523, 11.755509928851117 46.69726562584515, 13.37087194689005 47.49387401642574, 15.076392578846209 48.07282025852261, 16.84288989384717 48.42419842141926, 18.64013863306768 48.5419963273281, 20.437387372288192 48.42419842141926, 22.20388468728915 48.07282025852261, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138724 48.953451060440116, 74.12646468490568 48.43073090444654, 75.58494601643167 47.71148750685245, 76.93706973601537 46.80802732160263, 78.15970063193521 45.735808802953194, 79.23191915058464 44.513177907033366, 80.13537933583446 43.16105418744966, 80.85462273342854 41.70257285592367, 81.37734288942212 40.162688932405224, 81.5625 39.36827914916011, 81.69459591702075 38.567750257762206, 81.80095352896302 36.9450466749183, 81.69459591702075 35.3223430920744, 81.37734288942212 33.72740441743138, 80.85462273342854 32.187520493912935, 80.13537933583446 30.729039162386947, 79.23191915058464 29.376915442803238, 78.15970063193521 28.15428454688341, 76.93706973601537 27.082066028233974, 75.58494601643167 26.178605842984155, 74.12646468490568 25.459362445390067, 72.58658076138724 24.936642289396488, 70.99164208674422 24.61938926179787, 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.022331449414295 23.8488525605847, 25.524767337284196 22.84821221194479, 23.909405319245263 22.051603821364203, 22.203884687289108 21.472657579267334, 20.43738737228815 21.12127941637069, 18.64013863306764 21.00348151046186, 16.842889893847133 21.1212794163707, 15.076392578846175 21.472657579267356, 13.370871946890022 22.051603821364232, 11.755509928851094 22.848212211944833, 10.257945816720998 23.848852560584746, 8.903803347661494 25.036403633488835, 7.716252274757412 26.390546102548342, 6.715611926117504 27.88811021467844, 5.919003535536911 29.50347223271737, 5.340057293440038 31.20899286467353, 4.988679130543391 32.97549017967449, 4.8708812246345605 34.772738918894994, 4.988679130543396 36.5699876581155, 5.340057293440047 38.336484973116455, 5.9190035355369215 40.04200560507262, 5.9765625 40.17887331434696, 6.715611926117516 41.65736762311154, 7.71625227475743 43.15493173524164, 8.903803347661514 44.50907420430114, 10.257945816721021 45.69662527720523, 11.755509928851117 46.69726562584515, 13.37087194689005 47.49387401642574, 15.076392578846209 48.07282025852261, 16.84288989384717 48.42419842141926, 18.64013863306768 48.5419963273281, 20.437387372288192 48.42419842141926, 22.20388468728915 48.07282025852261, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138724 48.953451060440116, 74.12646468490568 48.43073090444654, 75.58494601643167 47.71148750685245, 76.93706973601537 46.80802732160263, 78.15970063193521 45.735808802953194, 79.23191915058464 44.513177907033366, 80.13537933583446 43.16105418744966, 80.85462273342854 41.70257285592367, 81.37734288942212 40.162688932405224, 81.5625 39.36827914916011, 81.69459591702075 38.567750257762206, 81.80095352896302 36.9450466749183, 81.69459591702075 35.3223430920744, 81.37734288942212 33.72740441743138, 80.85462273342854 32.187520493912935, 80.13537933583446 30.729039162386947, 79.23191915058464 29.376915442803238, 78.15970063193521 28.15428454688341, 76.93706973601537 27.082066028233974, 75.58494601643167 26.178605842984155, 74.12646468490568 25.459362445390067, 72.58658076138724 24.936642289396488, 70.99164208674422 24.61938926179787, 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.022331449414295 23.8488525605847, 25.524767337284196 22.84821221194479, 23.909405319245263 22.051603821364203, 22.203884687289108 21.472657579267334, 20.43738737228815 21.12127941637069, 18.64013863306764 21.00348151046186, 16.842889893847133 21.1212794163707, 15.076392578846175 21.472657579267356, 13.370871946890022 22.051603821364232, 11.755509928851094 22.848212211944833, 10.257945816720998 23.848852560584746, 8.903803347661494 25.036403633488835, 7.716252274757412 26.390546102548342, 6.715611926117504 27.88811021467844, 5.919003535536911 29.50347223271737, 5.340057293440038 31.20899286467353, 4.988679130543391 32.97549017967449, 4.8708812246345605 34.772738918894994, 4.988679130543396 36.5699876581155, 5.340057293440047 38.336484973116455, 5.9190035355369215 40.04200560507262, 5.9765625 40.17887331434696, 6.715611926117516 41.65736762311154, 7.71625227475743 43.15493173524164, 8.903803347661514 44.50907420430114, 10.257945816721021 45.69662527720523, 11.755509928851117 46.69726562584515, 13.37087194689005 47.49387401642574, 15.076392578846209 48.07282025852261, 16.84288989384717 48.42419842141926, 18.64013863306768 48.5419963273281, 20.437387372288192 48.42419842141926, 22.20388468728915 48.07282025852261, 22.5 47.98992166741417) LINESTRING (22.5 47.98992166741417, 71.71875 49.15296965617039) LINESTRING (71.71875 49.15296965617039, 72.58658076138724 48.953451060440116, 74.12646468490568 48.43073090444654, 75.58494601643167 47.71148750685245, 76.93706973601537 46.80802732160263, 78.15970063193521 45.735808802953194, 79.23191915058464 44.513177907033366, 80.13537933583446 43.16105418744966, 80.85462273342854 41.70257285592367, 81.37734288942212 40.162688932405224, 81.5625 39.36827914916011, 81.69459591702075 38.567750257762206, 81.80095352896302 36.9450466749183, 81.69459591702075 35.3223430920744, 81.37734288942212 33.72740441743138, 80.85462273342854 32.187520493912935, 80.13537933583446 30.729039162386947, 79.23191915058464 29.376915442803238, 78.15970063193521 28.15428454688341, 76.93706973601537 27.082066028233974, 75.58494601643167 26.178605842984155, 74.12646468490568 25.459362445390067, 72.58658076138724 24.936642289396488, 70.99164208674422 24.61938926179787, 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.022331449414295 23.8488525605847, 25.524767337284196 22.84821221194479, 23.909405319245263 22.051603821364203, 22.203884687289108 21.472657579267334, 20.43738737228815 21.12127941637069, 18.64013863306764 21.00348151046186, 16.842889893847133 21.1212794163707, 15.076392578846175 21.472657579267356, 13.370871946890022 22.051603821364232, 11.755509928851094 22.848212211944833, 10.257945816720998 23.848852560584746, 8.903803347661494 25.036403633488835, 7.716252274757412 26.390546102548342, 6.715611926117504 27.88811021467844, 5.919003535536911 29.50347223271737, 5.340057293440038 31.20899286467353, 4.988679130543391 32.97549017967449, 4.8708812246345605 34.772738918894994, 4.988679130543396 36.5699876581155, 5.340057293440047 38.336484973116455, 5.9190035355369215 40.04200560507262, 5.9765625 40.17887331434696, 6.715611926117516 41.65736762311154, 7.71625227475743 43.15493173524164, 8.903803347661514 44.50907420430114, 10.257945816721021 45.69662527720523, 11.755509928851117 46.69726562584515, 13.37087194689005 47.49387401642574, 15.076392578846209 48.07282025852261, 16.84288989384717 48.42419842141926, 18.64013863306768 48.5419963273281, 20.437387372288192 48.42419842141926, 22.20388468728915 48.07282025852261, 22.5 47.98992166741417, 71.71875 49.15296965617039, 72.58658076138724 48.953451060440116, 74.12646468490568 48.43073090444654, 75.58494601643167 47.71148750685245, 76.93706973601537 46.80802732160263, 78.15970063193521 45.735808802953194, 79.23191915058464 44.513177907033366, 80.13537933583446 43.16105418744966, 80.85462273342854 41.70257285592367, 81.37734288942212 40.162688932405224, 81.5625 39.36827914916011, 81.69459591702075 38.567750257762206, 81.80095352896302 36.9450466749183, 81.69459591702075 35.3223430920744, 81.37734288942212 33.72740441743138, 80.85462273342854 32.187520493912935, 80.13537933583446 30.729039162386947, 79.23191915058464 29.376915442803238, 78.15970063193521 28.15428454688341, 76.93706973601537 27.082066028233974, 75.58494601643167 26.178605842984155, 74.12646468490568 25.459362445390067, 72.58658076138724 24.936642289396488, 70.99164208674422 24.61938926179787, 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)
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
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
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 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 = 357222443 nanoseconds Time with PreparedGeometry = 214496717 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 = 304872303 nanoseconds Time with PreparedGeometry = 111271858 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
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
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
TWkbReader reader = new TWkbReader()
Geometry geometry = reader.read("01000204")
println geometry.wkt
POINT (1 2)
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@
Bounds Recipes
The Bounds class is in the geoscript.geom package.
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.7684517875,703506.2231641772,1155828.1202425088,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.2040371667 703068.0661327888)
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.2040371667 703068.0661327888)
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.2040371667 703068.0661327888)
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.2040371667 703068.0661327888)
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.6581745719509
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.516427795897236)
double azimuth = results.backAzimuth
println azimuth
75.65337425050724
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.52791689304305) POINT (-79.8828640042499 44.63747566950249) POINT (-84.51118758826816 45.565540142641) POINT (-89.27793446221685 46.300124344169255) POINT (-94.15564606698499 46.83102721803566) POINT (-99.11079892605703 47.15045006457598) POINT (-104.10532353179985 47.25351783423774) POINT (-109.09873812691619 47.13862709798195) POINT (-114.05062990603696 46.80756425557423) 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 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])
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.
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-34d9214a_16d54d1675c_-7ffc 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
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
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
0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65
String geobuf = '0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65'
Feature feature = Feature.fromGeobuf(geobuf)
println feature
features.0 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
0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65
GeobufReader reader = new GeobufReader()
String geobuf = '0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65'
Feature feature = reader.read(geobuf)
println feature
features.0 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 xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary><updated>Sat Sep 21 10:14:33 PDT 2019</updated><georss:point xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'>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-34d9214a_16d54d1675c_-8000 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 xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary><updated>Sat Sep 21 10:14:33 PDT 2019</updated><georss:point xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'>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-34d9214a_16d54d1675c_-7ffe 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-34d9214a_16d54d1675c_-7ffd 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-34d9214a_16d54d1675c_-7fff 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)
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 306 Functions: Area Categorize Collection_Average Collection_Bounds Collection_Count Collection_Max Collection_Median Collection_Min Collection_Nearest Collection_Sum
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
}
YlOrRd PRGn PuOr RdGy Spectral Grays PuBuGn RdPu BuPu YlOrBr Greens BuGn Accents GnBu PuRd Purples RdYlGn Paired Blues RdBu Oranges RdYlBu PuBu OrRd Set3 Set2 Set1 Reds PiYG Dark2 YlGn BrBG YlGnBu Pastel2 Pastel1 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
}
PRGn PuOr RdGy Spectral RdYlGn RdBu RdYlBu PiYG BrBG BlueToOrange GreenToOrange BlueToRed GreenToRedOrange
List<String> sequentialPalettes = Color.getPaletteNames("sequential")
sequentialPalettes.each { String name ->
println name
}
YlOrRd Grays PuBuGn RdPu BuPu YlOrBr Greens BuGn GnBu PuRd Purples Blues Oranges PuBu OrRd Reds YlGn YlGnBu Sunset Green YellowToRedHeatMap BlueToYellowToRedHeatMap DarkRedToYellowWhiteHeatMap LightPurpleToDarkPurpleHeatMap BoldLandUse MutedTerrain
List<String> qualitativePalettes = Color.getPaletteNames("qualitative")
qualitativePalettes.each { String name ->
println name
}
Accents Paired Set3 Set2 Set1 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: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:length geo:isEmpty geo:contains geo:disjoint geo:intersects geo:area geo:numGeometries geo:isClosed geo:buffer geo:difference geo:boundary geo:splitPolygon geo:within geo:touches geo:convexHull geo:crosses geo:symDifference geo:distance geo:centroid geo:interiorPoint geo:getGeometryN geo:overlaps geo:isSimple geo:isWithinDistance geo:relate geo:densify geo:simplify geo:startPoint geo:numPoints geo:reproject geo:dimension geo:exteriorRing geo:numInteriorRing geo:geometryType geo:envelope geo:isRing geo:polygonize geo:endPoint geo:equalsExact geo:isValid geo:union geo:intersection geo:getX geo:getY geo:pointN geo:interiorRingN geo:relatePattern geo:equalsExactTolerance polygonlabelprocess:PolyLabeller 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})
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.9971868880408555E7,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
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("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("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_1 = '${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_1 = '${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_1='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_1='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_1='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_1='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)
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)
Symbolizer symbolizer = new Fill("#ffffcc").where("PEOPLE < 4504128.33") +
new Fill("#41b6c4").where("PEOPLE BETWEEN 4504128.33 AND 16639804.33") +
new Fill("#253494").where("PEOPLE > 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_1")
.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)
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_1")
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")
Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.1) + new Label(Expression.fromCQL("strToLowerCase(NAME_1)"))
.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_1")
.point(anchor: [0.5,0.5])
.polygonAlign("mbr")
.strikethrough(true)
Symbolizer symbolizer = new Fill("white") + new Stroke("black", 0.1) + new Label("NAME_1")
.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_1")
.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, "PEOPLE", "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, "PEOPLE", "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="http://www.opengis.net/sld" xmlns:sld="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>
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 and fill-opacity
-
Stroke properties: stroke, stroke-width, stroke-opacity
-
Shape properties: shape, shape-size, shape-type
-
Label properties: label-size, label-style, label-weight, label-family
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
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
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
}
Directory of spatial files (shapefiles) PostGIS (JNDI) H2 (JNDI) SQLite PostGIS MySQL (JNDI) GeoPackage MySQL Geobuf H2 Shapefile Web Feature Server (NG) Properties
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[/Users/jericks/Projects/geoscript-cookbook/src/main/resources/data]
String format = directory.format
println format
Directory
File file = directory.file
println file
/Users/jericks/Projects/geoscript-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
}
Directory of spatial files (shapefiles) PostGIS (JNDI) H2 (JNDI) SQLite PostGIS MySQL (JNDI) GeoPackage MySQL Geobuf H2 Shapefile Web Feature Server (NG) Properties
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
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) ocean (2) places (326) rivers (460) states (52)
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) ocean (2) places (326) rivers (460) states (52)
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)
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)
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) ocean (2) places (326) rivers (460) states (52)
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) ocean (2) places (326) rivers (460) states (52)
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 -- 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 ------ countries (177) ocean (2) places (326)
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: (-179.99999999999997,-90.00000000000003,180.00000000000014,83.64513000000002,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.0 Maximum Population in 2050 = 36400.0
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_1"]
}
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_1 LIKE 'M%'") { Feature feature ->
println feature["NAME_1"]
}
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_1"], start: 0, max: 5, fields: ["NAME_1"], filter: "NAME_1 LIKE 'M%'") { Feature feature ->
println feature["NAME_1"]
}
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_1"]
}
# Features = 52 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_1"]
}.sort()
println "# Names = ${names.size()}"
names.each { String name ->
println name
}
# Names = 52 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_1"],
start: 0,
max: 5,
fields: ["NAME_1"],
filter: "NAME_1 LIKE 'M%'") { Feature f ->
f["NAME_1"]
}
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_1='Washington'")
println feature.get("NAME_1")
Washington
Workspace workspace = new GeoPackage("src/main/resources/data.gpkg")
Layer layer = workspace.get("states")
Feature featureAsc = layer.first(sort: "NAME_1 ASC")
println featureAsc.get("NAME_1")
Feature featureDesc = layer.first(sort: "NAME_1 DESC")
println featureDesc.get("NAME_1")
Alabama Wyoming
Filter
Workspace workspace = new Directory("target")
Layer layer = workspace.get("countries")
Layer disputedLayer = layer.filter("TYPE='Disputed'")
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_1"]
}
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_1 LIKE 'M%'")
while(cursor.hasNext()) {
Feature feature = cursor.next()
println feature["NAME_1"]
}
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_1"], start: 0, max: 5, fields: ["NAME_1"], filter: "NAME_1 LIKE 'M%'").each { Feature feature ->
println feature["NAME_1"]
}
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_0 has 1 features rivers_1 has 27 features rivers_2 has 35 features rivers_3 has 53 features rivers_4 has 71 features rivers_5 has 67 features rivers_6 has 206 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 74 features countries_3_1 has 13 features countries_3_2 has 70 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
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
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-34d9214a_16d54d1675c_-68cc" }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ -122.4842, 47.2619 ] }, "properties": { "id": 2, "name": "Tacoma" }, "id": "fid-34d9214a_16d54d1675c_-68ca" } ] }
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-34d9214a_16d54d1675c_-7e12" }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ -122.4842, 47.2619 ] }, "properties": { "id": 2, "name": "Tacoma" }, "id": "fid-34d9214a_16d54d1675c_-7e10" } ] }
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
0a0269640a046e616d6510021806223d0a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c650a1c0a0c08001a08ffd6e77498a3892d6a0218026a080a065461636f6d61
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
0a0269640a046e616d6510021806223f0a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c650a1e0a0c08001a08afe9ff7480d2b42b6a0218026a0a0a08506f72746c616e64
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-34d9214a_16d54d1675c_-736d"> <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-34d9214a_16d54d1675c_-736b"> <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-34d9214a_16d54d1675c_-7393"> <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-34d9214a_16d54d1675c_-7391"> <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-34d9214a_16d54d1675c_-69d7 </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-34d9214a_16d54d1675c_-69d5 </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-34d9214a_16d54d1675c_-738b"> <kml:name>Seattle</kml:name> <kml:Point> <kml:coordinates>-122.3204,47.6024</kml:coordinates> </kml:Point> </kml:Placemark> <kml:Placemark id="fid-34d9214a_16d54d1675c_-7389"> <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)
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-34d9214a_16d54d1675c_-7a1b</title> <summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary> <updated>Sat Sep 21 10:15:00 PDT 2019</updated> <georss:point>47.6024 -122.3204</georss:point> </entry> <entry> <title>fid-34d9214a_16d54d1675c_-7a19</title> <summary>[geom:POINT (-122.48416 47.2619), id:2, name:Tacoma]</summary> <updated>Sat Sep 21 10:15:00 PDT 2019</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-34d9214a_16d54d1675c_-738f</name> </wpt> <wpt lat="47.2619" lon="-122.48416"> <name>fid-34d9214a_16d54d1675c_-738d</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)
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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0018197573940657E7,-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.2805929263 4533021.525424092) is (2343967.4055929263,4410824.650424092,2588361.1555929263,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.0036395147881314E7, "minY": -2.0037471205137067E7, "maxX": 2.0036395147881314E7, "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.0036395147881314E7</minX> <minY>-2.0037471205137067E7</minY> <maxX>2.0036395147881314E7</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.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
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.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>
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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.5027296360910986E7,-1.0018735602568535E7,-5009098.786970329,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.1583540944868885E7,5635538.7764447965,-1.0644334922311949E7,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.5027296360910986E7,2504683.9006421305,-5009098.786970329,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.1583540944868885E7,5635538.7764447965,-1.0644334922311949E7,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.1466140192049267E7,5674674.46239233,-1.1436790003844364E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,2.003747120513706E7,EPSG:3857) geoscript.layer.Pyramid(proj:EPSG:3857, bounds:(-2.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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)
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-34d9214a_16d54d1675c_-3456"},{"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.9
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.0036395147881314E7,-2.0037471205137067E7,2.0036395147881314E7,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.5027296360910986E7,-1.0018735602568535E7,-5009098.786970329,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.1583540944868885E7,5635538.7764447965,-1.0644334922311949E7,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.5027296360910986E7,2504683.9006421305,-5009098.786970329,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.1583540944868885E7,5635538.7764447965,-1.0644334922311949E7,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.1583540944868885E7,5635538.7764447965,-1.0644334922311949E7,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"
])
Stamen Toner
Create a TileLayer for OSM Stamen Toner tiles.
OSM osm = OSM.getWellKnownOSM("stamen-toner")
Stamen Toner Lite
Create a TileLayer for OSM Stamen Toner Lite tiles.
OSM osm = OSM.getWellKnownOSM("stamen-toner-lite")