<?xml version="1.0" encoding="UTF-8"?>
<classpath>
+ <classpathentry exported="true" kind="lib" path="lib/commons-io-2.1.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/gt-api-16.0.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/gt-coverage-16.0.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/gt-geotiff-16.0.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/gt-main-16.0.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/guava-17.0.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/imageio-ext-geocore-1.1.16.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/imageio-ext-streams-1.1.16.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/imageio-ext-tiff-1.1.16.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/imageio-ext-utilities-1.1.16.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jai_codec-1.1.3.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jai_imageio-1.1.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jdom-1.1.3.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-affine-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-algebra-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-bandcombine-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-bandmerge-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-bandselect-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-binarize-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-border-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-buffer-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-classifier-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-colorconvert-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-colorindexer-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-crop-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-errordiffusion-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-format-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-imagefunction-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-iterators-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-lookup-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-mosaic-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-nullop-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-orderdither-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-piecewise-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-rescale-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-rlookup-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-scale-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-stats-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-translate-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-utilities-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-utils-1.4.0.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-vectorbin-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-warp-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-zonal-1.0.11.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jt-zonalstats-1.4.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/hsqldb-2.3.4.jar"/>
<classpathentry exported="true" kind="lib" path="lib/gt-epsg-hsql-16.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-pool-1.5.4.jar"/>
lib/jts-1.13.jar,
.,
lib/gt-epsg-hsql-16.0.jar,
- lib/hsqldb-2.3.4.jar
+ lib/hsqldb-2.3.4.jar,
+ lib/commons-io-2.1.jar,
+ lib/gt-api-16.0.jar,
+ lib/gt-coverage-16.0.jar,
+ lib/gt-geotiff-16.0.jar,
+ lib/gt-main-16.0.jar,
+ lib/guava-17.0.jar,
+ lib/imageio-ext-geocore-1.1.16.jar,
+ lib/imageio-ext-streams-1.1.16.jar,
+ lib/imageio-ext-tiff-1.1.16.jar,
+ lib/imageio-ext-utilities-1.1.16.jar,
+ lib/jai_codec-1.1.3.jar,
+ lib/jai_imageio-1.1.jar,
+ lib/jdom-1.1.3.jar,
+ lib/jt-affine-1.0.11.jar,
+ lib/jt-algebra-1.0.11.jar,
+ lib/jt-bandcombine-1.0.11.jar,
+ lib/jt-bandmerge-1.0.11.jar,
+ lib/jt-bandselect-1.0.11.jar,
+ lib/jt-binarize-1.0.11.jar,
+ lib/jt-border-1.0.11.jar,
+ lib/jt-buffer-1.0.11.jar,
+ lib/jt-classifier-1.0.11.jar,
+ lib/jt-colorconvert-1.0.11.jar,
+ lib/jt-colorindexer-1.0.11.jar,
+ lib/jt-crop-1.0.11.jar,
+ lib/jt-errordiffusion-1.0.11.jar,
+ lib/jt-format-1.0.11.jar,
+ lib/jt-imagefunction-1.0.11.jar,
+ lib/jt-iterators-1.0.11.jar,
+ lib/jt-lookup-1.0.11.jar,
+ lib/jt-mosaic-1.0.11.jar,
+ lib/jt-nullop-1.0.11.jar,
+ lib/jt-orderdither-1.0.11.jar,
+ lib/jt-piecewise-1.0.11.jar,
+ lib/jt-rescale-1.0.11.jar,
+ lib/jt-rlookup-1.0.11.jar,
+ lib/jt-scale-1.0.11.jar,
+ lib/jt-stats-1.0.11.jar,
+ lib/jt-translate-1.0.11.jar,
+ lib/jt-utilities-1.0.11.jar,
+ lib/jt-utils-1.4.0.jar,
+ lib/jt-vectorbin-1.0.11.jar,
+ lib/jt-warp-1.0.11.jar,
+ lib/jt-zonal-1.0.11.jar,
+ lib/jt-zonalstats-1.4.0.jar
Export-Package: com.vividsolutions.jts,
com.vividsolutions.jts.geom,
com.vividsolutions.jts.geom.impl,
com.vividsolutions.jts.geomgraph,
com.vividsolutions.jts.geomgraph.index,
com.vividsolutions.jts.index.quadtree,
+ com.vividsolutions.jts.index.strtree,
+ it.geosolutions.imageio.stream.input.spi,
+ it.geosolutions.imageio.stream.output.spi,
+ org.geotools.coverage,
+ org.geotools.coverage.grid,
+ org.geotools.coverage.grid.io,
+ org.geotools.gce.geotiff,
org.geotools.geometry,
org.geotools.referencing,
org.opengis.geometry,
output.. = bin/
bin.includes = META-INF/,\
.,\
- lib/
+ lib/,\
+ lib/commons-io-2.1.jar,\
+ lib/gt-api-16.0.jar,\
+ lib/gt-coverage-16.0.jar,\
+ lib/gt-geotiff-16.0.jar,\
+ lib/gt-main-16.0.jar,\
+ lib/guava-17.0.jar,\
+ lib/imageio-ext-geocore-1.1.16.jar,\
+ lib/imageio-ext-streams-1.1.16.jar,\
+ lib/imageio-ext-tiff-1.1.16.jar,\
+ lib/imageio-ext-utilities-1.1.16.jar,\
+ lib/jai_codec-1.1.3.jar,\
+ lib/jai_imageio-1.1.jar,\
+ lib/jdom-1.1.3.jar,\
+ lib/jt-affine-1.0.11.jar,\
+ lib/jt-algebra-1.0.11.jar,\
+ lib/jt-bandcombine-1.0.11.jar,\
+ lib/jt-bandmerge-1.0.11.jar,\
+ lib/jt-bandselect-1.0.11.jar,\
+ lib/jt-binarize-1.0.11.jar,\
+ lib/jt-border-1.0.11.jar,\
+ lib/jt-buffer-1.0.11.jar,\
+ lib/jt-classifier-1.0.11.jar,\
+ lib/jt-colorconvert-1.0.11.jar,\
+ lib/jt-colorindexer-1.0.11.jar,\
+ lib/jt-crop-1.0.11.jar,\
+ lib/jt-errordiffusion-1.0.11.jar,\
+ lib/jt-format-1.0.11.jar,\
+ lib/jt-imagefunction-1.0.11.jar,\
+ lib/jt-iterators-1.0.11.jar,\
+ lib/jt-lookup-1.0.11.jar,\
+ lib/jt-mosaic-1.0.11.jar,\
+ lib/jt-nullop-1.0.11.jar,\
+ lib/jt-orderdither-1.0.11.jar,\
+ lib/jt-piecewise-1.0.11.jar,\
+ lib/jt-rescale-1.0.11.jar,\
+ lib/jt-rlookup-1.0.11.jar,\
+ lib/jt-scale-1.0.11.jar,\
+ lib/jt-stats-1.0.11.jar,\
+ lib/jt-translate-1.0.11.jar,\
+ lib/jt-utilities-1.0.11.jar,\
+ lib/jt-utils-1.4.0.jar,\
+ lib/jt-vectorbin-1.0.11.jar,\
+ lib/jt-warp-1.0.11.jar,\
+ lib/jt-zonal-1.0.11.jar,\
+ lib/jt-zonalstats-1.4.0.jar
org.simantics.scl.osgi,
org.simantics.district.route,
org.simantics.scenegraph.profile,
- org.simantics.district.geotools;bundle-version="1.0.0"
+ org.simantics.district.geotools;bundle-version="1.0.0",
+ org.simantics.maps.elevation.server
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: javax.annotation;version="1.0.0";resolution:=optional,
javax.inject;version="1.0.0"
import org.simantics.g2d.canvas.ICanvasContext;
import org.simantics.g2d.canvas.IToolMode;
import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.maps.elevation.server.SingletonTiffTileInterface;
+import org.simantics.maps.elevation.server.prefs.MapsElevationServerPreferences;
import org.simantics.scenegraph.g2d.G2DNode;
import org.simantics.scenegraph.g2d.events.EventTypes;
import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent;
import org.simantics.scenegraph.utils.GeometryUtils;
import org.simantics.scenegraph.utils.NodeUtil;
import org.simantics.utils.threads.ThreadUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class NetworkDrawingNode extends G2DNode {
+ private static final Logger LOGGER = LoggerFactory.getLogger(NetworkDrawingNode.class);
+
static class DrawingNode {
private List<Point2D> routeNodes = new ArrayList<>();
double x = ModelledCRS.xToLongitude(pos.getX() / scale);
double y = ModelledCRS.yToLatitude(-pos.getY() / scale);
+ double elevation = 0;
+ if (MapsElevationServerPreferences.useElevationServer()) {
+ // ok! we use new elevation API to resolve possible elevations for the starting points
+ try {
+ elevation = SingletonTiffTileInterface.lookup(x, y).doubleValue();
+ } catch (Exception ee) {
+ LOGGER.error("Could not get elevation from tiff interface", ee);
+ }
+ }
+ final double felevation = elevation;
+
boolean leftButton = e.button == MouseEvent.LEFT_BUTTON;
ThreadUtils.getNonBlockingWorkExecutor().schedule(() -> {
if (mapping == null) {
mapping = graph.getSingleObject(diagramResource, DistrictNetworkResource.getInstance(graph).VertexDefaultMapping);
}
- DistrictNetworkUtil.createVertex(graph, diagramResource, new double[] { x, y }, 0, mapping); // TODO: elevation can be fetched from e.g. elevation API
+ DistrictNetworkUtil.createVertex(graph, diagramResource, new double[] { x, y }, felevation, mapping);
}
});
}, 100, TimeUnit.MILLISECONDS);
detailedGeometryCoords[i++] = lat;
}
+ double startElevation = 0;
+ double endElevation = 0;
+ if (MapsElevationServerPreferences.useElevationServer()) {
+ // ok! we use new elevation API to resolve possible elevations for the starting points
+ try {
+ startElevation = SingletonTiffTileInterface.lookup(startLat, startLon).doubleValue();
+ endElevation = SingletonTiffTileInterface.lookup(endLat, endLon).doubleValue();
+ } catch (Exception e) {
+ LOGGER.error("Could not get elevation from tiff interface", e);
+ }
+ }
+ final double se = startElevation;
+ final double ee = endElevation;
DNEdgeBuilder builder = new DNEdgeBuilder(diagramResource, diagram);
Simantics.getSession().asyncRequest(new WriteRequest() {
-
+
@Override
public void perform(WriteGraph graph) throws DatabaseException {
- builder.create(graph, startCoords, 0, endCoords, 0, detailedGeometryCoords, padding);
+ builder.create(graph, startCoords, se, endCoords, ee, detailedGeometryCoords, padding);
}
});
-
+
}
@Override
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.simantics.maps.elevation.server.ui"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.simantics.maps.elevation.server.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simantics Maps Elevation Server UI
+Bundle-SymbolicName: org.simantics.maps.elevation.server.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.maps.elevation.server.ui.Activator
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.slf4j.api;bundle-version="1.7.25",
+ org.simantics.maps.elevation.server;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: org.simantics.maps.elevation.server.ui
+Bundle-ActivationPolicy: lazy
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ category="org.simantics.district.network.ui.preferences"
+ class="org.simantics.maps.elevation.server.ui.MapsElevationServerPreferencePage"
+ id="org.simantics.maps.elevation.server.ui.preferences"
+ name="Elevation server">
+ </page>
+ </extension>
+</plugin>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.simantics.district</groupId>
+ <artifactId>org.simantics.district.root</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.simantics.maps.elevation.server.ui</artifactId>
+ <packaging>eclipse-plugin</packaging>
+ <version>1.0.0-SNAPSHOT</version>
+
+</project>
--- /dev/null
+package org.simantics.maps.elevation.server.ui;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.simantics.maps.elevation.server.ui"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
--- /dev/null
+package org.simantics.maps.elevation.server.ui;
+
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
+import org.simantics.maps.elevation.server.prefs.MapsElevationServerPreferences;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MapsElevationServerPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MapsElevationServerPreferencePage.class);
+
+ public MapsElevationServerPreferencePage() {
+ super(GRID);
+ setDescription("Maps elevation server preferences");
+ }
+
+ @Override
+ protected IPreferenceStore doGetPreferenceStore() {
+ return new ScopedPreferenceStore(InstanceScope.INSTANCE, MapsElevationServerPreferences.P_NODE);
+ }
+
+ private void createGeneralGroup() {
+ Group serverGroup = new Group(getFieldEditorParent(), SWT.NONE);
+ serverGroup.setText("General");
+ GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(serverGroup);
+
+ BooleanFieldEditor automatically = new BooleanFieldEditor(MapsElevationServerPreferences.P_USE_ELEVATION_SERVER, "Use elevation server", serverGroup);
+ addField(automatically);
+
+ GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(serverGroup);
+ }
+
+ @Override
+ protected void createFieldEditors() {
+ createGeneralGroup();
+
+ }
+
+ @Override
+ protected void performApply() {
+ super.performApply();
+ }
+
+ @Override
+ public void init(IWorkbench workbench) {
+
+ }
+
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.simantics.maps.elevation.server</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simantics Maps Elevation Server
+Bundle-SymbolicName: org.simantics.maps.elevation.server;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: org.simantics.maps.elevation.server
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.simantics.district.geotools;bundle-version="1.0.0",
+ org.slf4j.api;bundle-version="1.7.25",
+ com.github.benmanes.caffeine;bundle-version="2.6.2",
+ org.eclipse.jetty.util;bundle-version="9.4.5",
+ org.eclipse.osgi,
+ org.eclipse.core.runtime;bundle-version="3.13.0",
+ org.eclipse.equinox.preferences
+Export-Package: org.simantics.maps.elevation.server,
+ org.simantics.maps.elevation.server.prefs
+Bundle-ActivationPolicy: lazy
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.simantics.district</groupId>
+ <artifactId>org.simantics.district.root</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.simantics.maps.elevation.server</artifactId>
+ <packaging>eclipse-plugin</packaging>
+ <version>1.0.0-SNAPSHOT</version>
+
+</project>
--- /dev/null
+package org.simantics.maps.elevation.server;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.spi.ImageInputStreamSpi;
+import javax.imageio.spi.ImageOutputStreamSpi;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import it.geosolutions.imageio.stream.input.spi.FileImageInputStreamExtImplSpi;
+import it.geosolutions.imageio.stream.input.spi.StringImageInputStreamSpi;
+import it.geosolutions.imageio.stream.input.spi.URLImageInputStreamSpi;
+import it.geosolutions.imageio.stream.output.spi.FileImageOutputStreamExtImplSpi;
+import it.geosolutions.imageio.stream.output.spi.StringImageOutputStreamSpi;
+import it.geosolutions.imageio.stream.output.spi.URLImageOutputStreamSpi;
+
+public class Activator implements BundleActivator {
+
+ private static AtomicBoolean registered = new AtomicBoolean(false);
+
+ public static final String PLUGIN_ID = "org.simantics.maps.elevation.server";
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ // register SPI's
+ registerSpis();
+ }
+
+ public static void registerSpis() {
+ if (!registered.getAndSet(true)) {
+ IIORegistry.getDefaultInstance().registerServiceProvider(new FileImageInputStreamExtImplSpi(), ImageInputStreamSpi.class);
+ IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageInputStreamSpi(), ImageInputStreamSpi.class);
+ IIORegistry.getDefaultInstance().registerServiceProvider(new StringImageInputStreamSpi(), ImageInputStreamSpi.class);
+ IIORegistry.getDefaultInstance().registerServiceProvider(new FileImageOutputStreamExtImplSpi(), ImageOutputStreamSpi.class);
+ IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageOutputStreamSpi(), ImageOutputStreamSpi.class);
+ IIORegistry.getDefaultInstance().registerServiceProvider(new StringImageOutputStreamSpi(), ImageOutputStreamSpi.class);
+ }
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+
+ }
+
+}
--- /dev/null
+package org.simantics.maps.elevation.server;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SingletonTiffTileInterface {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SingletonTiffTileInterface.class);
+
+ private static final String TIFS_FOLDER = System.getProperty("tifsFolder");
+
+ private static SingletonTiffTileInterface instance = new SingletonTiffTileInterface();
+
+ private TiffTileInterface tileInterface;
+
+ private SingletonTiffTileInterface() {
+ // register spis
+ Activator.registerSpis();
+ Path tilesFolder = Paths.get("tifsFolder");
+ if (TIFS_FOLDER != null) {
+ Path potTilesFolder = Paths.get(TIFS_FOLDER);
+ if (!Files.exists(potTilesFolder)) {
+ // use default from working directory
+ tilesFolder = potTilesFolder;
+ }
+ }
+ try {
+ Files.createDirectories(tilesFolder);
+ } catch (IOException e) {
+ LOGGER.error("Could not create directories {}", tilesFolder.toAbsolutePath(), e);
+ }
+ tileInterface = new TiffTileInterface(tilesFolder);
+ }
+
+ public static Number lookup(double x, double y) {
+ return instance.tileInterface.lookup(x, y);
+ }
+}
--- /dev/null
+package org.simantics.maps.elevation.server;
+
+import java.awt.image.DataBuffer;
+import java.nio.file.Path;
+
+import org.geotools.coverage.grid.GridCoverage2D;
+import org.geotools.gce.geotiff.GeoTiffReader;
+import org.geotools.geometry.Envelope2D;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TiffInterface {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(TiffInterface.class);
+
+ private final Path tifPath;
+ private GridCoverage2D coverage;
+ private CoordinateReferenceSystem crs;
+
+ private boolean init = false;
+
+ public TiffInterface(Path tifPath) {
+ this.tifPath = tifPath;
+ loadMetadata();
+ }
+
+ private void loadMetadata() {
+ GeoTiffReader reader = null;
+ try {
+ reader = new GeoTiffReader(this.tifPath.toFile());
+ this.coverage = reader.read(null);
+ this.crs = coverage.getCoordinateReferenceSystem();
+ this.init = true;
+ } catch (Exception e) {
+ LOGGER.error("Could not load {}", tifPath, e);
+ } finally {
+ if (reader != null) {
+ reader.dispose();
+ }
+ }
+ }
+
+ public Number lookup(DirectPosition pos) {
+ ensureInit();
+ Object r = coverage.evaluate(pos);
+ final int dataType = coverage.getRenderedImage().getSampleModel().getDataType();
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE: return new Byte(((byte[]) r)[0]);
+ case DataBuffer.TYPE_SHORT: // Fall through
+ case DataBuffer.TYPE_USHORT: // Fall through
+ case DataBuffer.TYPE_INT: return new Integer(((int[]) r)[0]);
+ case DataBuffer.TYPE_FLOAT: return new Float(((float[]) r)[0]);
+ case DataBuffer.TYPE_DOUBLE: return new Double(((double[]) r)[0]);
+ default: return null;
+ }
+ }
+
+ private void ensureInit() {
+ if (!init) {
+ throw new IllegalStateException("Interface is not initialized for " + this.tifPath);
+ }
+ }
+
+ public void close() {
+ coverage.dispose(true);
+ }
+
+ public Envelope2D getCornerCoords() {
+ return coverage.getEnvelope2D();
+ }
+
+ public CoordinateReferenceSystem getCRS() {
+ return crs;
+ }
+}
--- /dev/null
+package org.simantics.maps.elevation.server;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
+
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jts.index.strtree.STRtree;
+
+import org.geotools.geometry.DirectPosition2D;
+import org.geotools.geometry.Envelope2D;
+import org.geotools.referencing.CRS;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TiffTileInterface {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(TiffTileInterface.class);
+
+ private Path tilesFolder;
+ private LoadingCache<Path, TiffInterface> interfaceCache;
+ private int openInterfacesSize;
+ private STRtree index;
+
+ public TiffTileInterface(Path tilesFolder) {
+ this(tilesFolder, 5);
+ }
+
+ public TiffTileInterface(Path tilesFolder, int openInterfacesSize) {
+ if (!Files.isDirectory(tilesFolder)) {
+ throw new IllegalArgumentException("tilesFolder has to be a folder: " + tilesFolder.toAbsolutePath());
+ }
+ this.tilesFolder = tilesFolder;
+ this.index = new STRtree();
+ this.openInterfacesSize = openInterfacesSize;
+
+ this.interfaceCache = Caffeine.newBuilder()
+ .maximumSize(this.openInterfacesSize)
+ .removalListener((key, gdalInterface, cause) -> ((TiffInterface) gdalInterface).close())
+ .build(key -> new TiffInterface(key));
+
+ try {
+ initializeIndex();
+ } catch (IOException e) {
+ LOGGER.error("Could not initialize index for folder {}", tilesFolder, e);
+ }
+ }
+
+ private TiffInterface openTifInterface(Path tifFile) {
+ return interfaceCache.get(tifFile);
+ }
+
+ private Stream<Path> allTiffFiles() throws IOException {
+ return Files.walk(tilesFolder).filter(Files::isRegularFile).filter(tif -> tif.getFileName().toString().endsWith(".tif"));
+ }
+
+ public void initializeIndex() throws IOException {
+ LOGGER.info("Initializing index..");
+ AtomicInteger counter = new AtomicInteger();
+ allTiffFiles().parallel().forEach(tifFile -> {
+ TiffInterface tifInterface = openTifInterface(tifFile);
+ Envelope2D coords = tifInterface.getCornerCoords();
+ try {
+ MathTransform transform = CRS.findMathTransform(tifInterface.getCRS(), c4326);
+ DirectPosition2D min = new DirectPosition2D();
+ DirectPosition2D max = new DirectPosition2D();
+ transform.transform(new DirectPosition2D(coords.getMinX(), coords.getMinY()), min);
+ transform.transform(new DirectPosition2D(coords.getMaxX(), coords.getMaxY()), max);
+ Envelope envelope = new Envelope(min.getX(), max.getX(), min.getY(), max.getY());
+ synchronized(index) {
+ index.insert(envelope, tifFile);
+ }
+ } catch (Exception e) {
+ LOGGER.error("Could not initialize index for file {}", tifFile, e);
+ } finally {
+ tifInterface.close();
+ int current = counter.getAndIncrement();
+ if (current % 100 == 0) {
+ LOGGER.info(" {}", current);
+ }
+ }
+ });
+ }
+
+ private static CoordinateReferenceSystem c4326;
+
+ static {
+ try {
+ c4326 = CRS.decode("EPSG:4326");
+ } catch (Exception e) {
+ LOGGER.error("Could not initialize epsg:4326", e);
+ }
+ }
+
+ public Number lookup(double x, double y) {
+ LOGGER.info("Looking up x={} y={}", x, y);
+ DirectPosition p = new DirectPosition2D(c4326, x, y);
+ List<Path> tifFile = (List<Path>) index.query(new Envelope(new Coordinate(x, y)));
+ if (!tifFile.isEmpty()) {
+ TiffInterface tifInterface = openTifInterface(tifFile.get(0));
+ try {
+ return tifInterface.lookup(p);
+ } finally {
+ tifInterface.close();
+ }
+ } else {
+ return new Double(0); // use 0 by default for now
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.maps.elevation.server.prefs;
+
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.osgi.service.prefs.Preferences;
+import org.simantics.maps.elevation.server.Activator;
+
+public class MapsElevationServerPreferences {
+
+ public static final String P_NODE = Activator.PLUGIN_ID;
+
+ public static final String P_USE_ELEVATION_SERVER = "org.simantics.maps.elevation.server.useElevationServer";
+
+ public static Preferences getPreferences() {
+ return InstanceScope.INSTANCE.getNode(MapsElevationServerPreferences.P_NODE);
+ }
+
+ public static boolean useElevationServer() {
+ return getPreferences().getBoolean(P_USE_ELEVATION_SERVER, false);
+ }
+
+}
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.simantics.maps.elevation.server"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="com.github.benmanes.caffeine"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
<layout>p2</layout>
<url>${simantics-download-site}/${branch-spec}/sdk</url>
</repository>
+ <repository>
+ <id>external-components</id>
+ <layout>p2</layout>
+ <url>${simantics-download-site}/${branch-spec}/external-components/maven</url>
+ </repository>
</repositories>
<pluginRepositories>
<module>org.simantics.district.route.feature</module>
<module>org.simantics.district.ui.feature</module>
<module>org.simantics.maps.server.feature</module>
-
+
+ <module>org.simantics.maps.elevation.server</module>
+ <module>org.simantics.maps.elevation.server.ui</module>
+
<module>org.simantics.district.repository</module>
</modules>
</project>