geoscript / geoscript-groovy Goto Github PK
View Code? Open in Web Editor NEWA Groovy implementation of GeoScript.
Home Page: https://geoscript.net/groovy
License: MIT License
A Groovy implementation of GeoScript.
Home Page: https://geoscript.net/groovy
License: MIT License
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
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")
?
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
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:
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
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) { ... }
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")
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.
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
}
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
You refer to extensive examples using Symbolizers (e.g. LineSymbolizer) for style formatting of Geometries (e.g. in http://geoscript.org/examples/map/line.html) but these Symbolizers are not implemented in Groovy (there are implemented in Java).
Are the Symbolizer implementations indeed implemented?
Thanks
Argyriou Mike
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
}
}
It seems that Scatter charts do not use name for the series. Instead in the legend always Values appears.
Also, legend: 'false'
in the opts doesn't hide the legend.
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.
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:
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.
While Plot.plot and Viewer.draw check for the "GroocyConsole" in the frame title, Viewer.plot does not.
I assume (but am not sure) it is due to these lines:
I tried boundless / osgeo repositories but cannot resolve it. When 1.3.1 came out distribution repository was set to http://repo.opengeo.org
Do we have a backup to add old releases to https://boundless.artifactoryonline.com/boundless/release/org/geoscript
again?
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.
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)
During the construction of the TIleCursor we need to allow support for the validation of the grid levels to be sparse and not rely on order.
Currently GeoJSON can be created from Geometry with the help of org.geotools.geojson.geom.Geometry
JSON class. It is instantiated in GeoJSONWriter
as 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.
I added a pull request on master to resolve this issue. I made a change that returned a boolean instead of an integer and forgot to remove the "false" path of the validation where there was an assignment of result=-1. This is no longer valid
GeoScript Groovy is still using Groovy 3. We should upgrade to Groovy 4.
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)
}
}
}
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()
}
}
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
LOVE YOUR WORK!!!
Just ran on 0.99 today... blown away.
Thanks!
(but would love 1.0 if I could access it :) )
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.
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
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.
GeoServer is upgrading to JTS 1.15.1 and is checking in with our dependencies ask if a new release can be made
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
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
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
JTS added a HPRtree spatial index in version 1.17.0.
https://github.com/locationtech/jts/releases/tag/1.17.0
GeoScript should add a class to support this.
like referenced in docs, the following link cause "File not found" : https://github.com/downloads/jericks/geoscript-groovy/geoscript-groovy-1.0.zip
Class GeoTIFF like shown in this example https://github.com/jericks/geoscript-groovy/blob/master/examples/style_rasters.groovy is not available although its available in source tree : https://github.com/jericks/geoscript-groovy/blob/master/src/main/groovy/geoscript/layer/GeoTIFF.groovy
I tested stable version 0.99 as well but same problem here.
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!
GeoTools recently added a YSLD module.
https://github.com/geotools/geotools/tree/master/modules/unsupported/ysld
GeoScript support would require a geoscript.style.io.YSLDReader and YSLDWriter.
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!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.