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:

  1. geoscript-groovy (which can run Groovy files)

geoscript groovy
  1. geoscript-groovysh (which starts a REPL shell)

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

geoscript groovyConsole

geoscript-groovy

The geoscript-groovy command can run scripts file, but it can also run inline scripts.

Convert a shapefile to geojson
geoscript-groovy -e "println new geoscript.layer.Shapefile('states.shp').toJSONString()"
Get the Bounds of a Shapefile as a Geometry
geoscript-groovy -e "println new geoscript.layer.Shapefile('states.shp').bounds.geometry"
Count the number of Features in a Shapefile
geoscript-groovy -e "println new geoscript.layer.Shapefile('states.shp').count"
Render a Shapefile to an image
geoscript-groovy -e "geoscript.render.Draw.draw(new geoscript.layer.Shapefile('states.shp'), out: 'image.png')"
Pipe a Shapefile’s geometry to another command line application that buffers each feature
geoscript-groovy -e "new geoscript.layer.Shapefile('states.shp').eachFeature{ println it.geom.centroid}" | geom combine | geom buffer -d 1.5
Pipe the results of buffering a point to convert it to KML
echo "POINT (1 1)" | geom buffer -d 10 | geoscript-groovy -e "println geoscript.geom.Geometry.fromWKT(System.in.text).kml"

Uber Jar

GeoScript Groovy also comes packaged as an uber jar which contains all dependencies. Download geoscript-groovy-app-1.21.0-SNAPSHOT.jar from github.

Run uber jar from the command line.
java -jar geoscript-groovy-app-1.21.0-SNAPSHOT.jar

The uber jar can take four commands:

  • script = Runs a script file like the geoscript-groovy command.

  • shell = Start an interactive shell like the geoscript-groovysh commmand.

  • console = Open the simple GUI like the geoscript-groovyConsole command.

  • version = Print the versions of GeoScript, GeoTools, and Groovy

Library

Maven

You can also use GeoScript Groovy as a library. If you use Maven you will need to add the OSGeo Maven Repository:
<repository>
    <id>osgeo-releases</id>
    <name>OSGeo Nexus Release Repository</name>
    <url>https://repo.osgeo.org/repository/release/</url>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
    <releases>
        <enabled>true</enabled>
    </releases>
</repository>
and then include the GeoScript Groovy dependency:
<dependency>
    <groupId>org.geoscript</groupId>
    <artifactId>geoscript-groovy</artifactId>
    <version>1.21.0-SNAPSHOT</version>
</dependency>

Gradle

To use GeoScript Groovy in a Gradle project, add the following repositories:
repositories {
    maven {
        url "https://repo.osgeo.org/repository/release/"
    }
}
and the include the GeoScript Groovy dependency:
dependencies {
    compile("org.geoscript:geoscript-groovy:1.21.0-SNAPSHOT")
}

Geometry Recipes

The Geometry classes are in the geoscript.geom package.

Creating Geometries

Point

Create a Point with an XY
Point point = new Point(-123,46)
geometry create point

LineString

Create a LineString from Coordinates
LineString lineString = new LineString(
        [3.1982421875, 43.1640625],
        [6.7138671875, 49.755859375],
        [9.7021484375, 42.5927734375],
        [15.3271484375, 53.798828125]
)
geometry create linestring coordinates

Polygon

Create a Polygon from a List of Coordinates
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]
]])
geometry create polygon
Create a Polygon with holes
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]
        )
    ]
)
geometry create polygon withholes

MultiPoint

Create a MultiPoint with a List of Points
MultiPoint multiPoint = new MultiPoint([
        new Point(-122.3876953125, 47.5820839916191),
        new Point(-122.464599609375, 47.25686404408872),
        new Point(-122.48382568359374, 47.431803338643334)
])
geometry create multipoint

MultiLineString

Create a MultiLineString with a List of LineStrings
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]
        )
])
geometry create multilinestring

MultiPolygon

Create a MultiPolygon with a List of Polygons
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]
    ]])
)
geometry create multipolygon

GeometryCollection

Create a GeometryCollection with a List of Geometries
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)
)
geometry create geometrycollection

CircularString

Create a CircularString with a List of Points
CircularString circularString = new CircularString([
        [-122.464599609375, 47.247542522268006],
        [-122.03613281249999, 47.37789454155521],
        [-122.37670898437499, 47.58393661978134]
])
geometry create circularstring

CircularRing

Create a CircularRing with a List of Points
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 create circularring

CompoundCurve

Create a CompoundCurve with a List of CircularStrings and LineStrings
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 create compoundcurve

CompoundRing

Create a CompoundRing with a connected List of CircularStrings and LineStrings
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 create compoundring

Points

Get x, y, and z values from a Point
Point point = new Point(-122.38632, 47.58208, 101.45)
println "X = ${point.x}"
println "Y = ${point.y}"
println "Z = ${point.z}"
geometry point xyz
X = -122.38632
Y = 47.58208
Z = 101.45
Add two Points together to create a MultiPoint
Point point1 = new Point(-122.38632, 47.58208)
Point point2 = new Point(-122.37001, 47.55868)
MultiPoint points = point1 + point2
geometry plus point
Add a Point to a MultiPoint
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

geometry plus multipoint1

MultiPoint with extra Point

geometry plus multipoint2
Calculate the angle between two points
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}"
geometry point getangle
Angle in degrees = -29.663413013476646
Angle in radians = -0.5177242244641005
Calculate the azimuth between two points
Point point1 = new Point(-122.29980, 47.65058)
Point point2 = new Point(-120.54199, 46.64943)
double azimuth = point1.getAzimuth(point2)
println "Azimuth = ${azimuth}"
geometry point getazimuth
Azimuth = 129.21026122904846

LineStrings

Get the start Point from a LineString
LineString lineString = new LineString(
        [3.1982421875, 43.1640625],
        [6.7138671875, 49.755859375],
        [9.7021484375, 42.5927734375],
        [15.3271484375, 53.798828125]
)
Point startPoint = lineString.startPoint
geometry get startpoint from linestring
Get the end Point from a LineString
LineString lineString = new LineString(
        [3.1982421875, 43.1640625],
        [6.7138671875, 49.755859375],
        [9.7021484375, 42.5927734375],
        [15.3271484375, 53.798828125]
)
Point endPoint = lineString.endPoint
geometry get endpoint from linestring
Reverse a LineString
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

geometry reverse linestring1

Reversed LineString showing start point

geometry reverse linestring2
Determine if a LineString is closed or not
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}"
geometry is linestring closed1
Is LINESTRING (3.1982421875 43.1640625, 6.7138671875 49.755859375, 9.7021484375 42.5927734375, 15.3271484375 53.798828125) closed? false
geometry is linestring closed2
Is LINESTRING (3.1982421875 43.1640625, 6.7138671875 49.755859375, 9.7021484375 42.5927734375, 15.3271484375 53.798828125, 3.1982421875 43.1640625) closed? true
Determine if a LineString is a Ring or not
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}"
geometry is linestring ring1
Is LINESTRING (-122.391428 47.5633, -122.391836 47.562793, -122.39101 47.562417, -122.390516 47.563126) a ring? false
geometry is linestring ring2
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
Close an open LineString to create a LinearRing
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

geometry close linestring

Closed LinearRing

geometry close linearring
Add a LineString to another LineString to create a MultiLineString
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
geometry linestring plus
Add a Point to a LineString
LineString lineString = new LineString([
        [-122.39142894744873, 47.5812734461813],
        [-122.38237380981445, 47.58121554959838]
])

Point point = new Point(-122.38640785217285, 47.58552866972616)

LineString lineStringWithPoint = lineString + point
geometry linestring pluspoint1
geometry linestring pluspoint2
Add a Point to a LineString at a specific index
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)
geometry linestring addpoint1
geometry linestring addpoint2
Set a Point on a LineString at a specific index
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)
geometry linestring setpoint1
geometry linestring setpoint2
Remove a Point on a LineString at a specific index
LineString lineString = new LineString([
        [-122.39142894744873, 47.5812734461813],
        [-122.38237380981445, 47.58121554959838],
        [-122.38640785217285, 47.58552866972616]
])

LineString newLineString = lineString.removePoint(2)
geometry linestring removepoint1
geometry linestring removepoint2
Remove a Point from the end of a LineString.
LineString lineString1 = new LineString([
    [-122.39423990249632, 47.57926150237904],
    [-122.3918581008911, 47.58121554959838],
    [-122.38657951354979, 47.58121554959838],
    [-122.38638639450075, 47.58535499390333],
    [-122.38374710083008, 47.58535499390333]
])
geometry linestring negative1
LineString lineString2 = -lineString1
geometry linestring negative2
LineString lineString3 = -lineString2
geometry linestring negative3
Interpolate Points on a 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]
])
Point startPoint = lineString.interpolatePoint(0.0)
Point midPoint = lineString.interpolatePoint(0.5)
Point endPoint = lineString.interpolatePoint(1.0)
geometry linestring interpolatepoint
Locate the position of Points on a 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]
])

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}"
geometry linestring locatepoint
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
Place Points on a LineString
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

geometry linestring placepoint1

Point on LineString

geometry linestring placepoint2
Extract part of a 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)
geometry linestring subline1
geometry linestring subline2
Create Points along a 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]
])
MultiPoint multiPoint = lineString.createPointsAlong(0.001)
geometry linestring createpointsalong

Polygons

Get a Polygon’s exterior LinearRing
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()
geometry polygon exteriorring1
geometry polygon exteriorring2
Get a Polygon’s interior LinearRings
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)
geometry polygon interiorring1
geometry polygon interiorring2
geometry polygon interiorring3
Add a Polygon to another Polygon to create a MultiPolygon
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
geometry plus polygons
Split a Polygon with a LineString
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)
geometry split polygon1
geometry split polygon2

MultiLineStrings

Add a LineString to a MultiLineString to get a new 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]
    )
])

LineString lineString = new LineString (
    [-122.29705810546874, 47.303447043862626],
    [-122.42889404296875, 47.23262467463881]
)

MultiLineString newMultiLineString = multiLineString + lineString
geometry multilinestring plus
Merge the LineStrings in a 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]
    )
])
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))
geometry multilinestring plus
Create Points along a MultiLineString
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)
geometry multilinestring createpointsalong

MultiPolygons

Add a Polygon to a MultiPolygon to get a new 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]
    ]])
)
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
geometry multipolygon plus
Split a MultiPolygon with a LineString
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

geometry multipolygon split1

After

geometry multipolygon split2

Geometry Collections

Add a Geometry to a 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]
    ]))
])
GeometryCollection newGeometryCollection =  geometryCollection + new Point(-122.38718032836913, 47.58121374032914)

Original Geometry Collection

geometry geometrycollection plus1

New Geometry Collection

geometry geometrycollection plus2
Get a subset of Geometries from a 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]
        ]))
])
geometry geometrycollection slice1
Polygon slicedGeometryCollection1 =  geometryCollection.slice(2)
geometry geometrycollection slice2
GeometryCollection slicedGeometryCollection2 =  geometryCollection.slice(0,2)
geometry geometrycollection slice3
Get a Geometry from a GeometryCollection that is the most type specific as possible.
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}"
geometry geometrycollection narrow1
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}"
geometry geometrycollection narrow2
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

Get Curved WKT from a 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}"
geometry circularstring curvedwkt
WKT = LINESTRING (-122.464599609375 47.247542522268006, -122.45502379201072 47.23410579860775, -122.43487808337773 47.21113402059189, -122.41190630536187 47.19098831195889, -122.38650151145399 47.1740133713689, -122.35909838472138 47.160499644761764, -122.33016580026003 47.150678355746436, -122.3001988026117 47.14471754930094, -122.26971013541457 47.14271921647622, -122.23922146821744 47.14471754930094, -122.2092544705691 47.150678355746436, -122.18032188610776 47.160499644761764, -122.15291875937515 47.1740133713689, -122.12751396546727 47.19098831195889, -122.10454218745141 47.21113402059189, -122.08439647881842 47.23410579860775, -122.06742153822843 47.25951059251563, -122.05390781162129 47.28691371924824, -122.04408652260595 47.315846303709584, -122.03812571616047 47.34581330135792, -122.03612738333574 47.37630196855505, -122.03613281249999 47.37789454155521, -122.03812571616047 47.406790635752174, -122.04408652260595 47.43675763340051, -122.05390781162129 47.465690217861855, -122.06742153822843 47.49309334459446, -122.08439647881842 47.518498138502345, -122.10454218745141 47.5414699165182, -122.12751396546727 47.561615625151205, -122.15291875937515 47.578590565741194, -122.18032188610776 47.59210429234833, -122.2092544705691 47.60192558136366, -122.23922146821744 47.60788638780915, -122.26971013541457 47.60988472063387, -122.3001988026117 47.60788638780915, -122.33016580026003 47.60192558136366, -122.35909838472138 47.59210429234833, -122.37670898437499 47.58393661978134)
Curnved WKT = CIRCULARSTRING (-122.464599609375 47.247542522268006, -122.03613281249999 47.37789454155521, -122.37670898437499 47.58393661978134)
Get control points from a Circular Strings
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
}
geometry circularstring controlpoints
POINT (-122.464599609375 47.247542522268006)
POINT (-122.03613281249999 47.37789454155521)
POINT (-122.37670898437499 47.58393661978134)
Convert a Circural Strings to a Linear Geometry
CircularString circularString = new CircularString([
        [-122.464599609375, 47.247542522268006],
        [-122.03613281249999, 47.37789454155521],
        [-122.37670898437499, 47.58393661978134]
])
Geometry linear = circularString.linear
println linear.wkt
geometry circularstring linear
LINESTRING (-122.464599609375 47.247542522268006, -122.45502379201072 47.23410579860775, -122.43487808337773 47.21113402059189, -122.41190630536187 47.19098831195889, -122.38650151145399 47.1740133713689, -122.35909838472138 47.160499644761764, -122.33016580026003 47.150678355746436, -122.3001988026117 47.14471754930094, -122.26971013541457 47.14271921647622, -122.23922146821744 47.14471754930094, -122.2092544705691 47.150678355746436, -122.18032188610776 47.160499644761764, -122.15291875937515 47.1740133713689, -122.12751396546727 47.19098831195889, -122.10454218745141 47.21113402059189, -122.08439647881842 47.23410579860775, -122.06742153822843 47.25951059251563, -122.05390781162129 47.28691371924824, -122.04408652260595 47.315846303709584, -122.03812571616047 47.34581330135792, -122.03612738333574 47.37630196855505, -122.03613281249999 47.37789454155521, -122.03812571616047 47.406790635752174, -122.04408652260595 47.43675763340051, -122.05390781162129 47.465690217861855, -122.06742153822843 47.49309334459446, -122.08439647881842 47.518498138502345, -122.10454218745141 47.5414699165182, -122.12751396546727 47.561615625151205, -122.15291875937515 47.578590565741194, -122.18032188610776 47.59210429234833, -122.2092544705691 47.60192558136366, -122.23922146821744 47.60788638780915, -122.26971013541457 47.60988472063387, -122.3001988026117 47.60788638780915, -122.33016580026003 47.60192558136366, -122.35909838472138 47.59210429234833, -122.37670898437499 47.58393661978134)

Circular Rings

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

Compound Curves

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

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

Compound Rings

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

Processing Geometries

Get the geometry type (Point, LineString, Polygon, ect…​) from a Geometry
Geometry geom = Geometry.fromString("POINT (-124.80 48.92)")
String type = geom.geometryType
println type
Point
Determine if one Geometry exactly equal another Geometry.
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
Determine if one Geometry equals another Geometry topologically.
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
Determine if one Geometry equals another Geometry when both are normalized.
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
Get a Geometry by index in a GeometryCollection
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)
Cast a Geometry to a Bounds or to a 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]
]])

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)
geometry astype
Get the area of a Geometry
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
Get the length of a Geometry
LineString lineString = new LineString([-122.69, 49.61], [-99.84, 45.33])
double length = lineString.length
println length
23.24738479915536
Buffer a Point
Point point = new Point(-123,46)
Geometry bufferedPoint = point.buffer(2)
geometry buffer point
Buffer a LineString with a butt cap
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 buffer line1
Buffer a LineString with a round cap
Geometry bufferedLine2 = line.buffer(2.1, 10, Geometry.CAP_ROUND)
geometry buffer line2
Buffer a LineString with a square cap
Geometry bufferedLine3 = line.buffer(2.1, 10, Geometry.CAP_SQUARE)
geometry buffer line3
Buffer a LineString on the right side only
LineString line = new LineString([
        [-122.563, 47.576],
        [-112.0166, 46.589],
        [-101.337, 47.606]
])
Geometry rightBufferedLine = line.singleSidedBuffer(1.5)
geometry buffer line singlesided1
Buffer a LineString on the left side only
Geometry leftBufferedLine = line.singleSidedBuffer(-1.5)
geometry buffer line singlesided2
Buffer a LineString with a beginning and end distance.
LineString line = new LineString([
        [-122.38494873046875, 47.57281986733871],
        [-122.27508544921875, 47.342545069660225],
        [-122.15972900390624, 47.14302937421008],
        [-121.96197509765625, 47.03082254778662],
        [-121.73950195312499, 46.89586230605985],
        [-121.56372070312499, 46.81509864599243]
])
Geometry buffer = line.variableBuffer([0.03, 0.07])
geometry variable buffer two
Buffer a LineString with a beginning, middle, and end distance.
LineString line = new LineString([
        [-122.38494873046875, 47.57281986733871],
        [-122.27508544921875, 47.342545069660225],
        [-122.15972900390624, 47.14302937421008],
        [-121.96197509765625, 47.03082254778662],
        [-121.73950195312499, 46.89586230605985],
        [-121.56372070312499, 46.81509864599243]
])
Geometry buffer = line.variableBuffer([0.03, 0.07, 0.1])
geometry variable buffer three
Buffer a LineString with a list of distances.
LineString line = new LineString([
        [-122.38494873046875, 47.57281986733871],
        [-122.27508544921875, 47.342545069660225],
        [-122.15972900390624, 47.14302937421008],
        [-121.96197509765625, 47.03082254778662],
        [-121.73950195312499, 46.89586230605985],
        [-121.56372070312499, 46.81509864599243]
])
Geometry buffer = line.variableBuffer([0.03, 0.05, 0.07, 0.09, 0.1, 0.2])
geometry variable buffer samenumber
Check whether a Geometry contains another Geometry
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
geometry contains 1
true
Check whether a Geometry is within another Geometry
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
geometry within 1
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
geometry within 2
false
Check whether a Geometry touches another Geometry
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)
geometry touches 12
true
LineString line3 = new LineString([
    [-122.386257648468, 47.58183793450921],
    [-122.38348960876465, 47.5818668824645]
])

touches = line1.touches(line3)
geometry touches 13
false
Create a convexhull Geometry around a Geometry
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
geometry convexhull
Check whether a Geometry covers another Geometry
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
geometry covers 1
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
geometry covers 2
false
Check whether a Geometry is covered by another Geometry
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
geometry coveredby 1
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
geometry coveredby 2
false
Check whether one Geometry crosses another Geometry
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
geometry crosses
false
false
true
Calculate the difference between two Geometries
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)
geometry difference
Calculate the symmetric difference between two Geometries
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)
geometry symdifference
Check whether one Geometry is disjoint from another Geometry
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
geometry distjoint
false
true
true
Calculate the distance bewteen two Geometries
Point point1 = new Point(-122.442, 47.256)
Point point2 = new Point(-122.321, 47.613)
double distance = point1.distance(point2)
println distance
geometry distance
0.37694827231332195
Get Bounds from a Geometry
Point point = new Point(-123,46)
Polygon polygon = point.buffer(2)
Bounds bounds = polygon.bounds
geometry bounds
Get the Boundary from a Geometry
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
geometry boundary
Get the Centroid from a Geometry
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
geometry centroid
Get the Interior Point from a Geometry
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
geometry interiorPoint
Get the number of Geometries
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
geometry getnumgeometries
3
Get a Geometry by index
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
}
geometry getgeometryn
POINT (-122.3876953125 47.5820839916191)
POINT (-122.464599609375 47.25686404408872)
POINT (-122.48382568359374 47.431803338643334)
Get a List of Geometries
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
}
geometry getgeometries
POINT (-122.3876953125 47.5820839916191)
POINT (-122.464599609375 47.25686404408872)
POINT (-122.48382568359374 47.431803338643334)
Get the number of Points in a Geometry
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
geometry numpoints
5
Create a Geometry of a String
Geometry geometry = Geometry.createFromText("Geo")
geometry createfromtext
Create a Sierpinski Carpet in a given Bounds and with a number of points
Bounds bounds = new Bounds(21.645,36.957,21.676,36.970, "EPSG:4326")
Geometry geometry = Geometry.createSierpinskiCarpet(bounds, 50)
geometry sierpinskicarpet
Create a Kock Snowflake in a given Bounds and with a number of points
Bounds bounds = new Bounds(21.645,36.957,21.676,36.970, "EPSG:4326")
Geometry geometry = Geometry.createKochSnowflake(bounds, 50)
geometry kochsnowflake
Perform a cascaded union on a List of Polygons.
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 cascadeunion
Create a number of random points within a given Geometry
Geometry geometry = new Bounds(-180, -90, 180, 90).geometry
MultiPoint randomPoints = Geometry.createRandomPoints(geometry, 100)
geometry create random points
Create a number of random points within a given Geometry where the points are contrained to the cells of a grid
Bounds bounds = new Bounds(-180, -90, 180, 90)
MultiPoint randomPoints = Geometry.createRandomPointsInGrid(bounds, 100, true, 0.5)
geometry create random points ingrid
Create a delaunay triangle diagram around a Geometry
Geometry points = Geometry.createRandomPoints(new Bounds(-180, -90, 180, 90).geometry, 100)
Geometry delaunayTriangle = points.delaunayTriangleDiagram
geometry delaunaytrianglediagram
Create a voronoi diagram around a Geometry
Geometry points = Geometry.createRandomPoints(new Bounds(-180, -90, 180, 90).geometry, 100)
Geometry voronoiDiagram = points.voronoiDiagram
geometry voronoidiagram
Triangulate inside of a Geometry.
Geometry geometry = Geometry.fromWKT("POLYGON ((-120.047607421875 48.100094697973795, -121.53076171875 48.44377831058802, " +
        "-122.03613281249999 47.5394554474239, -120.81665039062499 47.249406957888446, -121.78344726562499 46.437856895024204, " +
        "-119.20166015625 46.31658418182218, -118.05908203124999 47.39834920035926, -117.61962890624999 48.50204750525715, " +
        "-119.3115234375 48.65468584817256, -119.20166015625 47.82053186746053, -120.003662109375 47.60616304386874, " +
        "-120.0146484375 48.06339653776211, -120.047607421875 48.100094697973795))")
Geometry triangles = geometry.triangulate()
geometry triangulate
Calculate the union of two Geometries
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)
geometry union
Calculate the intersection between two Geometries
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)
geometry intersection
Check whether one Geometry intersects from another Geometry
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
geometry intersects
true
false
false
Check whether one Geometry overlaps from another Geometry
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
geometry overlaps
true
false
false
Calculate the octagonal envelope of a Geometry
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 octagonalEnvelope
Calculate the minimum rectangle of a Geometry
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 minimumrectangle
Calculate the minimum circle of a Geometry
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 minimumBoundingCircle
Calculate the minimum diameter of a Geometry
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 minimumDiameter
Calculate the minimum clearance of a Geometry
Geometry geometry = new Polygon ([[
    [-122.20367431640624, 47.543163654317304],
    [-122.3712158203125,  47.489368981370724],
    [-122.33276367187499, 47.35371061951363],
    [-122.11029052734374, 47.3704545156932],
    [-122.08831787109375, 47.286681888764214],
    [-122.28332519531249, 47.2270293988673],
    [-122.2174072265625,  47.154237057576594],
    [-121.904296875,      47.32579231609051],
    [-122.06085205078125, 47.47823216312885],
    [-122.20367431640624, 47.543163654317304]
]])
Geometry minimumClearance = geometry.minimumClearance
geometry minimumClearance
Calculate the largest empty circle within a Geometry
Geometry g = Geometry.fromWKT("POLYGON ((-122.38855361938475 47.5805786829606, -122.38636493682861 47.5783206388176, " +
        "-122.38700866699219 47.5750491969984, -122.38177299499512 47.57502024527343, " +
        "-122.38481998443604 47.5780600889959, -122.38151550292969 47.5805786829606, " +
        "-122.38855361938475 47.5805786829606))")
Geometry circle = g.getLargestEmptyCircle(1.0)
geometry largest empty circle
Calculate the maximum inscribed circle within a Geometry
Geometry g = Geometry.fromWKT("POLYGON ((-122.38855361938475 47.5805786829606, -122.38636493682861 47.5783206388176, " +
        "-122.38700866699219 47.5750491969984, -122.38177299499512 47.57502024527343, " +
        "-122.38481998443604 47.5780600889959, -122.38151550292969 47.5805786829606, " +
        "-122.38855361938475 47.5805786829606))")
Geometry circle = g.getMaximumInscribedCircle(1.0)
geometry maximum inscribed circle
Offset a LineString by a given distance. Positive distances will offset to the right. Negative distance will offset to the left.
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)
geometry offset
Get the dimension of a Geometry
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
Determine if a Geometry is empty or not
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
Determine if a Geometry is rectanglular
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'}"
geometry isrectangle1
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'}"
geometry isrectangle2
Is the geometry a rectangle? No
Determine if a Geometry is simple
Geometry geom1 = new LineString(
        [-122.323, 47.599],
        [-122.385, 47.581]
)
boolean isGeom1Simple = geom1.simple
println "Is the Geometry simple? ${isGeom1Simple}"
geometry issimple1
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}"
geometry issimple2
Is the Geometry simple? false
Determine if a Geometry is valid
Geometry geom1 = new LineString(
        [-122.323, 47.599],
        [-122.385, 47.581]
)
boolean isGeom1Valid = geom1.valid
println "Is the Geometry valid? ${isGeom1Valid}"
geometry isvalid1
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
geometry isvalid2
Is the Geometry valid? false
Self-intersection
Fix a Geometry
Geometry line = new LineString([[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [1, 1]])
println "LineString with duplicated Points = ${line.wkt}"
Geometry fixedLine = line.fix()
println "Fixed LineString = ${fixedLine}"
geometry fix
LineString with duplicated Points = LINESTRING (0 0, 0 0, 0 0, 0 0, 0 0, 1 1)
Fixed LineString = LINESTRING (0 0, 1 1)
Determine if a Geometry is curved
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}"
geometry iscurved1
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}"
geometry iscurved2
Is the Geometry curved? false
Determine if a Geometry is within a given distance of another Geometry
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
Normalizing a Geometry changes the Geometry in place.
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}"
geometry normalize
Normalized Geometry = POLYGON ((1 3, 2 4, 4 4, 6 3, 6 1, 2 1, 1 3))
Calculating a normalized Geometry from a Geometry does not change the original Geometry.
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}"
geometry norm
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))
Smooth a Geometry
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)
geometry smooth
Calculate the DE-9IM Intersection Matrix between two geometries.
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}"
geometry relateIntersectionMatrix
Intersection Matrix = 212101212
Contains = false
Covered By = false
Covers = false
Disjoint = false
Intersects = true
Within = false
Determine if a Geometry relates to another Geometry according to the given DE-9IM Intersection Matrix string
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")
geometry relate
true
false
false
Densify a Geometry by adding points at a given interval.
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}"
geometry densify orig
geometry densify
# of points in original geometry = 8
# of points in densified geometry = 50
Simplify a Geometry by removing points at a given interval.
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}"
geometry simplify orig
geometry simplify
# of points in original geometry = 13
# of points in simplified geometry = 5
Simplify a Geometry by removing points at a given interval but preserve the topological structure.
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}"
geometry simplifyPreservingTopology orig
geometry simplifyPreservingTopology
# of points in original geometry = 13
# of points in simplified geometry = 11
Translate or move a geometry a given distance along the x and y axis.
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 translate
Scale a geometry a given amount in an x and y direction around the origin
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 scalexy
Scale a geometry a given amount in an x and y direction around a point
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 scalexy around point
Rotate a Geometry around it’s origin by a given angle theta (in radians).
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 rotate theta1
geometry rotate theta2
Rotate a Geometry around an XY coordinate by a given angle theta (in radians).
Geometry thetaXY = geometry.rotate(Math.toRadians(90), geometry.centroid.x, geometry.centroid.y)
geometry rotate thetaxy
Rotate a Geometry around it’s origin by a given angle sine and cosine (in radians).
Geometry sinCos = geometry.rotate(Math.toRadians(15), Math.toRadians(35))
geometry rotate sincos1
geometry rotate sincos2
Rotate a Geometry around an XY coordinate by a given angle sine and cosine (in radians).
Geometry sinCosXY = geometry.rotate(Math.toRadians(15), Math.toRadians(35), geometry.centroid.x, geometry.centroid.y)
geometry rotate sincosxy
Shear a Geometry around it’s origin by a given distance along the x and y axis.
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 shear1
geometry shear2
Reflect a Geometry around an XY coordinate for given distance along the x and y axis
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 reflect
Reflect a Geometry around the origin for given distance along the x and y axis
Geometry reflectedAroundOrigin = geometry.reflect(0.5, 0.34)
geometry reflect2
geometry reflected2
Reduce the precision of a Geometry’s coordinates.
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)
Find the nearest points in one Geometry to another
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 nearestpoints
Convert a Geometry to a PreparedGeometry for more effecient spatial queries.
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         = 454292680 nanoseconds
Time with PreparedGeometry = 256996788 nanoseconds
Convert a Geometry to a PreparedGeometry using a static method for more effecient spatial queries.
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         = 391420308 nanoseconds
Time with PreparedGeometry = 254410345 nanoseconds

Prepared Geometry

PreparedGeometry are more effecient for spatial queries.

You can create a PreparedGeometry by wrapping an existing Geometry. You can then get the original Geometry with the geometry property.
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
geometry preparedgeometry create
Check whether a PreparedGeometry contains another 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
geometry preparedgeometry contains 1
true
geometry preparedgeometry contains 2
false
Check whether a PreparedGeometry properly contains another Geometry. This means that every point in the other geometry doesn’t intersect with the first.
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
geometry preparedgeometry containsproperly 1
true
geometry preparedgeometry containsproperly 2
false
Check whether a PreparedGeometry is covered by another Geometry.
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
geometry preparedgeometry coveredby 1
true
geometry preparedgeometry coveredby 2
false
Check whether a PreparedGeometry covers another 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 isCovered = polygon1.covers(polygon2)
println isCovered
geometry preparedgeometry covers 1
true
geometry preparedgeometry covers 2
false
Check whether a PreparedGeometry crosses another Geometry.
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
geometry preparedgeometry crosses
true
false
Check whether a PreparedGeometry is disjoint from another Geometry.
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
geometry preparedgeometry disjoint
false
true
Check whether a PreparedGeometry intersects another Geometry.
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
geometry preparedgeometry intersects
true
false
Check whether a PreparedGeometry overlaps another Geometry.
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
geometry preparedgeometry overlaps
true
false
Check whether a PreparedGeometry touches another Geometry.
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)
geometry preparedgeometry touches 12
true
LineString line3 = new LineString([
    [-122.386257648468, 47.58183793450921],
    [-122.38348960876465, 47.5818668824645]
])

touches = line1.touches(line3)
geometry preparedgeometry touches 13
false
Check whether a PreparedGeometry is within another Geometry.
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
geometry preparedgeometry within 1
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
geometry preparedgeometry within 2
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

Find all Geometry Readers
List<Reader> readers = Readers.list()
readers.each { Reader reader ->
    println reader.class.simpleName
}
GeobufReader
GeoJSONReader
GeoRSSReader
Gml2Reader
Gml3Reader
GpxReader
KmlReader
WkbReader
WktReader
GeoPackageReader
GooglePolylineEncoder
TWkbReader
YamlReader
Find a Geometry Reader
String wkt = "POINT (-123.15 46.237)"
Reader reader = Readers.find("wkt")
Geometry geometry = reader.read(wkt)
geometry find reader
Find all Geometry Writers
List<Writer> writers = Writers.list()
writers.each { Writer writer ->
    println writer.class.simpleName
}
GeobufWriter
GeoJSONWriter
GeoRSSWriter
Gml2Writer
Gml3Writer
GpxWriter
KmlWriter
WkbWriter
WktWriter
GeoPackageWriter
GooglePolylineEncoder
YamlWriter
TWkbWriter
Find a Geometry Writer
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]}
Create a Geometry from a String. The string will be parse by each Geometry Reader.
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

Read a Geometry from WKB using the WkbReader
String wkb = "0000000001C05EC9999999999A40471E5604189375"
WkbReader reader = new WkbReader()
Geometry geometry = reader.read(wkb)
geometry read wkbreader
Read a Geometry from WKB using the Geometry.fromWKB() static method
String wkb = "000000000200000004400995810624DD2F404594FDF3B645A2401ADA1CAC0831274048E0A3D70A3D714023676C8B43958140454BC6A7EF9DB2402EA3D70A3D70A4404AE624DD2F1AA0"
Geometry geometry = Geometry.fromWKB(wkb)
geometry read geometryfromwkb
Get the WKB of a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String wkb = geometry.wkb
println wkb
0000000001C05EC9999999999A40471E5604189375
Write a Geometry to WKB using the WkbWriter
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

Read a Geometry from WKT using the WktReader
String wkt = "POINT (-123.15 46.237)"
WktReader reader = new WktReader()
Geometry geometry = reader.read(wkt)
geometry read wktreader
Read a Geometry from WKT using the Geometry.fromWKT() static method
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 read geometryfromwkt
Get the WKT of a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String wkt = geometry.wkt
println wkt
POINT (-123.15 46.237)
Write a Geometry to WKT using the WktWriter
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

Get a Geometry from a TWKB Encoded String
String twkb = "E10801BFCBB99609A0D3F9B80300"
Geometry geometry = Geometry.fromTwkb(twkb)
geometry from twkb
Get TWKB Encoded String from a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String twkb = geometry.twkb
println twkb
E10801BFCBB99609A0D3F9B80300
Read a Geometry from TWKB hex encoded String
TWkbReader reader = new TWkbReader()
Geometry geometry = reader.read("E10801BFCBB99609A0D3F9B80300")
println geometry.wkt
POINT (-123.15 46.237)
geometry read from twkb
Write a Geometry to a TWKB hex encoded String using the TwkbWriter
Geometry geometry = new LineString(
        [3.198, 43.164],
        [6.713, 49.755],
        [9.702, 42.592],
        [15.32, 53.798]
)
TWkbWriter writer = new TWkbWriter()
String twkb = writer.write(geometry)
println twkb
E2080104C0E7BF1E80B7D29B0300E0E2C221E0D3ED3E00A0D7C01CDFF2A74400C0F4C935C099EF6A00

GeoJSON

Read a Geometry from GeoJSON using the GeoJSONReader
String json = '{"type":"Point","coordinates":[-123.15,46.237]}'
GeoJSONReader reader = new GeoJSONReader()
Geometry geometry = reader.read(json)
geometry read geojsonreader
Read a Geometry from GeoJSON using the Geometry.fromGeoJSON() static method
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 read geometryfromgeojson
Get the GeoJSON of a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String json = geometry.geoJSON
println json
{"type":"Point","coordinates":[-123.15,46.237]}
Write a Geometry to GeoJSON using the GeoJSONWriter
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

Read a Geometry from GeoPackage hex encoded string using the GeoPackageReader
String str = "4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375"
GeoPackageReader reader = new GeoPackageReader()
Geometry geometry = reader.read(str)
geometry from geopackage string
Read a Geometry from GeoPackage bytes using the GeoPackageReader
byte[] bytes = "4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375".decodeHex()
GeoPackageReader reader = new GeoPackageReader()
Geometry geometry = reader.read(bytes)
geometry from geopackage bytes
Write a Geometry to a GeoPackage hex encoded string
Geometry geometry = new Point(-123.15, 46.237)
GeoPackageWriter writer = new GeoPackageWriter()
String str = writer.write(geometry)
println str
4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375
Write a Geometry to a GeoPackage byte array
Geometry geometry = new Point(-123.15, 46.237)
GeoPackageWriter writer = new GeoPackageWriter()
byte[] bytes = writer.writeBytes(geometry)
println bytes.encodeHex()
4750000200000000c05ec9999999999ac05ec9999999999a40471e560418937540471e56041893750000000001c05ec9999999999a40471e5604189375

KML

Read a Geometry from KML using the KmlReader
String kml = "<Point><coordinates>-123.15,46.237</coordinates></Point>"
KmlReader reader = new KmlReader()
Geometry geometry = reader.read(kml)
geometry read kmlreader
Read a Geometry from KML using the Geometry.fromKml() static method
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 read geometryfromkml
Get the KML of a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String kml = geometry.kml
println kml
<Point><coordinates>-123.15,46.237</coordinates></Point>
Write a Geometry to KML using the KmlWriter
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

Read a Geometry from Geobuf using the GeobufReader
String geobuf = "10021806320c08001a08dffab87590958c2c"
GeobufReader reader = new GeobufReader()
Geometry geometry = reader.read(geobuf)
geometry read geobufreader
Read a Geometry from Geobuf using the Geometry.fromGeobuf() static method
String geobuf = "10021806322408021a20e0b08603c0859529f089ad03b0c8a40690efec02efb1ea06a0e5ad05e0f5d70a"
Geometry geometry = Geometry.fromGeobuf(geobuf)
geometry read geometryfromgeobuf
Get the Geobuf of a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String geobuf = geometry.geobuf
println geobuf
10021806320c08001a08dffab87590958c2c
Write a Geometry to Geobuf using the GeobufWriter
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

Read a Geometry from GML2 using the Gml2Reader
String gml2 = "<gml:Point><gml:coordinates>-123.15,46.237</gml:coordinates></gml:Point>"
Gml2Reader reader = new Gml2Reader()
Geometry geometry = reader.read(gml2)
geometry read gml2reader
Read a Geometry from GML2 using the Geometry.fromGML2() static method
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 read geometryfromgml2
Get the GML2 of a Geometry
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>
Write a Geometry to GML2 using the Gml2Writer
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

Read a Geometry from GML3 using the Gml3Reader
String gml3 = "<gml:Point><gml:pos>-123.15 46.237</gml:pos></gml:Point>"
Gml3Reader reader = new Gml3Reader()
Geometry geometry = reader.read(gml3)
geometry read gml3reader
Read a Geometry from GML3 using the Geometry.fromGML3() static method
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 read geometryfromgml3
Get the GML3 of a Geometry
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>
Write a Geometry to GML3 using the Gml3Writer
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

Read a Geometry from GPX using the GpxReader
String gpx = "<wpt lat='46.237' lon='-123.15'/>"
GpxReader reader = new GpxReader()
Geometry geometry = reader.read(gpx)
geometry read gpxreader
Read a Geometry from GPX using the Geometry.fromGPX() static method
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 read geometryfromgpx
Get the GPX of a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String gpx = geometry.gpx
println gpx
<wpt lat='46.237' lon='-123.15'/>
Write a Geometry to GPX using the GpxWriter
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

Read a Geometry from GeoRSS using the GeoRSSReader
String georss = "<georss:point>46.237 -123.15</georss:point>"
GeoRSSReader reader = new GeoRSSReader()
Geometry geometry = reader.read(georss)
geometry read georssreader
Write a Geometry to GeoRSS using the GeoRSSWriter
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

Read a Geometry from a Google Polyline Encoded String using the GeoRSSReader
String str = "_p~iF~ps|U_ulLnnqC_mqNvxq`@"
GooglePolylineEncoder encoder = new GooglePolylineEncoder()
Geometry geometry = encoder.read(str)
geometry read googlepolyline
Write a Geometry to a Google Polyline Encoded String using the GeoRSSWriter
Geometry geometry = new LineString(
        [3.198, 43.164],
        [6.713, 49.755],
        [9.702, 42.592],
        [15.32, 53.798]
)
GooglePolylineEncoder encoder = new GooglePolylineEncoder()
String str = encoder.write(geometry)
println str
_nmfGoroRwhfg@womTv_vj@gxfQotkcAogha@

YAML

Get a Geometry from a GeoYaml String
        String yaml = """---
geometry:
    type: "Point"
    coordinates:
    - -122.23
    - 45.67
"""
        Geometry geometry = Geometry.fromYaml(yaml)
geometry from yaml
Get GeoYaml from a Geometry
Geometry geometry = new Point(-123.15, 46.237)
String yaml = geometry.yaml
println yaml
---
geometry:
  type: Point
  coordinates:
  - -123.15
  - 46.237
Read a Geometry from a GeoYaml String using the YamlReader
        String yaml = """---
geometry:
    type: "Point"
    coordinates:
    - -122.23
    - 45.67
"""
        YamlReader reader = new YamlReader()
        Geometry geometry = reader.read(yaml)
geometry read yaml
Write a Geometry to a GeoYaml String using the YamlWriter
Geometry geometry = new LineString(
        [3.198, 43.164],
        [6.713, 49.755],
        [9.702, 42.592],
        [15.32, 53.798]
)
YamlWriter writer = new YamlWriter()
String yaml = writer.write(geometry)
println yaml
---
geometry:
  type: LineString
  coordinates:
  - - 3.198
    - 43.164
  - - 6.713
    - 49.755
  - - 9.702
    - 42.592
  - - 15.32
    - 53.798

Bounds Recipes

The Bounds class is in the geoscript.geom package.

It represents a minimum bounding box or rectangle, so it has minimum and maximum x and y coordinates in a specified projection.

Creating Bounds

Create a Bounds from four coordinates (minx, miny, maxx, maxy) and a projection.
Bounds bounds = new Bounds(-127.265, 43.068, -113.554, 50.289, "EPSG:4326")
geometry create bounds
Create a Bounds from four coordinates (minx, miny, maxx, maxy) without a projection. The projection can be set later.
Bounds bounds = new Bounds(-127.265, 43.068, -113.554, 50.289)
bounds.proj = new Projection("EPSG:4326")
geometry create bounds no proj
Create a Bounds from a string with commas delimiting minx, miny, maxx, maxy and projection values.
Bounds bounds = Bounds.fromString("-127.265,43.068,-113.554,50.289,EPSG:4326")
geometry create bounds fromstring withcommas
Create a Bounds from a string with spaces delimiting minx, miny, maxx, maxy and projection values.
Bounds bounds = Bounds.fromString("12.919921874999998 40.84706035607122 15.99609375 41.77131167976407 EPSG:4326")
geometry create bounds fromstring withspaces

Getting Bounds Properties

Create a Bounds and view it’s string representation
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)
Get the minimum x coordinate
double minX = bounds.minX
println minX
-127.265
Get the minimum y coordinate
double minY = bounds.minY
println minY
43.068
Get the maximum x coordinate
double maxX = bounds.maxX
println maxX
-113.554
Get the maximum y coordinate
double maxY = bounds.maxY
println maxY
50.289
Get the Projection
Projection proj = bounds.proj
println proj.id
EPSG:4326
Get the area
double area = bounds.area
println area
99.00713100000004
Get the width
double width = bounds.width
println width
13.710999999999999
Get the height
double height = bounds.height
println height
7.221000000000004
Get the aspect ratio
double aspect = bounds.aspect
println aspect
1.8987674837280144
A Bounds is not a Geometry but you can get a Geometry from a Bounds
Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
Geometry geometry = bounds.geometry
geometry bounds geometry
You can also get a Polygon from a Bounds
Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
Polygon polygon = bounds.polygon
geometry bounds polygon
Get the four corners from a Bounds as a List of Points
Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
List<Point> points = bounds.corners
geometry bounds corners

Processing Bounds

Reproject a Bounds from one Projection to another.
Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
println bounds
(-122.485,47.246,-122.452,47.267,EPSG:4326)
Bounds reprojectedBounds = bounds.reproject("EPSG:2927")
println reprojectedBounds
(1147444.7684518,703506.2231641796,1155828.1202425023,711367.9403610165,EPSG:2927)
Expand a Bounds by a given distance
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)
geometry bounds expandby
Expand a Bounds to include another Bounds
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)
geometry bounds expand
Scale an existing Bounds some distance to create a new Bounds
Bounds bounds1 = new Bounds(-127.265, 43.068, -113.554, 50.289, "EPSG:4326")
Bounds bounds2 = bounds1.scale(2)
geometry bounds scale
Divide a Bounds into smaller tiles or Bounds
Bounds bounds = new Bounds(-122.485, 47.246, -122.452, 47.267, "EPSG:4326")
List<Bounds> subBounds = bounds.tile(0.25)
geometry bounds tile
Calculate a quad tree for this Bounds between the start and stop levels. A Closure is called for each new Bounds generated.
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)
Determine whether a Bounds is empty or not. A Bounds is empty if it is null or it’s area is 0.
Bounds bounds = new Bounds(0,10,10,20)
println bounds.isEmpty()
false
Bounds emptyBounds = new Bounds(0,10,10,10)
println emptyBounds.isEmpty()
true
Determine if a Bounds contains another Bounds
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)
geometry bounds contains bounds1
true
Bounds bounds3 = new Bounds(-112.412, 36.809, -99.316, 44.777)
println bounds1.contains(bounds3)
geometry bounds contains bounds2
false
Determine if a Bounds contains a Point
Bounds bounds = new Bounds(-107.226, 34.597, -92.812, 43.068)
Point point1 = new Point(-95.976, 39.639)
println bounds.contains(point1)
geometry bounds contains point1
true
Point point2 = new Point(-89.384, 38.959)
println bounds.contains(point2)
geometry bounds contains point2
true
Determine if two Bounds intersect
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)
geometry bounds intersects1
false
Bounds bounds3 = new Bounds(-95.904, 46.747, -95.839, 46.792)
println bounds1.intersects(bounds3)
geometry bounds intersects2
true
Calculate the intersection between two Bounds
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)
geometry bounds intersection
Generate a grid from a Bounds with a given number of columns and rows and the polygon shape. Other shapes include: polygon, point, circle/ellipse, hexagon, hexagon-inv).
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(5,4,"polygon")
geometry bounds grid polygon colsrows
Generate a grid from a Bounds with a given number of columns and rows and a point shape. A Closure that is called with a geometry, column, and row for each grid cell that is created.
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)
}
geometry bounds grid point colsrows
Generate a grid from a Bounds with a given cell width and height and a circle/ellipse shape.
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(72.0,72.0,"circle")
geometry bounds grid circle cellwidthheight
Generate a grid from a Bounds with a given cell width and height and a hexagon shape. A Closure is called with a geometry, column, and row for each grid cell generated.
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)
}
geometry bounds grid hexagon cellwidthheight
Generate a grid from a Bounds with a given cell width and height and an inverted hexagon shape.
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(5,5,"hexagon-inv")
geometry bounds grid hexagoninv colsrows
Generate a grid from a Bounds with a given cell width and height and a triangle shape.
Bounds bounds = new Bounds(-180,-90,180,90,"EPSG:4326")
Geometry geometry = bounds.getGrid(5,5,"triangle")
geometry bounds grid triangle colsrows
Create a rectangle from a Bounds with a given number of Points and a rotation angle in radians.
Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createRectangle(20,Math.toRadians(45))
geometry bounds createrectangle
Create an ellipse from a Bounds. The default number of points is 20 and the default rotation angle in radians is 0.
Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createEllipse()
geometry bounds createreellipse
Create a squircle from a Bounds. The default number of points is 20 and the default rotation angle in radians is 0.
Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createSquircle()
geometry bounds createresquircle
Create a super circle from a Bounds with a given power. The default number of points is 20 and the default rotation angle in radians is 0.
Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createSuperCircle(1.75)
geometry bounds createresupercircle
Create an arc from a Bounds with a start angle and angle extent. The default number of points is 20 and the default rotation angle in radians is 0.
Bounds bounds = new Bounds(0,0,20,20)
LineString lineString = bounds.createArc(Math.toRadians(45), Math.toRadians(90))
geometry bounds createrearc
Create an arc polygon from a Bounds with a start angle and angle extent. The default number of points is 20 and the default rotation angle in radians is 0.
Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createArcPolygon(Math.toRadians(45), Math.toRadians(90))
geometry bounds createrearcpolygon
Create a sine star from a Bounds with a number of arms and an arm length ratio. The default number of points is 20 and the default rotation angle in radians is 0.
Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createSineStar(5, 2.3)
geometry bounds createsinestar
Create a hexagon from a Bounds that is either inverted (false) or not (true).
Bounds bounds = new Bounds(0,0,20,20)
Polygon polygon = bounds.createHexagon(false)
geometry bounds createhexagon

Projection Recipes

The Projection classes are in the geoscript.proj package.

Creating Projections

Create a Projection from an EPSG Code
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"]]
Create a Projection from a WKT Projection String
      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"]]
Create a Projection from well known name
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]]
Get a List of all supported Projections (this is really slow)
List<Projection> projections = Projection.projections()
EPSG:4326
EPSG:4269
EPSG:26918
EPSG:2263
EPSG:2927
...

Getting Projection Properties

Get the id
Projection proj = new Projection("EPSG:4326")
String id = proj.id
EPSG:4326
Get the srs
String srs = proj.srs
EPSG:4326
Get the epsg code
int epsg = proj.epsg
4326
Get the WKT
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"]]
Get the Bounds in the native Projection
Bounds bounds = proj.bounds
(-180.0,-90.0,180.0,90.0,EPSG:4326)
Get the Bounds in the EPSG:4326
Bounds geoBounds = proj.geoBounds
(-180.0,-90.0,180.0,90.0,EPSG:4326)

Using Projections

Transform a Geometry from one projection to another using the Projection static method with strings
Geometry epsg4326Geom = new Point(-122.440, 47.245)
Geometry epsg2927Geom = Projection.transform(epsg4326Geom, "EPSG:4326", "EPSG:2927")
println epsg2927Geom
POINT (1158609.2040371664 703068.0661327793)
Transform a Geometry from one projection to another using the Projection static method with Projections
Projection epsg4326 = new Projection("EPSG:4326")
Projection epsg2927 = new Projection("EPSG:2927")
Geometry epsg4326Geom = new Point(-122.440, 47.245)
Geometry epsg2927Geom = Projection.transform(epsg4326Geom, epsg4326, epsg2927)
println epsg2927Geom
POINT (1158609.2040371664 703068.0661327793)
Transform a Geometry from one projection to another using two Projections
Projection fromProj = new Projection("EPSG:4326")
Projection toProj = new Projection("EPSG:2927")
Geometry geom = new Point(-122.440, 47.245)
Geometry projectedGeom = fromProj.transform(geom, toProj)
println projectedGeom
POINT (1158609.2040371664 703068.0661327793)
Transform a Geometry from one projection to another using a Projections and a String
Projection fromProj = new Projection("EPSG:4326")
Geometry geom = new Point(-122.440, 47.245)
Geometry projectedGeom = fromProj.transform(geom, "EPSG:2927")
println projectedGeom
POINT (1158609.2040371664 703068.0661327793)

Using Geodetic

Create a Geodetic object with an ellipsoid
Geodetic geodetic = new Geodetic("wgs84")
println geodetic
Geodetic [SPHEROID["WGS 84", 6378137.0, 298.257223563]]
Calculate the forward and back azimuth and distance between the given two Points.
Geodetic geodetic = new Geodetic("clrk66")
Point bostonPoint = new Point(-71.117, 42.25)
Point portlandPoint = new Point(-123.683, 45.52)
Map results = geodetic.inverse(bostonPoint, portlandPoint)
double forwardAzimuth =  results.forwardAzimuth
println forwardAzimuth
-66.52547810974724
double backAzimuth = results.backAzimuth
println backAzimuth
75.65817457195088
double distance = results.distance
println distance
4164050.459880065
Calculate a new Point and back azimuth given the starting Point, azimuth, and distance.
Geodetic geodetic = new Geodetic("clrk66")
Point bostonPoint = new Point(-71.117, 42.25)
Map results = geodetic.forward(bostonPoint, -66.531, 4164192.708)
Point point = results.point
println point
POINT (-123.6835797667373 45.51642779589723)
double azimuth = results.backAzimuth
println azimuth
75.65337425050723
Place the given number of points between starting and ending Points
Geodetic geodetic = new Geodetic("clrk66")
Point bostonPoint = new Point(-71.117, 42.25)
Point portlandPoint = new Point(-123.683, 45.52)
List<Point> points = geodetic.placePoints(bostonPoint, portlandPoint, 10)
points.each { Point point ->
    println point.wkt
}
POINT (-75.41357382496236 43.52791689304304)
POINT (-79.8828640042499 44.63747566950249)
POINT (-84.51118758826816 45.565540142641005)
POINT (-89.27793446221685 46.300124344169255)
POINT (-94.15564606698499 46.83102721803566)
POINT (-99.11079892605703 47.15045006457598)
POINT (-104.10532353179985 47.25351783423774)
POINT (-109.09873812691617 47.13862709798196)
POINT (-114.05062990603696 46.80756425557422)
POINT (-118.92312608779855 46.26537395700513)

Using Decimal Degrees

Create a new DecimalDegrees from a longitude and latitude
DecimalDegrees decimalDegrees = new DecimalDegrees(-122.525619, 47.212023)
println decimalDegrees
-122° 31' 32.2284" W, 47° 12' 43.2828" N
Create a new DecimalDegrees from a Point
DecimalDegrees decimalDegrees = new DecimalDegrees(new Point(-122.525619,47.212023))
println decimalDegrees
POINT (-122.52561944444444 47.212022222222224)
Create a new DecimalDegrees from a Longitude and Latitude string
DecimalDegrees decimalDegrees = new DecimalDegrees("-122.525619, 47.212023")
println decimalDegrees
-122° 31' 32.2284" W, 47° 12' 43.2828" N
Create a new DecimalDegrees from two strings with glyphs
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
Create a new DecimalDegrees from two strings
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
Create a new DecimalDegrees from a single Degrees Minutes Seconds formatted string
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
Create a new DecimalDegrees from a single Decimal Degree Minutes formatted string with glyphs
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
Create a new DecimalDegrees from a single Decimal Degree Minutes formatted string
DecimalDegrees decimalDegrees = new DecimalDegrees("122d 31.5372m W, 47d 12.7213m N")
println decimalDegrees
-122° 31' 32.2320" W, 47° 12' 43.2780" N
Get degrees minutes seconds from a DecimalDegrees object
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
Convert a DecimalDegrees object to a DMS String with glyphs
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
Convert a DecimalDegrees object to a DMS String without glyphs
println decimalDegrees.toDms(false)
-122d 31m 32.2300s W, 47d 12m 43.2800s N
Get degrees minutes from a DecimalDegrees object
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
Convert a DecimalDegrees object to a DDM String with glyphs
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
Convert a DecimalDegrees object to a DDM String without glyphs
println decimalDegrees.toDdm(false)
-122d 31.5372m W, 47d 12.7213m N
Get a Point from a DecimalDegrees object
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

Create a STRtree spatial index
STRtree index = new STRtree()
Insert Geometries and their Bounds
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))
Get the size of the index
int size = index.size
println size
4
Query the index
List results = index.query(new Bounds(1,1,5,5))
results.each { Geometry geometry ->
    println geometry
}
POINT (4 4)
POINT (5 5)

Using HPRtree

Create a HPRtree spatial index
HPRtree index = new HPRtree()
Insert Geometries and their Bounds
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))
Get the size of the index
int size = index.size
println size
4
Query the index
List results = index.query(new Bounds(1,1,5,5))
results.each { Geometry geometry ->
    println geometry
}
POINT (5 5)
POINT (4 4)

Using Quadtree

Create a Quadtree spatial index
Quadtree index = new Quadtree()
Insert Geometries and their Bounds
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))
Get the size of the index
int size = index.size
println size
4
Query the index with a Bounds
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)
Query the entire index
List allResults = index.queryAll()
allResults.each { Geometry geometry ->
    println geometry
}
POINT (30 30)
POINT (32 32)
POINT (5 5)
POINT (4 4)
Remove an item from the index
Geometry itemToRemove = allResults[0]
boolean removed = index.remove(itemToRemove.bounds, itemToRemove)
println "Removed? ${removed}"
println "Size = ${index.size}"
Removed = true
Size = 3

Using GeoHash

Encode a Point as a String
GeoHash geohash = new GeoHash()
Point point = new Point(112.5584, 37.8324)
String hash = geohash.encode(point)
println hash
ww8p1r4t8
Decode a Point from a String
GeoHash geohash = new GeoHash()
Point point = geohash.decode("ww8p1r4t8")
println point
POINT (112.55838632583618 37.83238649368286)
Encode a Point as a Long
GeoHash geohash = new GeoHash()
Point point = new Point(112.5584, 37.8324)
long hash = geohash.encodeLong(point)
println long
4064984913515641
Decode a Point from a Long
GeoHash geohash = new GeoHash()
Point point = geohash.decode(4064984913515641)
println point
POINT (112.55839973688126 37.83240124583244)
Decode a Bounds from a String
GeoHash geohash = new GeoHash()
Bounds bounds = geohash.decodeBounds("ww8p1r4t8")
println bounds
(112.55836486816406,37.83236503601074,112.5584077835083,37.83240795135498)
Decode a Bounds from a Long
GeoHash geohash = new GeoHash()
Bounds bounds = geohash.decodeBounds(4064984913515641)
println bounds
(112.55836486816406,37.83236503601074,112.5584077835083,37.83240795135498)
Find neighboring geohash strings
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
Find neighboring geohash longs
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
Find all neighboring geohash strings
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
Find all neighboring geohash longs
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
Find all geohashes as strings within a Bounds
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
Find all geohashes as longs within a Bounds
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

Draw a geometry in a simple GUI
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)
viewer draw
Draw a geometry to an image
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)
viewer draw2image
Draw a geometry to an image with options
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
)
viewer draw2imagewithoptions
Draw a List of geometries to an image
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
)
viewer draw2imagegeometries
Draw a List of Geometries to a File
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])
viewer drawtofile
Draw a Geometry to a Base64 Encoded String
Polygon polygon = new Polygon([[
       [-101.35986328125, 47.754097979680026],
       [-101.5576171875, 46.93526088057719],
       [-100.12939453125, 46.51351558059737],
       [-99.77783203125, 47.44294999517949],
       [-100.45898437499999, 47.88688085106901],
       [-101.35986328125, 47.754097979680026]
]])
String base64EncodedString = Viewer.drawToBase64EncodedString(polygon)
println base64EncodedString
image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADL1t+KAAAR/ElEQVR4Xu3bC47kxrVFUc1VA30z0JT8ELKvXXWU9UkyfiTXBhZg2SmpO8jk...

Plotting geometries

Plot a geometry in a simple GUI
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)
viewer plot
Plot a Geometry to an image
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)
viewer plot2image
Plot a List of Geometries to an image
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
)
viewer plot2imagegeometries
Plot a Geometry to a File
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])
viewer plottofile

Plot Recipes

The Plot classes are in the geoscript.plot package.

Processing Charts

Show a chart in a GUI
List data = [
        [1,10],[45,12],[23,3],[5,20]
]
Chart chart = Bar.xy(data)
plot show
Get an image from a chart
Map data = [
        "A":20,"B":45,"C":2,"D":14
]
Chart chart = Pie.pie(data)
BufferedImage image = chart.image
plot getimage
Save a chart to a file
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)
plot save
Overlay multiple charts
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])
plot overlay

Creating Bar Charts

Create a basic bar chart
List data = [
        [1,10],[45,12],[23,3],[5,20]
]
Chart chart = Bar.xy(data)
plot bar chart
Create a bar chart with categories
Map data = [
        "A":20,"B":45,"C":2,"D":14
]
Chart chart = Bar.category(data)
plot bar chart with categories
Create a stacked bar chart with two series of data
Map data = [
        "A": ["B":50,"C":25,"D":25],
        "F": ["G":75,"H":10,"I":15]
]
Chart chart = Bar.category(data, stacked: true)
plot bar chart with categories stacked
Create a 3D bar chart with categories
Map data = [
        "A":20,"B":45,"C":2,"D":14
]
Chart chart = Bar.category(data, trid: true)
plot bar chart with categories 3d

Creating Pie Charts

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

Creating Box Charts

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

Creating Curve Charts

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

Creating Regression Charts

Create a linear regression chart
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)
plot linear regression
Create a power regression chart
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)
plot power regression

Creating Scatter Plot Charts

Create a scatter plot chart
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)
plot scatterplot
Create a scatter plot chart with options
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")
plot scatterplot options

Feature Recipes

The Feature classes are in the geoscript.feature package.

The major classes in this package include Field, Schema, and Feature.

A Field has a name and a type and describes a column of data.

A Schema is a collection of Fields together with a name. Schemas are used to create new Layers.

A Feature contains a geometry and a collection of attributes. A collection of Features is called a Layer.

Creating Fields

Create a Field with a name and a type
Field field = new Field("name", "String")
println field
name: String
Create a Geometry Field with a name and a geometry type and an optional projection
Field field = new Field("geom", "Point", "EPSG:4326")
println field
geom: Point(EPSG:4326)
Create a Field with a List of Strings (name, type, projection)
Field field = new Field(["geom", "Polygon", "EPSG:4326"])
println field
geom: Polygon(EPSG:4326)
Create a Field from a Map where keys are name, type, proj
Field field = new Field([
        "name": "geom",
        "type": "LineString",
        "proj": new Projection("EPSG:4326")
])
println field
geom: LineString(EPSG:4326)
Access a Field’s properties
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

Create a Schema from a list of Fields
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
Create a Schema from a list of Lists
Schema schema = new Schema("cities", [
        ["geom", "Point", "EPSG:4326"],
        ["id", "Integer"],
        ["name", "String"]
])
println schema
cities geom: Point(EPSG:4326), id: Integer, name: String
Create a Schema from a list of Maps
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
Create a Schema from a 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

Get the Schema’s name
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
Get the Schema’s geometry Field
Field geomField = schema.geom
println geomField
geom: Point(EPSG:4326)
Get the Schema’s Projection
Projection proj = schema.proj
println proj
EPSG:4326
Get the Schema’s URI
String uri = schema.uri
println uri
https://github.com/jericks/geoscript-groovy-cookbook
Get the Schema’s specification string
String spec = schema.spec
println spec
geom:Point:srid=4326,id:Integer,name:String

Getting Schema Fields

Get the Schema’s 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
Get a Field
Field nameField = schema.field("name")
println nameField
name: String
Get a Field
Field idField = schema.get("id")
println idField
id: Integer
Check if a Schema has a Field
boolean hasArea = schema.has("area")
println "Has area Field? ${hasArea}"

boolean hasGeom = schema.has("geom")
println "Has geom Field? ${hasGeom}"
false
true

Modifying Schemas

Change the projection of a Schema
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
Change the geometry type of a Schema
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
Change a Field definition of a Schema
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
Change Field definitions of a Schema
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
Add a Field to a Schema
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
Add a List of Fields to a Schema
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
Remove a Field from a Schema
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
Remove a List of Fields from a Schema
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
Create a new Schema from an existing Schema but only including a subset of Fields
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.

Combine two Schemas with no duplicate fields and no postfixes to field names
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]
Combine two Schemas with no duplicate fields and postfixes
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

Create a Feature from a Schema with a Map of values
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
Create a Feature from a Schema with a List of values. The order of the values must match the order of the Fields.
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
Create a Feature from a Schema with another Feature.
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
Create an empty Feature 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()
println feature
cities.fid-6908cacc_18a62461511_-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 all Schema Writers
List<SchemaWriter> writers = SchemaWriters.list()
writers.each { SchemaWriter writer ->
    println writer.class.simpleName
}
JsonSchemaWriter
StringSchemaWriter
XmlSchemaWriter
Find a Schema Writer
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 all Schema Readers
List<SchemaReader> readers = SchemaReaders.list()
readers.each { SchemaReader reader ->
    println reader.class.simpleName
}
JsonSchemaReader
StringSchemaReader
XmlSchemaReader
Find a Schema Reader
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

Read a Schema from a 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
Write a Schema to a 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

Read a Schema from a 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
Write a Schema to a JSON
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

Read a Schema from a 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
Write a Schema to a XML
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

Create an empty Feature from a Map of values and a Schema.
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
Create an empty Feature from a List of values and a Schema.
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
Create an empty Feature from a Map of values. The Schema is inferred from the values.
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

Get a Feature’s ID
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
Get a Feature’s Geometry
Geometry geometry = feature.geom
println geometry
POINT (-122.3204 47.6024)
Get a Feature’s Bounds
Bounds bounds = feature.bounds
println bounds
(-122.3204,47.6024,-122.3204,47.6024,EPSG:4326)
Get a Feature’s attributes
Map attributes = feature.attributes
println attributes
[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]

Getting Feature Attributes

Get an attribute from a Feature using a Field name
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
Get an attribute from a Feature using a Field
String name = feature.get(schema.field("name"))
println name
Seattle
Set an attribute of a Feature using a Field name and a new value
feature.set("name", "Tacoma")
println feature["name"]
Tacoma
Set an attribute of a Feature using a Field and a new value
feature.set(schema.field("name"), "Mercer Island")
println feature["name"]
Mercer Island
Set attributes of a Feature using a Map of new values
feature.set([id: 2])
println feature["id"]
2
Set a new Geometry value
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 all Feature Writers
List<Writer> writers = Writers.list()
writers.each { Writer writer ->
    println writer.class.simpleName
}
GeobufWriter
GeoJSONWriter
GeoRSSWriter
GmlWriter
GpxWriter
KmlWriter
YamlWriter
Find a Feature Writer
Writer writer = Writers.find("geojson")
println writer.class.simpleName
GeoJSONWriter
List all Feature Readers
List<Reader> readers = Readers.list()
readers.each { Reader reader ->
    println reader.class.simpleName
}
GeobufReader
GeoJSONReader
GeoRSSReader
GmlReader
GpxReader
KmlReader
YamlReader
Find a Feature Reader
Reader reader = Readers.find("geojson")
println reader.class.simpleName
GeoJSONReader

GeoJSON

Get a GeoJSON String from a Feature
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"}
Write a Feature to 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)

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"}
Get a Feature from GeoJSON
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)
Read a Feature from GeoJSON
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

Get a GeoBuf String from a Feature
Schema schema = new Schema("cities", [
        new Field("geom", "Point", "EPSG:4326"),
        new Field("id", "Integer"),
        new Field("name", "String")
])
Feature feature = new Feature([
        new Point(-122.3204, 47.6024),
        1,
        "Seattle"
], "city.1", schema)

String geobuf = feature.geobuf
println geobuf
0a0269640a046e616d65100218062a2b0a0c08001a089fd8d374c0ebb22d5a06636974792e316a0218016a090a0753656174746c65720400000101
Get a Feature from a GeoBuf String
String geobuf = '0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65'
Feature feature = Feature.fromGeobuf(geobuf)
println feature
features. geom: POINT (-122.3204 47.6024), id: 1, name: Seattle
Write a Feature to a GeoBuf String
Schema schema = new Schema("cities", [
        new Field("geom", "Point", "EPSG:4326"),
        new Field("id", "Integer"),
        new Field("name", "String")
])
Feature feature = new Feature([
        new Point(-122.3204, 47.6024),
        1,
        "Seattle"
], "city.1", schema)

GeobufWriter writer = new GeobufWriter()
String geobuf = writer.write(feature)
println geobuf
0a0269640a046e616d65100218062a2b0a0c08001a089fd8d374c0ebb22d5a06636974792e316a0218016a090a0753656174746c65720400000101
Read a Feature from a GeoBuf String
GeobufReader reader = new GeobufReader()
String geobuf = '0a0269640a046e616d65100218062a1d0a0c08001a089fd8d374c0ebb22d6a0218016a090a0753656174746c65'
Feature feature = reader.read(geobuf)
println feature
features. geom: POINT (-122.3204 47.6024), id: 1, name: Seattle

GeoRSS

Get a GeoRSS String from a Feature
Schema schema = new Schema("cities", [
        new Field("geom", "Point", "EPSG:4326"),
        new Field("id", "Integer"),
        new Field("name", "String")
])
Feature feature = new Feature([
        new Point(-122.3204, 47.6024),
        1,
        "Seattle"
], "city.1", schema)

String georss = feature.geoRSS
println georss
<entry xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'><title>city.1</title><summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary><updated>Mon Sep 04 22:17:55 UTC 2023</updated><georss:point>47.6024 -122.3204</georss:point></entry>
Get a Feature from a GeoRSS String
        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-6908cacc_18a62461511_-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)
Write a Feature to a GeoRSS String
Schema schema = new Schema("cities", [
        new Field("geom", "Point", "EPSG:4326"),
        new Field("id", "Integer"),
        new Field("name", "String")
])
Feature feature = new Feature([
        new Point(-122.3204, 47.6024),
        1,
        "Seattle"
], "city.1", schema)

GeoRSSWriter writer = new GeoRSSWriter()
String georss = writer.write(feature)
println georss
<entry xmlns:georss='http://www.georss.org/georss' xmlns='http://www.w3.org/2005/Atom'><title>city.1</title><summary>[geom:POINT (-122.3204 47.6024), id:1, name:Seattle]</summary><updated>Mon Sep 04 22:17:55 UTC 2023</updated><georss:point>47.6024 -122.3204</georss:point></entry>
Read a Feature from a GeoRSS String
        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-6908cacc_18a62461511_-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

Get a GML String from a Feature
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>
Get a Feature from a GML String
        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)
Write a Feature to a GML String
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>
Read a Feature from a GML String
        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

Get a GPX String from a Feature
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>
Get a Feature from a GPX String
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-6908cacc_18a62461511_-7ffd geom: POINT (-122.3204 47.6024), name: city.1
Write a Feature to a GPX String
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>
Read a Feature from a GPX String
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-6908cacc_18a62461511_-7fff geom: POINT (-122.3204 47.6024), name: city.1

KML

Get a KML String from a Feature
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>
Get a Feature from a KML String
        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)
Write a Feature to a KML String
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>
Read a Feature from a KML String
        KmlReader reader = new KmlReader()
        String kml = """<kml:Placemark xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1" id="city.1">
    <kml:name>Seattle</kml:name>
    <kml:Point>
        <kml:coordinates>-122.3204,47.6024</kml:coordinates>
    </kml:Point>
</kml:Placemark>"""
        Feature feature = reader.read(kml)
        println feature
placemark.city.1 name: Seattle, description: null, Geometry: POINT (-122.3204 47.6024)

YAML

Get a Yaml String from a Feature
Schema schema = new Schema("cities", [
        new Field("geom", "Point", "EPSG:4326"),
        new Field("id", "Integer"),
        new Field("name", "String")
])
Feature feature = new Feature([
        new Point(-122.3204, 47.6024),
        1,
        "Seattle"
], "city.1", schema)

String yaml = feature.yaml
println yaml
---
type: Feature
properties:
  id: 1
  name: Seattle
geometry:
  type: Point
  coordinates:
  - -122.3204
  - 47.6024
Get a Feature from a Yaml String
        String yaml = """---
type: "Feature"
properties:
  id: 1
  name: "Seattle"
geometry:
  type: "Point"
  coordinates:
  - -122.3204
  - 47.6024
"""
        Feature feature = Feature.fromYaml(yaml)
        println feature
feature.1 id: 1, name: Seattle, geom: POINT (-122.3204 47.6024)
Write a Feature to a YAML String
Schema schema = new Schema("cities", [
        new Field("geom", "Point", "EPSG:4326"),
        new Field("id", "Integer"),
        new Field("name", "String")
])
Feature feature = new Feature([
        new Point(-122.3204, 47.6024),
        1,
        "Seattle"
], "city.1", schema)

YamlWriter writer = new YamlWriter()
String yml = writer.write(feature)
println yml
---
type: Feature
properties:
  id: 1
  name: Seattle
geometry:
  type: Point
  coordinates:
  - -122.3204
  - 47.6024
Read a Feature from a YAML String
        YamlReader reader = new YamlReader()
        String yml = """---
type: "Feature"
properties:
  id: 1
  name: "Seattle"
geometry:
  type: "Point"
  coordinates:
  - -122.3204
  - 47.6024
"""
        Feature feature = reader.read(yml)
        println feature
feature.1 id: 1, name: Seattle, geom: POINT (-122.3204 47.6024)

Filter Recipes

The Filter classes are in the geoscript.filter package.

Creating Filters

Create a Filter from a CQL string
Filter filter = new Filter("name='Seattle'")
println filter.toString()
[ name = Seattle ]
Create a Filter from a CQL string
Filter filter = new Filter("<filter><PropertyIsEqualTo><PropertyName>soilType</PropertyName><Literal>Mollisol</Literal></PropertyIsEqualTo></filter>")
println filter.toString()
[ soilType = Mollisol ]
Create a pass Filter that return true for everything
Filter filter = Filter.PASS
println filter.toString()
Filter.INCLUDE
Create a fail Filter that return false for everything
Filter filter = Filter.FAIL
println filter.toString()
Filter.EXCLUDE
Create a spatial bounding box Filter from a Bounds
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] ]
Create a spatial contains Filter from a Geometry
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)) ]
Create a spatial distance within Filter from a Geometry and a distance
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 ]
Create a spatial crosses Filter from a Geometry
Filter filter = Filter.crosses("the_geom", Geometry.fromWKT("LINESTRING (-104 45, -95 45)"))
println filter.toString()
[ the_geom crosses LINESTRING (-104 45, -95 45) ]
Create a spatial intersects Filter from a Geometry
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)) ]
Create a feature id Filter
Filter filter = Filter.id("points.1")
println filter.toString()
[ points.1 ]
Create a feature ids Filter
Filter filter = Filter.ids(["points.1","points.2","points.3"])
println filter.toString()
[ points.1, points.2, points.3 ]
Create an equals Filter
Filter filter = Filter.equals("name", "Washington")
println filter.toString()
[ name = Washington ]

Using Filters

Get a CQL string from a Filter
Filter filter = new Filter("name='Seattle'")
String cql = filter.cql
println cql
name = 'Seattle'
Get an XML string from a Filter
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>
Combine Filters with and
Filter cityFilter = new Filter("city = 'Seattle'")
Filter stateFilter = new Filter("state = 'WA'")
Filter andFilter = cityFilter.and(stateFilter)
println andFilter
[[ city = Seattle ] AND [ state = WA ]]
Combine Filters with and using the plus operator
Filter cityFilter = new Filter("city = 'Seattle'")
Filter stateFilter = new Filter("state = 'WA'")
Filter andFilter = cityFilter + stateFilter
println andFilter
[[ city = Seattle ] AND [ state = WA ]]
Combine Filters with or
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter tacomaFilter = new Filter("city = 'Tacoma'")
Filter orFilter = seattleFilter.or(tacomaFilter)
println orFilter
[[ city = Seattle ] OR [ city = Tacoma ]]
Negate a Filter
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter notSeattleFilter = seattleFilter.not
println notSeattleFilter
[ NOT [ city = Seattle ] ]
Negate a Filter using the minus operator
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter notSeattleFilter = -seattleFilter
println notSeattleFilter
[ NOT [ city = Seattle ] ]
Simplify a Filter
Filter seattleFilter = new Filter("city = 'Seattle'")
Filter filter = (seattleFilter + Filter.PASS).simplify()
println filter
[ city = Seattle ]

Evaluating Filters

Test to see if a Filter matches a Feature by attribute
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
Test to see if a Filter matches a Feature by feature id
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
Test to see if a Filter matches a Feature by a spatial bounding box
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

Create a literal Expression from a number
Expression expression = new Expression(3.56)
println expression
3.56
Create a literal Expression from a string
Expression expression = new Expression("Seattle")
println expression
Seattle
Evaluating a literal Expression just gives you the value
Expression expression = new Expression(3.56)
double number = expression.evaluate()
println number
3.56

Creating Properties

Create a Property from a string
Property property = new Property("name")
println property
name
Create a Property from a Field
Field field = new Field("geom", "Polygon")
Property property = new Property(field)
println property
geom

Evaluating Properties

Evaluate a Property to get values from a Feature. Get the id
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
Get the name
Property nameProperty = new Property("name")
String name = nameProperty.evaluate(feature)
println name
Seattle
Get the geometry
Property geomProperty = new Property("geom")
Geometry geometry = geomProperty.evaluate(feature)
println geometry
POINT (-122.3204 47.6024)

Creating Functions

Create a Function from a CQL string
Function function = new Function("centroid(the_geom)")
println function
centroid([the_geom])
Create a Function from a name and Expressions
Function function = new Function("centroid", new Property("the_geom"))
println function
centroid([the_geom])
Create a Function from a name, a Closure, and Expressions
Function function = new Function("my_centroid", {g-> g.centroid}, new Property("the_geom"))
println function
my_centroid([the_geom])
Create a Function from a CQL string and a Closure
Function function = new Function("my_centroid(the_geom)", {g-> g.centroid})
println function
my_centroid([the_geom])
You can get a list of built in Functions
List<String> functionNames = Function.getFunctionNames()
println "There are ${functionNames.size()} Functions:"
functionNames.sort().subList(0,10).each { String name ->
    println name
}
There are 318 Functions:
And
Area
Categorize
Collection_Average
Collection_Bounds
Collection_Count
Collection_Max
Collection_Median
Collection_Min
Collection_Nearest

Evaluating Functions

Evaulate a geometry Function
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)
filter function evaluate buffer
Evaulate a geometry Function
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.

Create a Function from a Process that converts geometries in a Layer into a convexhull.
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
createFunctionProcess
Create a ProcessFunction from a Process that converts geometries in a Layer into a bounds.
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
createProcessFunction

Creating Colors

Create a Color from a RGB color string
Color color = new Color("0,255,0")
filter color rbgstring
Create a Color from a CSS color name
Color color = new Color("silver")
filter color csscolorname
Create a Color from a hexadecimal string
Color color = new Color("#0000ff")
filter color hexadecimal
Create a Color from a RGB List
Color color = new Color([255,0,0])
filter color rgblist
Create a Color from a RGB Map
Color color = new Color([r: 5, g: 35, b:45])
filter color rgbmap
Create a Color from a RGB function string
Color color = new Color("rgb(0,128,128)")
filter color rgbs funcstring
Create a Color from a HLS Map
Color color = new Color([h: 0, s: 1.0, l: 0.5])
filter color hlsmap
Create a Color from a HSL function string
Color color = new Color("hsl(0,1,0.5)")
filter color hsl functionstr
Get a Random Color
Color color = Color.getRandom()
filter color random
Get a Random Pastel Color
Color color = Color.getRandomPastel()
filter color random pastel
Get a darker Color
Color color = new Color("lightblue")
Color darkerColor = color.darker()
getDarkerColor
Get a brighter Color
Color color = new Color("purple")
Color brigtherColor = color.brighter()
getBrighterColor

Getting Color Formats

Create a Color
Color color = new Color("wheat")
getColorProperties
Get Hex
String hex = color.hex
println hex
#f5deb3
Get RGB
List rgb = color.rgb
println rgb
[245, 222, 179]
Get HSL
List hsl = color.hsl
println hsl
[0.10858585256755147, 0.7674419030001307, 0.8313725489999999]
Get the java.awt.Color
java.awt.Color awtColor = color.asColor()
println awtColor
java.awt.Color[r=245,g=222,b=179]

Displaying Colors

Draw a List of Colors to a BufferedImage
Color color = new Color("pink")
BufferedImage image = Color.drawToImage(
        [color.brighter(), color, color.darker()],
        "vertical",
        40
)
filter color draw2img
Draw a List of Colors to a simple GUI
List<Color> colors = Color.getPaletteColors("YlOrBr")
Color.draw(colors, "horizontal", 50)
filter color drawgui

Using Color Palettes

Get all color palettes
List<String> allPalettes = Color.getPaletteNames("all")
allPalettes.each { String name ->
    println name
}
PiYG
RdGy
Purples
Reds
BuPu
Set1
PuBuGn
Grays
PuOr
Accents
YlGn
YlOrBr
RdPu
PuRd
RdYlGn
Paired
Set3
Set2
GnBu
YlGnBu
RdYlBu
RdBu
BuGn
BrBG
PRGn
Blues
Greens
OrRd
Dark2
Oranges
Spectral
Pastel2
Pastel1
PuBu
YlOrRd
BlueToOrange
GreenToOrange
BlueToRed
GreenToRedOrange
Sunset
Green
YellowToRedHeatMap
BlueToYellowToRedHeatMap
DarkRedToYellowWhiteHeatMap
LightPurpleToDarkPurpleHeatMap
BoldLandUse
MutedTerrain
BoldLandUse
MutedTerrain
Get diverging color palettes
List<String> divergingPalettes = Color.getPaletteNames("diverging")
divergingPalettes.each { String name ->
    println name
}
PiYG
RdGy
PuOr
RdYlGn
RdYlBu
RdBu
BrBG
PRGn
Spectral
BlueToOrange
GreenToOrange
BlueToRed
GreenToRedOrange
Get sequential color palettes
List<String> sequentialPalettes = Color.getPaletteNames("sequential")
sequentialPalettes.each { String name ->
    println name
}
Purples
Reds
BuPu
PuBuGn
Grays
YlGn
YlOrBr
RdPu
PuRd
GnBu
YlGnBu
BuGn
Blues
Greens
OrRd
Oranges
PuBu
YlOrRd
Sunset
Green
YellowToRedHeatMap
BlueToYellowToRedHeatMap
DarkRedToYellowWhiteHeatMap
LightPurpleToDarkPurpleHeatMap
BoldLandUse
MutedTerrain
Get qualitative color palettes
List<String> qualitativePalettes = Color.getPaletteNames("qualitative")
qualitativePalettes.each { String name ->
    println name
}
Set1
Accents
Paired
Set3
Set2
Dark2
Pastel2
Pastel1
BoldLandUse
MutedTerrain
Get a Blue Green Color Palette
List colors = Color.getPaletteColors("BuGn")
color palette bugn
Get a Purple Color Palette with only four colors
colors = Color.getPaletteColors("Purples", 4)
color palette purples
Get a Blue Green Color Palette
colors = Color.getPaletteColors("MutedTerrain")
color palette mutedterrain
Get a Blue Green Color Palette
colors = Color.getPaletteColors("BlueToYellowToRedHeatMap")
color palette bluetoyellowtoredheatmap
Create a Color palette by interpolating between two colors
Color startColor = new Color("red")
Color endColor = new Color("green")
List<Color> colors = startColor.interpolate(endColor, 10)
filter color interpolate
Create a Color palette by interpolating between two colors
Color startColor = new Color("wheat")
Color endColor = new Color("lightblue")
List<Color> colors = Color.interpolate(startColor, endColor, 8)
filter color interpolate static

Creating Expressions from CQL

Create a literal number Expression from a CQL String
Expression expression = Expression.fromCQL("12")
println expression
12
Create a literal string Expression from a CQL String
Expression expression = Expression.fromCQL("'Washington'")
println expression
Washington
Create a Property from a CQL String
Property property = Expression.fromCQL("NAME")
println property
NAME
Create a Function from a CQL String
Function function = Expression.fromCQL("centroid(the_geom)")
println function
centroid([the_geom])

Create Expression from static imports

You can import short helper methods from the Expressions class.
import static geoscript.filter.Expressions.*
Create a literal
Expression literal = expression(1.2)
Create a Color
Expression color = color("wheat")
Create a Property
Expression property = property("ID")
Create a Function
Expression function = function("max(10,22)")

Process Recipes

The Process classes are in the geoscript.process package.

Execute a built-in Process

Create a Process from a built-in process by name
Process process = new Process("vec:Bounds")
String name = process.name
println name
vec:Bounds
Get the title
String title = process.title
println title
Bounds
Get the description
String description = process.description
println description
Computes the bounding box of the input features.
Get the version
String version = process.version
println version
1.0.0
Get the input parameters
Map parameters = process.parameters
println parameters
[features:class geoscript.layer.Cursor]
Get the output parameters
Map results = process.results
println results
[bounds:class geoscript.geom.Bounds]
Execute the Process to calculate the bounding box of all Features in a Layer
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer layer = workspace.get("places")
Map executeResults = process.execute([features: layer])
Bounds bounds = executeResults.bounds
process execute bounds

Listing built-in Processes

Get the names of all built-in Processes
List<String> processes = Process.processNames
processes.each { String name ->
    println name
}
vec:Aggregate
vec:BarnesSurface
vec:Bounds
vec:BufferFeatureCollection
vec:Centroid
vec:ClassifyByRange
vec:Clip
vec:CollectGeometries
vec:Count
vec:Feature
vec:FeatureClassStats
vec:Grid
vec:GroupCandidateSelection
vec:Heatmap
vec:InclusionFeatureCollection
vec:IntersectionFeatureCollection
vec:LRSGeocode
vec:LRSMeasure
vec:LRSSegment
vec:Nearest
vec:PointBuffers
vec:PointStacker
vec:Query
vec:RectangularClip
vec:Reproject
vec:Simplify
vec:Snap
vec:Transform
vec:UnionFeatureCollection
vec:Unique
vec:VectorToRaster
vec:VectorZonalStatistics
geo:difference
geo:union
geo:isValid
geo:intersects
geo:getX
geo:getY
geo:area
geo:numGeometries
geo:splitPolygon
geo:reproject
geo:isClosed
geo:within
geo:touches
geo:convexHull
geo:crosses
geo:symDifference
geo:boundary
geo:centroid
geo:interiorPoint
geo:getGeometryN
geo:intersection
geo:overlaps
geo:isSimple
geo:isWithinDistance
geo:relate
geo:densify
geo:simplify
geo:startPoint
geo:numPoints
geo:dimension
geo:exteriorRing
geo:numInteriorRing
geo:geometryType
geo:envelope
geo:equalsExact
geo:isRing
geo:polygonize
geo:endPoint
geo:interiorRingN
geo:relatePattern
geo:pointN
geo:equalsExactTolerance
geo:length
geo:buffer
geo:isEmpty
geo:contains
geo:distance
geo:disjoint
polygonlabelprocess:PolyLabeller
centerLine:centerLine
skeltonize:centerLine
ras:AddCoverages
ras:Affine
ras:AreaGrid
ras:BandMerge
ras:BandSelect
ras:Contour
ras:ConvolveCoverage
ras:CoverageClassStats
ras:CropCoverage
ras:Jiffle
ras:MultiplyCoverages
ras:NormalizeCoverage
ras:PolygonExtraction
ras:RangeLookup
ras:RasterAsPointCollection
ras:RasterZonalStatistics
ras:RasterZonalStatistics2
ras:ScaleCoverage
ras:StyleCoverage
ras:TransparencyFill
geoscript:convexhull

Executing a new Process

Create a Process using a Groovy Closure
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
Get the title
String title = process.title
println title
convexhull
Get the description
String description = process.description
println description
Create a convexhull around the features
Get the version
String version = process.version
println version
1.0.0
Get the input parameters
Map parameters = process.parameters
println parameters
[features:class geoscript.layer.Cursor]
Get the output parameters
Map results = process.results
println results
[result:class geoscript.layer.Cursor]
Execute the Process created from a Groovy Closure
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 execute closure

Process Functions

Process Functions are a combination of Functions and Processes that can be used to create rendering transformations.

Create a Function from a Process that converts geometries in a Layer into a convexhull.
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer places = workspace.get("places")
Process process = new Process("convexhull",
        "Create a convexhull around the features",
        [features: geoscript.layer.Cursor],
        [result: geoscript.layer.Cursor],
        { inputs ->
            def geoms = new GeometryCollection(inputs.features.collect{ f -> f.geom})
            println geoms
            def output = new Layer()
            output.add([geoms.convexHull])
            [result: output]
        }
)
Function function = new Function(process, new Function("parameter", new Expression("features")))
Symbolizer symbolizer =  new Transform(function, Transform.RENDERING) + new Fill("aqua", 0.75) + new Stroke("navy", 0.5)
places.style = symbolizer
processFunctionProcess
Create a ProcessFunction from a Process that converts geometries in a Layer into a bounds.
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
processProcessFunction

Render Recipes

The Render classes are in the geoscript.render package.

Creating Maps

Create a Map with Layers and render to a 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]
)
File file = new File("map.png")
map.render(file)
map create
Create a Map with Layers and render to a file name.
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")
map create filename
Create a Map with Layers and render to an 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]
)
File file = new File("map.png")
file.withOutputStream { OutputStream outputStream ->
    map.render(outputStream)
}
map create outputstream
Create a Map with Layers and render to an BufferedImage.
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()
map create image
Create a Map with Layers and render to a Graphics2D object.
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()
map create graphics
Create a Map with Layers and display in a simple UI.
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()
render display map

Map Properties

Get 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)
map properties
Get width and height
int width = map.width
int height = map.height
println "Width and Height = ${width} x ${height}"
Width and Height = 600 x 600
Get the Bounds
Bounds bounds = map.bounds
println "Bounds = ${bounds}"
Bounds = (-2.0037508342789244E7,-1.997186888040857E7,2.0037508342789244E7,1.9971868880408563E7,EPSG:3857)
Get the Projection
Projection projection = map.proj
println "Projeciton = ${projection}"
Projeciton = EPSG:3857
Get the Layers
List<Layer> layers = map.layers
println "Layers:"
layers.each { Layer layer ->
    println "   ${layer.name}"
}
Layers:
   countries
Get the renderer type
String type = map.type
println "Type = ${type}"
Type = png
Get whether we are fixing the aspect ration or not.
boolean shouldFixAspectRation = map.fixAspectRatio
println "Fix Aspect Ratio = ${shouldFixAspectRation}"
Fix Aspect Ratio = false
Get the background color
String backgroundColor = map.backgroundColor
println "Background Color = ${backgroundColor}"
Background Color = #a5bfdd
Get the scale
double scale = map.scaleDenominator
println "Scale = ${scale}"
Scale = 2.385417659855862E8

Advanced Properties

You can set the scale computation to be accurate (the default) or ogc compliant.
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

map accurate

OGC

map ogc
You can set whether to use advanced projection handling or not. By default this is set to true.
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

map advancedproj true

No

map advancedproj false
You can set whether to use continuous map wrapping. The default is true.
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

map continuouswrapping true

No

map continuouswrapping false

Projections

Create a map in the mercator projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Mercator")
Bounds bounds = new Bounds(-179.99, -85.0511, 179.99, 85.0511, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 400,
        height: 400,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_mercator.png")
map.render(file)
map mercator
Create a map in the WGS84 projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WGS84")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_wgs84.png")
map.render(file)
map wgs84
Create a map in the Equal Earth projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("EqualEarth")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_equalearth.png")
map.render(file)
map equalearth
Create a map in the Mollweide projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Mollweide")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_mollweide.png")
map.render(file)
map mollweide
Create a map in the Aitoff projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Aitoff")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_aitoff.png")
map.render(file)
map aitoff
Create a map in the Eckert IV projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("EckertIV")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_eckertIV.png")
map.render(file)
map eckertIV
Create a map in the Wagner IV projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WagnerIV")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_wagnerIV.png")
map.render(file)
map wagnerIV
Create a map in the Robinson projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("Robinson")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_robinson.png")
map.render(file)
map robinson
Create a map in the Winkel Tripel projection
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WinkelTripel")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_winkeltripel.png")
map.render(file)
map winkeltripel
Create a map in the World Vander Grinten I projection
Workspace workspace = new Directory('src/main/resources/shapefiles')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("black", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd") + new Stroke("black", 0.5)
Layer graticules = workspace.get("graticules")
graticules.style = new Stroke("black", 0.5)
Projection proj = new Projection("WorldVanderGrintenI")
Bounds bounds = new Bounds(-180, -90, 180, 90, "EPSG:4326").reproject(proj)
Map map = new Map(
        width: 600,
        height: 350,
        proj: proj,
        bounds: bounds,
        layers: [ocean, countries, graticules]
)
File file = new File("map_worldVanderGrintenIMap.png")
map.render(file)
map worldVanderGrintenIMap

Map Cubes

Create a map cube to a file
Workspace workspace = new Directory("src/main/resources/shapefiles")
Layer countries = workspace.get("countries")
Layer ocean = workspace.get("ocean")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
ocean.style = new Fill("#a5bfdd")

MapCube mapCube = new MapCube(
    drawOutline: true,
    drawTabs: true,
    tabSize: 30,
    title: "World Cube",
    source: "Nartual Earth",
    imageType: "png"
)
File file = new File("target/map_cube_file.png")
mapCube.render([ocean, countries], file)
map cube file
Create a map cube to a byte array
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])
map cube bytes
Create a map cube to a byte array
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")

MapCube mapCube = new MapCube()
File file = new File("target/map_cube_stream.png")
file.withOutputStream { OutputStream outputStream ->
    mapCube.render([ocean, countries], outputStream)
}
map cube stream

Rendering Maps

Finding Renderers

Get all Renderers
List<Renderer> renderers = Renderers.list()
renderers.each { Renderer renderer ->
    println renderer.class.simpleName
}
ASCII
Base64
GeoTIFF
GIF
JPEG
Pdf
PNG
Svg
Get a Renderer
Renderer renderer = Renderers.find("png")
println renderer.class.simpleName
PNG

Image

Render a Map to an image using an Image Renderer
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)
map image image
Render a Map to an OutputStream using the Image Renderer
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()
map image file

PNG

Render a Map to an Image using the PNG Renderer
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)
map png image
Render a Map to an OutputStream using the PNG Renderer
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()
map png file

JPEG

Render a Map to an Image using the JPEG Renderer
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)
map jpeg image
Render a Map to an OutputStream using the JPEG Renderer
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()
map jpeg file

GIF

Render a Map to an Image using the GIF Renderer
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)
map gif image
Render a Map to an OutputStream using the GIF Renderer
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))
map gif file
Render a Map to an animated GIF using the GIF Renderer
Workspace workspace = new GeoPackage('src/main/resources/data.gpkg')
Layer states = workspace.get("states")
states.style = new Fill("") + new Stroke("black", 1.0)
Layer countries = workspace.get("countries")
countries.style = new Fill("#ffffff") + new Stroke("#b2b2b2", 0.5)
Layer ocean = workspace.get("ocean")
ocean.style = new Fill("#a5bfdd")
Map map = new Map(
        width: 800,
        height: 300,
        layers: [ocean, countries, states]
)

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

GIF gif = new GIF()
List images = ["Washington","Oregon","California"].collect { String state ->
    map.bounds = states.getFeatures("name = '${state}'")[0].bounds
    def image = gif.render(map)
    image
}
File file = new File("states.gif")
byte[] bytes = gif.renderAnimated(images, 500, true)
file.bytes = bytes
render animated gif bytes

GeoTIFF

Render a Map to an Image using the GeoTIFF Renderer
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)
map geotiff image
Render a Map to an OutputStream using the GeoTIFF Renderer
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))
map geotiff file

ASCII

Render a Map to an string using the ASCII Renderer
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
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((((((^(^(.(?......((((((((((((((^(((((((((((((((((
.....:.^(^..!?^^!^:..!(^...(((((^.^((((...........:.^(^..!?^
.....(:((.........((.(((.((((((:(.................(:((......
!..(^((((((((^.........((((((.(..............!..(^((((((((^.
.(((((((((((((^.......((((((((...:^.^?...^..:.(((((((((((((^
((.((((((((((((.....:((((((((^^(((:!^((^.....((.((((((((((((
((((((((((((((((.!(((((((((((................(((((((((((((((
(((((((((((((((((.((.(((((((....:....((..(((((((((((((((((((
(((((((((((((((((((.((((((((^.(...(((((.((^(((((((((((((((((
((((((((((((((((((((.!:((((((((.....((((((((((((((((((((((((
((.(((((((((((((((((.....(((((((...((((((((((((.((((((((((((
(^((((((((((((((((((.....(((((((.^.(((((((((((^(((((((((((((
....(((((((((((((((((?...(((((((.((^((((((((^....(((((((((((
....(((((((((((((((((...((((((((^.((((((((((.....(((((((((((
(((.(((((((((((((((((..(((((((((((((((((((((((((.(((((((((((
(((((((((((((((((((((.((((((((((((((((((((((((((((((((((((((
(((((((((((((((((((((^((((((((((((((((((((((((((((((((((((((
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
....(((((((((((((((((?((((((((((((?....(.........(((((((((((
.....(((((...........(((((........................(((((.....
.......^....................................................
Render a Map to an text file using the ASCII Renderer
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