1 package org.simantics.maps.elevation.server;
3 import java.awt.image.DataBuffer;
4 import java.io.Closeable;
5 import java.nio.file.Path;
7 import org.geotools.coverage.grid.GridCoverage2D;
8 import org.geotools.gce.geotiff.GeoTiffReader;
9 import org.geotools.geometry.Envelope2D;
10 import org.geotools.referencing.CRS;
11 import org.opengis.geometry.DirectPosition;
12 import org.opengis.referencing.crs.CoordinateReferenceSystem;
13 import org.opengis.referencing.operation.MathTransform;
14 import org.simantics.maps.elevation.server.prefs.MapsElevationServerPreferences;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
18 public class TiffInterface implements Closeable {
20 private static final Logger LOGGER = LoggerFactory.getLogger(TiffInterface.class);
22 private final Path tifPath;
23 private GridCoverage2D coverage;
25 private boolean init = false;
27 public TiffInterface(Path tifPath) {
28 this.tifPath = tifPath;
32 private void loadMetadata() {
33 GeoTiffReader reader = null;
35 reader = new GeoTiffReader(this.tifPath.toFile());
36 this.coverage = reader.read(null);
38 } catch (Exception e) {
39 LOGGER.error("Could not load {}", tifPath, e);
47 public boolean contains(DirectPosition pos) {
49 Envelope2D e = coverage.getEnvelope2D();
51 MathTransform transform = CRS.findMathTransform(pos.getCoordinateReferenceSystem(), getCRS(), false);
52 DirectPosition target = transform.transform(pos, null);
53 boolean contains = e.contains(target);
55 } catch (Exception ex) {
61 public Number lookup(DirectPosition pos) {
63 Object r = coverage.evaluate(pos);
64 final int dataType = coverage.getRenderedImage().getSampleModel().getDataType();
65 int pipeDepthUnderGround = MapsElevationServerPreferences.pipeDepthUnderGround();
67 case DataBuffer.TYPE_BYTE: {
68 // TODO: if the result is byte how does one subtract the pipeDepth form the value?
69 // Might not be even relevant with this use case
70 return Byte.valueOf(((byte[]) r)[0]);
72 case DataBuffer.TYPE_SHORT: // Fall through
73 case DataBuffer.TYPE_USHORT: // Fall through
74 case DataBuffer.TYPE_INT: {
75 int val = ((int[]) r)[0] - pipeDepthUnderGround;
76 return Integer.valueOf(val);
78 case DataBuffer.TYPE_FLOAT: {
79 float val = ((float[]) r)[0] - pipeDepthUnderGround;
80 return Float.valueOf(val);
82 case DataBuffer.TYPE_DOUBLE: {
83 double val = ((double[]) r)[0] - pipeDepthUnderGround;
84 return Double.valueOf(val);
90 private void ensureInit() {
92 throw new IllegalStateException("Interface is not initialized for " + this.tifPath);
97 coverage.dispose(true);
100 public Envelope2D getCornerCoords() {
101 return coverage.getEnvelope2D();
104 public CoordinateReferenceSystem getCRS() {
105 return coverage.getCoordinateReferenceSystem();