GithubHelp home page GithubHelp logo

geoscript / geoscript-groovy Goto Github PK

View Code? Open in Web Editor NEW
46.0 10.0 22.0 207.95 MB

A Groovy implementation of GeoScript.

Home Page: https://geoscript.net/groovy

License: MIT License

Shell 0.17% Groovy 99.42% HTML 0.14% CSS 0.01% Scheme 0.13% Batchfile 0.12% Dockerfile 0.01%
groovy geospatial gis

geoscript-groovy's Introduction

image

GeoScript Groovy

GeoScript Groovy is the Groovy implementation of GeoScript. GeoScript is a geospatial scripting API for the JVM that contains one API and four implementations (Python, JavaScript, Scala, and Groovy).

GeoScript is built on the shoulders of giants and essentially wraps the Java Topology Suite and the GeoTools libraries.

GeoScript provides several modules that includes geometry, projection, features, layers, workspaces, styling and rendering.

Build

Building GeoScript Groovy is quite easy. You will need to have git, Java, Maven, and Ant installed.

Use git to clone the repository:

git clone git://github.com/jericks/geoscript-groovy.git

Use maven to build, test, and package:

mvn clean install

The distribution can be found in target/geoscript-groovy-${version}-app/geoscript-groovy-${version}.

Use

To use GeoScript Groovy you need Java 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)
  2. geoscript-groovysh (which starts a REPL shell)
  3. geoscript-groovyConsole (which starts a graphical editor/mini IDE)

Buffering a Point:

import geoscript.geom.Point

def point = new Point(0,0)
def poly = point.buffer(10)
println(poly.wkt)

Project a Geomemtry:

import geoscript.geom.Point
import geoscript.proj.Projection

def p1 = new Point(-111.0, 45.7)
def p2 = Projection.transform(p1, "EPSG:4326", "EPSG:26912")

Read a Shapefile:

import geoscript.layer.Shapefile
import geoscript.geom.Bounds

def shp = new Shapefile("states.shp")
int count = shp.count
Bounds bounds = shp.bounds
shp.features.each {f->
    println(f)
}

Drawing a Shapefile:

import geoscript.layer.Shapefile
import geoscript.style.Stroke
import static geoscript.render.Draw.draw

def shp = new Shapefile("states.shp")
shp.style = new Stroke("#999999", 0.1)
draw(shp)

Reading a Raster:

import geoscript.layer.GeoTIFF

def format = new GeoTIFF(new File("raster.tif"))
def raster = format.read()

println "Format = ${raster.format}"
println "Proj EPSG = ${raster.proj.id}"
println "Proj WKT = ${raster.proj.wkt}"
println "Bounds = ${raster.bounds.geometry.wkt}"
println "Size = ${raster.size}"
println "Block Size = ${raster.blockSize}"
println "Pixel Size = ${raster.pixelSize}"
println "Band:"
raster.bands.eachWithIndex{b,i ->
    println "   ${i}). ${b}"
}

Generating tiles:

import geoscript.layer.*
import geoscript.style.*

Shapefile shp = new Shapefile(new File("states.shp"))
shp.style = new Fill("wheat") + new Stroke("navy", 0.1)

File file = new File("states.gpkg")
GeoPackage gpkg = new GeoPackage(file, "states", Pyramid.createGlobalMercatorPyramid(origin: Pyramid.Origin.TOP_LEFT))

TileRenderer renderer = new ImageTileRenderer(gpkg, shp)
TileGenerator generator = new TileGenerator(verbose: true)
generator.generate(gpkg, renderer, 0, 4)

See the web site, the groovy docs or the cook book or the examples directory for more examples.

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.22.0</version>
</dependency>

Docker

If you want to give GeoScript Groovy a spin with Docker use the following image:

https://hub.docker.com/repository/docker/jarederickson/geoscript-groovy

To run the image use:

docker image build -t jarederickson/geoscript-groovy:latest .

To build the image locally:

docker run -it --rm --name geoscript-groovy jarederickson/geoscript-groovy:latest

Versions

GeoScript GeoTools GeoServer JTS Groovy
1.22 30 2.24 1.19.0 4.0.15
1.21 29 2.23 1.19.0 4.0.13
1.20 28 2.22 1.19.0 3.0.13
1.19 27 2.21 1.18.2 3.0.11
1.18 26 2.20 1.18.2 3.0.9
1.17 25 2.19 1.18.1 3.0.7
1.16 24 2.18 1.17.1 3.0.5
1.15 23 2.17 1.16.1 3.0.3
1.14 22 2.16 1.16.1 2.5.8
1.13 21 2.15 1.16.0 2.5.6
1.12 20 2.14 1.16.0 2.4.15
1.11 19 2.13 1.14 2.4.14
1.10 18 2.12 1.13 2.4.12
1.9 17 2.11 1.13 2.4.10
1.8 16 2.10 1.13 2.4.7
1.7 15 2.9 1.13 2.4.6
1.6 14 2.8 1.13 2.4.5
1.5 13 2.7 1.13 2.3.10
1.4 12 2.6 1.13 2.2.2
1.3 11 2.5 1.13 2.1.9
1.2 10 2.4 1.13 2.1.6
1.1 9 2.3 1.13 1.8.9
1.0 8 2.2 1.12 1.8.8

API Groovy Docs

1.22.0

1.21.0

1.20.0

1.19.0

1.18.0

1.17.0

1.16.0

1.15.0

1.14.0

1.13.0

1.12.0

1.11.0

1.10.0

1.9.0

1.8.0

Projects using GeoScript Groovy

geoc: A geospatial command line application

geo-shell: An interactive geospatial shell

mbtiles server: Restful web services for mbtiles

geopackage server: Restful web services for geopackage

geoscript groovy jupyter kernel

Presentations

GeoScript: The GeoSpatial Swiss Army Knife (FOSS4G 2014)

Using GeoScript Groovy (CUGOS 2014)

Rendering Maps in GeoScript (CUGOS 2012)

Scripting GeoServer (CUGOS 2012)

GeoScript: Spatial Capabilities for Scripting Languages (FOSS4G 2011)

Build Servers

https://github.com/geoscript/geoscript-groovy/actions

https://build.geoserver.org/job/geoscript-groovy/

License

GeoScript Groovy is open source and licensed under the MIT license.

geoscript-groovy's People

Contributors

bananeweizen avatar blackrez avatar dwins avatar gnafu avatar jericks avatar sbortman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geoscript-groovy's Issues

Fix HatBox / PostGIS conflict

GeoScript Groovy can't connect to PostGIS when the new hatbox jar is on the classpath.

https://groups.google.com/forum/#!topic/geoscript/Ff2vqftzhqQ

The error we get is:

java.lang.SecurityException: Prohibited package name: java.sql
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)

The solution appears to be removing the hatbox java.sql package and upgrading the java compiler version to 1.6. The interfaces were only there to support java 1.5.

Hatbox Issue:
jodygarnett/hatbox#1

Hatbox Pull Request:
jodygarnett/hatbox#2

Why does a Feature's id change when its added to a Layer?

https://github.com/timkeane/geoscript-test/blob/master/src/test/groovy/nyc/FeatureIdTest.groovy

package nyc

import spock.lang.*

import geoscript.feature.*
import geoscript.layer.Layer
import geoscript.geom.*

class ProximityTest extends Specification {

	def 'test that feature ids persist'(){
		given:
			Schema schema = new Schema('mySchema', [['geom', 'Point'], ['name', 'string'], ['address', 'string']])
			def attrs = [geom: new Point(1, 10), name: 'myName', address: 'myAddress']
			Feature inFeature = new Feature(attrs, 'myFID', schema)
			Layer layer = new Layer('myLayer', schema)
			layer.add(inFeature)
		when:
			Feature outFeature = layer.getFeatures()[0]
		then:
			inFeature.getId() == 'myFID' 
			inFeature.getId() == outFeature.getId() 
	}
}

Update to Groovy 4

GeoScript Groovy is still using Groovy 3. We should upgrade to Groovy 4.

Add GeneratingTileLayer

A TileLayer that can generate Tiles on demand as a client tries to get them. It would be wrap a TileLayer (like MBTiles) and a TileRenderer (like ImageTileRenderer) and if the client tries to get a tile that isn't present (doesn't have any data) it would use the TileRenderer to generate the data.

MBTiles mbtiles = new MBTiles(new File("world.mbtiles"),"The World","The World Tiles")

Workspace workspace = new geoscript.workspace.GeoPackage(new File("naturalearth.gpkg"))
Layer countries = workspace.get("countries")
countries.style = new SLDReader().read(new File("countries.sld"))
Layer ocean = workspace.get("ocean")
ocean.style = new SLDReader().read(new File("ocean.sld"))

ImageTileRenderer renderer = new ImageTileRenderer(mbtiles, [ocean, countries])

GeneratingTileLayer generatingTiles = new GeneratingTileLayer(mbtiles, renderer)
generatingTiles.get(0,0,0)
generatingTiles.get(1,0,0)
generatingTiles.get(1,0,1)
generatingTiles.get(1,1,0)
generatingTiles.get(1,1,1)

Layer name [QUESTION]

The getName() method returns the name of the feature datasource instead of the name of the layer.
Usually the layer name is independent of the data source.
There may be a modeling problem with geoscript.
Because a layer is not an abstraction of a data source (Feature or Raster) but directly linked to a FeatureSource.

Cannot resolve org.geoscript:geoscript-groovy:jar:1.6.0 from any repository

Issue #25 is marked as resolved althought the old version 1.3.1 isn't provided by boundles repository anymore. Now uDig build is failing because 1.6.0 cannot be resolved either anymore.

This raises the question : What is the offical maven release repository for org.geoscript?

From pom.xml its
https://boundless.artifactoryonline.com/boundless/release/
but down below org/geoscript I cannot find any resources.

The validation in TileCursor for z is not in synch with how the z is queried in Pyramid

In the Method for Pyramid.groovy called grid(long z) it finds the z based on a comparison. This gives support for having a sparse range that might just cover hypothetical levels of 9-15. In the TileCursor constructors the validate calls assumes that the z grids are always 0 based and always goes from 0..level-1 which is a contradiction to the code found in pyramid.

Attached is a fix that basically changes the occurrences of:

   this.z = validate(z, 0, tileLayer.pyramid.grids.size() - 1, "z")

To be:
this.z = validate(z, tileLayer.pyramid.grids[0].z, tileLayer.pyramid.grids[-1].z, "z")

and where z is not passed in the modification was:

        this.z = validate(m.z, 0, tileLayer.pyramid.grids.size() - 1, "z")

to be:
this.z = validate(m.

z, tileLayer.pyramid.grids[0].z, tileLayer.pyramid.grids[-1].z, "z")

Although this might be a problem too for the new validation supports pyramid definitions of any range it does not support still sparse sets. For example, only defining grid definitions for something like 4,8,9.

With the above fix we can define Grids with ranges of only 8-10 or 4-9 or whatever we want

I am not sure how to attache the update TileCursor.groovy file so the modifications are here (Just the constructors need modification that take a z):

/**
 * Create TileCursor that iterates over every Tile in a given zoom level between the
 * given columns and rows
 * @param layer The TileLayer
 * @param z The zoom level
 * @param minX The min x or column
 * @param minY The min y or row
 * @param maxX The max x or column
 * @param maxY The max y or row
 */
TileCursor (TileLayer layer, long z, long minX, long minY, long maxX, long maxY) {
    this.tileLayer = layer
   // this.z = validate(z, 0, tileLayer.pyramid.grids.size() - 1, "z")
    this.z = validate(z, tileLayer.pyramid.grids[0].z, tileLayer.pyramid.grids[-1].z, "z")
    Grid grid = tileLayer.pyramid.grid(this.z)
    this.minX = validate(minX, 0, grid.width - 1, "minX")
    this.minY = validate(minY, 0, grid.height - 1, "minY")
    this.maxX = validate(maxX, 0, grid.width - 1, "maxX")
    this.maxY = validate(maxY, 0, grid.height - 1, "maxY")
    this.width = (maxX - minX) + 1
    this.height = (maxY - minY) + 1
    this.size = width * height
}

/**
 * Create TileCursor that iterates over every Tile in a given zoom level and within the given Bounds
 * @param layer The TileLayer
 * @param b The Bounds
 * @param z The zoom level
 */
TileCursor(TileLayer layer, Bounds b, long z) {
    // Limit the Bounds to the intersection of the requested Bounds
    // and the Pyramid's Bounds
    Bounds pyramidBounds = layer.pyramid.bounds
    Bounds intersectedBounds = pyramidBounds.intersection(b)
    // Check that the intersected Bounds is not empty
    if (!intersectedBounds.empty) {
        Grid m = layer.pyramid.grid(z)
        Map tileCoords = layer.getTileCoordinates(intersectedBounds, m)
        this.tileLayer = layer
        //this.z = validate(z, 0, tileLayer.pyramid.grids.size() - 1, "z")
        this.z = validate(z, tileLayer.pyramid.grids[0].z, tileLayer.pyramid.grids[-1].z, "z")
        Grid grid = tileLayer.pyramid.grid(this.z)
        this.minX = validate(tileCoords.minX, 0, grid.width - 1, "minX")
        this.minY = validate(tileCoords.minY, 0, grid.height - 1, "minY")
        this.maxX = validate(tileCoords.maxX, 0, grid.width - 1, "maxX")
        this.maxY = validate(tileCoords.maxY, 0, grid.height - 1, "maxY")
        this.width = (maxX - minX) + 1
        this.height = (maxY - minY) + 1
        this.size = width * height
    } else {
        // Cache the bounds as the empty Bounds with the correct projection
        this.bounds = intersectedBounds
        this.size = 0
    }
}

/**
 * Create TileCursor that iterates over every Tile within the given Bounds and for the x and y resolutions
 * @param layer The TileLayer
 * @param b The Bounds
 * @param resX The x resolution
 * @param resY The y resolution
 */
TileCursor(TileLayer layer, Bounds b, double resX, double resY) {
    // Limit the Bounds to the intersection of the requested Bounds
    // and the Pyramid's Bounds
    Bounds pyramidBounds = layer.pyramid.bounds
    Bounds intersectedBounds = pyramidBounds.intersection(b)
    // Check that the intersected Bounds is not empty
    if (!intersectedBounds.empty) {
        Grid m = layer.pyramid.grid(intersectedBounds, resX, resY)
        Map tileCoords = layer.getTileCoordinates(intersectedBounds, m)
        this.tileLayer = layer

// this.z = validate(m.z, 0, tileLayer.pyramid.grids.size() - 1, "z")
this.z = validate(m.z, tileLayer.pyramid.grids[0].z, tileLayer.pyramid.grids[-1].z, "z")
Grid grid = tileLayer.pyramid.grid(this.z)
this.minX = validate(tileCoords.minX, 0, grid.width - 1, "minX")
this.minY = validate(tileCoords.minY, 0, grid.height - 1, "minY")
this.maxX = validate(tileCoords.maxX, 0, grid.width - 1, "maxX")
this.maxY = validate(tileCoords.maxY, 0, grid.height - 1, "maxY")
this.width = (maxX - minX) + 1
this.height = (maxY - minY) + 1
this.size = width * height
} else {
// Cache the bounds as the empty Bounds with the correct projection
this.bounds = intersectedBounds
this.size = 0
}
}

/**
 * Create TileCursor that iterates over every Tile within the Bounds for the image size
 * @param layer The TileLayer
 * @param b The Bounds
 * @param w The image width
 * @param h The image height
 */
TileCursor(TileLayer layer, Bounds b, int w, int h) {
    // Limit the Bounds to the intersection of the requested Bounds
    // and the Pyramid's Bounds
    Bounds pyramidBounds = layer.pyramid.bounds
    Bounds intersectedBounds = pyramidBounds.intersection(b)
    // Check that the intersected Bounds is not empty
    if (!intersectedBounds.empty) {
        Grid m = layer.pyramid.grid(intersectedBounds, w, h)
        Map tileCoords = layer.getTileCoordinates(intersectedBounds, m)
        this.tileLayer = layer

// this.z = validate(m.z, 0, tileLayer.pyramid.grids.size() - 1, "z")
this.z = validate(m.z, tileLayer.pyramid.grids[0].z, tileLayer.pyramid.grids[-1].z, "z")
Grid grid = tileLayer.pyramid.grid(this.z)
this.minX = validate(tileCoords.minX, 0, grid.width - 1, "minX")
this.minY = validate(tileCoords.minY, 0, grid.height - 1, "minY")
this.maxX = validate(tileCoords.maxX, 0, grid.width - 1, "maxX")
this.maxY = validate(tileCoords.maxY, 0, grid.height - 1, "maxY")
this.width = (maxX - minX) + 1
this.height = (maxY - minY) + 1
this.size = width * height
} else {
// Cache the bounds as the empty Bounds with the correct projection
this.bounds = intersectedBounds
this.size = 0
}
}

Move OrbisGIS to GeoScript-Groovy

At OrbisGIS team we think about using GeoScript-Groovy and contribute to the project.
We have successfully made the link with H2GIS ;-)
Before taking this decision, we would like to know if it is possible to consider to organise Geoscript in modules.
e.g a module for data access, a module for map, plot...
Indeed, our apps don't require all the geoscript modules each time.
Thanks

Add Raster.getShadedRelieft method

GeoTools recently added a shaded relief algorithm:

See geotools/geotools#1931 for the GeoTools pull request.

GeoScript should support it with something like:

Raster shadedRelieftRaster = raster.createShadedRelieft(1, 45, 65, "ZEVENBERGEN_THORNE")

Viewer.plot issues

Given the following testcode:

import geoscript.geom.*
import geoscript.viewer.*

def multiLineCoordinates = [
    [[10,10],[20,20],[10,40]],
    [[40,40],[30,30],[40,20],[30,10]]
]
def geom = new MultiLineString(multiLineCoordinates)

Viewer.plot([size: [800,800]],[geom])

I get the following:

image

You can see the points being shifted against the lines they are part of.

The same result can be obtained by avoiding to set the size:

Viewer.plot([geom])

and then enlarging the plot window.

`MultiGeoemtry`: Typo in KmlWriter produces invalid geometry

In KmlWriter.groovy (line 96ff) is a error, which produces invalid KML-Files:

  } else if (geom instanceof GeometryCollection) {
            builder."${ns}MultiGeoemtry" {
                geom.geometries.each {
                    write builder, it, namespace: namespace
                }
            }
        } 

It should be MultiGeometry not MultiGeoemtry.

The same in the Testcase!

From OrbisGIS to GeoScript

At OrbisGIS team we think about using GeoScript-Groovy and contribute to the project.
We have successfully made the link with H2GIS ;-)
Before taking this decision, we would like to know if it is possible to consider to organise Geoscript in modules.
e.g a module for data access, a module for map, plot...
Indeed, our apps don't require all the geoscript modules each time.
Thanks

upgrade to jts 1.15.1

GeoServer is upgrading to JTS 1.15.1 and is checking in with our dependencies ask if a new release can be made

the examples on the code page fail

Just trying geoscript-groovy for the first time, and the second and third examples on the code page are failing for me.

The second example has a typo in it as well. The line

def p2 = Projection.transform(p, "EPSG:4326", "EPSG:26912")

should read

def p2 = Projection.transform(p1, "EPSG:4326", "EPSG:26912")

When I fix the typo and run it with geoscript-groovy, this is the output I get:

Mar 11, 2016 3:41:21 PM org.geotools.factory.FactoryRegistry scanForPlugins
WARNING: Can't load a service for category "MathTransformProvider". Cause is "ServiceConfigurationError: org.geotools.referencing.operation.MathTransformProvider: Provider org.geotools.referencing.operation.transform.WarpTransform2D$Provider could not be instantiated".
java.util.ServiceConfigurationError: org.geotools.referencing.operation.MathTransformProvider: Provider org.geotools.referencing.operation.transform.WarpTransform2D$Provider could not be instantiated
at java.util.ServiceLoader.fail(ServiceLoader.java:232)
at java.util.ServiceLoader.access$100(ServiceLoader.java:185)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:384)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)

(rest of lines removed for brevity's sake).

A similar problem occurs with the third example.

This is with groovy 2.4.6 (the latest as of today) and GeoScript 1.6.0 (also the latest).

Please help!

PostGIS table without a geometry column

If a PostGIS table has not geometry column, the geoscript.workspace.PostGIS.getLayers() method throws an error:

Caught: java.lang.NullPointerException: Cannot get property 'typ' on null object
java.lang.NullPointerException: Cannot get property 'typ' on null object
at geoscript.layer.Layer.(Layer.groovy:136)
at geoscript.layer.Layer.(Layer.groovy:145)
at geoscript.workspace.Workspace.get(Workspace.groovy:86)
at geoscript.workspace.Workspace$_getLayers_closure2.doCall(Workspace.groovy:77)
at geoscript.workspace.Workspace.getLayers(Workspace.groovy:77)
at geoscript.workspace.Workspace$getLayers.call(Unknown Source)
at exportPostgisToShapefile.run(exportPostgisToShapefile.groovy:15)

This is due to the Layer constructor which is setting a default symbolizer. It tries to get the geometry type from the schema but the schema has no geometry type.

Probably something like this could help:

    if (this.schema.geom) {
      setDefaultSymbolizer(this.schema.geom.typ)
    }

Don't know if this has some side affects?

Stefan

Linux Ubuntu missing libproj.so.0

I am trying (perhaps poorly) to create a new layer that is an intersection of two existing layer/shapefiles. To do so I am getting a workspace and adding that layer to the workspace with a shapefile name. The relevant code lines are:

def tramosXsnaspe = tramos.intersection(snaspe)

def resultsWorkspaceName = "./Toltén"
def resultsWorkspace = new geoscript.workspace.Workspace(resultsWorkspaceName)

def tramosXsnaspeFileName = "tramosXsnaspe"
resultsWorkspace.add(tramosXsnaspe, tramosXsnaspeFileName)

When I execute the code, I get the following message (twice):

java.lang.UnsatisfiedLinkError: /tmp/spatialite-3.7.22.4-libspatialitejdbc.so: libproj.so.0: cannot open shared object file: No such file or directory

I don't see a "libproj.so.0" on my system but there is a

/usr/lib/x86_64-linux-gnu/libproj.so.9

Any suggestions would be hugely appreciated.

Missing org/jfree/chart/JFreeChart

Hello,

I'm trying to us geoscript for a very simple project but at the compilation, build fails.

➜  prj2epsg-ng ./gradlew run   

> Task :compileGroovy FAILED
startup failed:
General error during instruction selection: java.lang.NoClassDefFoundError: Unable to load class geoscript.plot.ViewerExtensionModule due to missing dependency org/jfree/chart/JFreeChart

java.lang.RuntimeException: java.lang.NoClassDefFoundError: Unable to load class geoscript.plot.ViewerExtensionModule due to missing dependency org/jfree/chart/JFreeChart

Fromat.groovy: Format.getFormat is only taking a file object

Hello,

In geotools core you can pass a generic object to find a format. I have modified the code to allow for a generic object. You do not have to limit the input to file only and you can actually pass an InputStream, URL, ... etc as an input for a particular format.

You might want to review the modification but all the tests seem to pass. I have added bridges the original code by testing instanceof File so that your original file based if checks will still run. With this modification you can now construct a new Format by a generic object.

/**
 * Get the Format that can read the given File
 * @param file The File
 * @return A Format
 */
static Format getFormat(Object input) {

    if(input instanceof File)
    {
        File file = input as File
        if (file.exists()) {
            AbstractGridFormat format = GridFormatFinder.findFormat(file);
            if (format == null || format instanceof UnknownFormat) {
                return null
            }
            if (format instanceof GeoTiffFormat) {
                return new GeoTIFF(file)
            } else if (format instanceof ArcGridFormat) {
                return new ArcGrid(file)
            } else if (format instanceof GrassCoverageFormat) {
                return new Grass(file)
            } else if (format instanceof GTopo30Format) {
                return new GTopo30(file)
            } else if (format instanceof ImagePyramidFormat) {
                return new ImagePyramid(file)
            } else if (format instanceof ImageMosaicFormat) {
                return new Mosaic(file)
            } else if (format instanceof MrSIDFormat) {
                return new MrSID(file)
            } else if (format instanceof WorldImageFormat) {
                return new WorldImage(file)
            } else if (format instanceof NetCDFFormat) {
                return new NetCDF(file)
            } else {
                return new Format(format, file)
            }
        } else {
            String ext = file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase()
            if (ext in ["tif"]) {
                return new GeoTIFF(file)
            } else if (ext in ["png","jpg","jpeg","gif"]) {
                return new WorldImage(file)
            } else if (ext in ["arx"]) {
                return new Grass(file)
            } else if (ext in ["sid"]) {
                return new MrSID(file)
            } else if (ext in ["asc"]) {
                return new ArcGrid(file)
            } else if (ext in ["nc"]) {
                return new NetCDF(file)
            } else {
                return null
            }
        }
    }
    else if(input instanceof InputStream)
    {
        AbstractGridFormat format = GridFormatFinder.findFormat(input);
        if (format == null || format instanceof UnknownFormat) {
            return null
        }else{
            return new Format(format, input)
        }
    }
}

ScaleBarItem border properties

The ScaleBarItem shares the same information to custom the color and the size of stroke for the border (rectangle) and line of the scale bar.
It would be nice to split them. Something like this

  • borderColor
  • borderWidth
  • backGroundColor
  • barWidth
  • barColor

The user will be able to control each element and build for example a scalebar with a background color but without a border around the scale.

See an example

map

Bug in geoscript.layer.Pyramid

When setting the initial projection on line 19:

Bounds bounds = new Bounds(-179.99, 179.99, -90, 90, "EPSG:4326")

Shouldn't that be:

Bounds bounds = new Bounds(-179.99, -90, 179.99, 90, "EPSG:4326")

?

GeoJSON decimal precision

Currently GeoJSON can be created from Geometry with the help of org.geotools.geojson.geom.GeometryJSON class. It is instantiated in GeoJSONWriteras new GeometryJSON (). In this case GeometryJSON writes after dot only 4 decimal digits. It has sense to use new GeometryJSON (int decimals) constructor to use precision up to user requirements.

Grid size attribute exceeding precision

The size attribute is exceeding precision due to the fact that it is calculated with width*height. Both width and height are integers and are blowing up at around level 16 for a geographic quad split. Changing the constructor and the attributes of width and height will fix this issue.

class Grid {

/**
 * The zoom level
 */
long z

/**
 * The width or number of columns
 */
long width

/**
 * The height or number of rows
 */
long height

/**
 * The number of tiles
 */
long size

/**
 * The x resolution
 */
double xResolution

/**
 * The y resolution
 */
double yResolution

/**
 * Create a new Grid
 * @param z The zoom level
 * @param width The width or number of columns
 * @param height The height or number of rows
 * @param xResolution The x resolution
 * @param yResolution The y resolution
 */
Grid(long z, long width, long height, double xResolution, double yResolution) {
    this.z = z
    this.width = width
    this.height = height
    this.xResolution = xResolution
    this.yResolution = yResolution
    this.size = this.width * this.height
}

Issues with asc raster math

Hi, I am trying to do a very simple raster diff (manually to teach students). The script is the following:

import geoscript.layer.*

def base = "path/to/base/folder/"
def dsmPath = base + "DSM_SolarTirol_small.asc"
def dtmPath = base + "DTM_SolarTirol_small.asc"
def chmPath = base + "CHM.asc"

def dtmRaster = Format.getFormat(dtmPath).read()
def dsmRaster = Format.getFormat(dsmPath).read()
def outChmRaster = Format.getFormat(dsmPath).read()

def cols = dtmRaster.cols
def rows = dtmRaster.rows
def nv = -9999.0

for ( row in 0..(rows-1)) {
    for ( col in 0..(cols-1)) {
        def position = [col, row]
        def dtmValue = dtmRaster.getValue(position)
        def dsmValue = dsmRaster.getValue(position)
        if(dtmValue != nv && dsmValue != nv){
            def chmValue = dsmValue - dtmValue
            outChmRaster.setValue(position, chmValue)
        }
    }    
}

Format.getFormat(chmPath).write(outChmRaster)

Issues with this:

  • if the raster has a cell size of 0.5, I get an error due to the fact that the point of the last column is outside the raster. It doesn't happen if I cheat and change it to 1.0. I am guessing there is a rounding problem.
  • in general the script doesn't work. I am not sure what I am not seeing, but the result is the same as the dsm raster. I am indeed using the dsmraster as a template to fill in the new data, but the setValue should overwrite it, which it is not doing. (is tere a better way to create a raster based on an existing in order to have exact the same grid?)

TileCursor hasNext method. Should it reset the cursor?

In the TileCursor.groovy for hasNext:

@Override
boolean hasNext() {
    boolean hasNext = counter < size
    if (!hasNext) {
        reset()
    }
    hasNext
}

I was wondering if this function is doing too much. I think the caller should see if it hasNext and should always return false unless the caller calls reset.

I propose this method should be simplified to:

@Override
boolean hasNext() {
   counter < size
}

What do you think.

Take care

Garrett

resizing the plot window malformes the plot

Hi. There is an issue with plotting geometries.

myPlot = []
myLayer.eachFeature{
    myPlot << it.geometry
}
Plot.plot(myPlot)

This plots my geometries to a default 500x500 plot window. Resizing the window causes some issues. Vertices of polygons are stretched while resizing differently than edges.

Zooming in results in the same undesired effect. Here are some screenshots:

http://i.imgur.com/ggSZo4k.png
http://i.imgur.com/kd3LjQB.png
http://i.imgur.com/ktGMOyq.png

Use Rule name with LegendItem

The LegendItem built from a Layer, eg. legend.addLayer(layer) doesn't take into account the rule name but set the Filter Expression or the name of the Layer. See https://github.com/geoscript/geoscript-groovy/blob/master/src/main/groovy/geoscript/carto/LegendItem.groovy#L243

So when a Legend is renderered with a set of rules it prints the filter expression e.g : VALUE = 0 ...

I propose to change a bit the code to set the rule to the LegendItem title.

layer.style.gtStyle.featureTypeStyles().each { def fts ->
            fts.rules().each { def rule ->
                Filter filter = rule.filter
                String title=rule.name
                if(!title){
                 title = numberOfRules > 1 ? CQL.toCQL(filter) : layer.name.capitalize()
                }
                Style style = SLDStyle.fromRule(rule)
                if (legendEntryType == LegendEntryType.POINT) {
                    addPointEntry(title, style)
                } else if (legendEntryType == LegendEntryType.LINE) {
                    addLineEntry(title, style)
                }  else if (legendEntryType == LegendEntryType.POLYGON) {
                    addPolygonEntry(title, style)
                }
            }
        }

and the unit test

  @Test
    void legendItemWithRuleName() {
        Workspace workspace = new Memory()
        Layer layer = workspace.create("points", [
                new Field("geom", "Point", "EPSG:4326"),
                new Field("id", "Integer")
        ])
        Shape symbolizer = new Shape("navy")
        def gtStyle = symbolizer.getGtStyle()
        gtStyle.featureTypeStyles()[0].rules()[0].name="Navy color"
        layer.style=new SLDReader.SLDStyle(gtStyle)
        LegendItem legend = new LegendItem(20, 20, 100, 100)
        legend.addLayer(layer)
        assertEquals("Navy color", legend.getEntries()[0].title)
}

Please find two images before and after this fix.

Before
before

After
after

java 11/13 compilation and split problems

This is more a question than an issue I guess.

I am trying to upgrade the Hortonmachine project to the latest geoscript and geotools >= 22 and in teh process I would like to migrate it to be compatible with java 13, but I am having quite some troubles.

Currently I am hanging on the fact that the groovy modules geoscript depends on are not java 11 ready in the sense that don't obey to the package split matter. Several jar contain the same package and that is not allowed.

Did anyone try to compile geoscript with a java 13?

Thanks.

PostGIS Workspace

geoscript.workspace.PostGIS

PostGIS (String name, String host, String port, String schema, String user, String password, boolean estimatedExtent = false) {
super(createDataStore(name, host, port, schema, user, password, estimatedExtent, false, ""))
}

I think the constructor is missing a paramter and should probably look like:

PostGIS (String name, String host, String port, String schema, String user, String password, boolean estimatedExtent = false, String createDatabaseParams="") {
super(createDataStore(name, host, port, schema, user, password, estimatedExtent, false, createDatabaseParams))
}

As it is now, you can't use this constructor:

PostGIS (Map options = [:], String name) { ... }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.