1 package org.simantics.maps.elevation.server;
3 import java.awt.geom.Point2D;
4 import java.awt.image.DataBuffer;
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.geometry.TransformedDirectPosition;
11 import org.opengis.geometry.DirectPosition;
12 import org.opengis.geometry.Envelope;
13 import org.opengis.referencing.crs.CoordinateReferenceSystem;
14 import org.opengis.referencing.operation.TransformException;
15 import org.simantics.maps.elevation.server.prefs.MapsElevationServerPreferences;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
19 public class TiffInterface {
21 private static final Logger LOGGER = LoggerFactory.getLogger(TiffInterface.class);
23 private final Path tifPath;
24 private GridCoverage2D coverage;
25 private CoordinateReferenceSystem crs;
27 private boolean init = false;
29 public TiffInterface(Path tifPath) {
30 this.tifPath = tifPath;
34 private void loadMetadata() {
35 GeoTiffReader reader = null;
37 reader = new GeoTiffReader(this.tifPath.toFile());
38 this.coverage = reader.read(null);
39 this.crs = coverage.getCoordinateReferenceSystem();
41 } catch (Exception e) {
42 LOGGER.error("Could not load {}", tifPath, e);
50 public boolean contains(DirectPosition pos) {
52 Envelope2D e = coverage.getEnvelope2D();
54 TransformedDirectPosition tdp = new TransformedDirectPosition(pos.getCoordinateReferenceSystem(), crs, null);
57 Point2D p = tdp.toPoint2D();
59 boolean contains = e.contains(p);
61 } catch (Exception ex) {
67 public Number lookup(DirectPosition pos) {
69 Object r = coverage.evaluate(pos);
70 final int dataType = coverage.getRenderedImage().getSampleModel().getDataType();
71 int pipeDepthUnderGround = MapsElevationServerPreferences.pipeDepthUnderGround();
73 case DataBuffer.TYPE_BYTE: {
74 // TODO: if the result is byte how does one subtract the pipeDepth form the value?
75 // Might not be even relevant with this use case
76 return new Byte(((byte[]) r)[0]);
78 case DataBuffer.TYPE_SHORT: // Fall through
79 case DataBuffer.TYPE_USHORT: // Fall through
80 case DataBuffer.TYPE_INT: {
81 int val = ((int[]) r)[0] - pipeDepthUnderGround;
82 return new Integer(val);
84 case DataBuffer.TYPE_FLOAT: {
85 float val = ((float[]) r)[0] - pipeDepthUnderGround;
86 return new Float(val);
88 case DataBuffer.TYPE_DOUBLE: {
89 double val = ((double[]) r)[0] - pipeDepthUnderGround;
90 return new Double(val);
96 private void ensureInit() {
98 throw new IllegalStateException("Interface is not initialized for " + this.tifPath);
102 public void close() {
103 coverage.dispose(true);
106 public Envelope2D getCornerCoords() {
107 return coverage.getEnvelope2D();
110 public CoordinateReferenceSystem getCRS() {