]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.elevation.server/src/org/simantics/maps/elevation/server/TiffInterface.java
Fix elevation bounding box profile shift & elevation transform fixes
[simantics/district.git] / org.simantics.maps.elevation.server / src / org / simantics / maps / elevation / server / TiffInterface.java
1 package org.simantics.maps.elevation.server;
2
3 import java.awt.image.DataBuffer;
4 import java.nio.file.Path;
5
6 import org.geotools.coverage.grid.GridCoverage2D;
7 import org.geotools.gce.geotiff.GeoTiffReader;
8 import org.geotools.geometry.Envelope2D;
9 import org.geotools.referencing.CRS;
10 import org.opengis.geometry.DirectPosition;
11 import org.opengis.referencing.crs.CoordinateReferenceSystem;
12 import org.opengis.referencing.operation.MathTransform;
13 import org.simantics.maps.elevation.server.prefs.MapsElevationServerPreferences;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 public class TiffInterface {
18
19     private static final Logger LOGGER = LoggerFactory.getLogger(TiffInterface.class);
20
21     private final Path tifPath;
22     private GridCoverage2D coverage;
23
24     private boolean init = false;
25
26     public TiffInterface(Path tifPath) {
27         this.tifPath = tifPath;
28         loadMetadata();
29     }
30
31     private void loadMetadata() {
32         GeoTiffReader reader = null;
33         try {
34             reader = new GeoTiffReader(this.tifPath.toFile());
35             this.coverage = reader.read(null);
36             this.init = true;
37         } catch (Exception e) {
38             LOGGER.error("Could not load {}", tifPath, e);
39         } finally {
40             if (reader != null) {
41                 reader.dispose();
42             }
43         }
44     }
45
46     public boolean contains(DirectPosition pos) {
47         ensureInit();
48         Envelope2D e = coverage.getEnvelope2D();
49         try {
50             MathTransform transform = CRS.findMathTransform(pos.getCoordinateReferenceSystem(), getCRS(), false);
51             DirectPosition target = transform.transform(pos, null);
52             boolean contains = e.contains(target);
53             return contains;
54         } catch (Exception ex) {
55             ex.printStackTrace();
56             return false;
57         }
58     }
59     
60     public Number lookup(DirectPosition pos) {
61         ensureInit();
62         Object r = coverage.evaluate(pos);
63         final int dataType = coverage.getRenderedImage().getSampleModel().getDataType();
64         int pipeDepthUnderGround = MapsElevationServerPreferences.pipeDepthUnderGround();
65         switch (dataType) {
66             case DataBuffer.TYPE_BYTE: {
67                 // TODO: if the result is byte how does one subtract the pipeDepth form the value?
68                 // Might not be even relevant with this use case 
69                 return new Byte(((byte[]) r)[0]);
70             }
71             case DataBuffer.TYPE_SHORT:  // Fall through
72             case DataBuffer.TYPE_USHORT: // Fall through
73             case DataBuffer.TYPE_INT: {
74                 int val = ((int[]) r)[0] - pipeDepthUnderGround;
75                 return new Integer(val);
76             }
77             case DataBuffer.TYPE_FLOAT: {
78                 float val = ((float[]) r)[0] - pipeDepthUnderGround;
79                 return new Float(val);
80             }
81             case DataBuffer.TYPE_DOUBLE: {
82                 double val = ((double[]) r)[0] - pipeDepthUnderGround;
83                 return new Double(val);
84             }
85             default: return null;
86         }
87     }
88
89     private void ensureInit() {
90         if (!init) {
91             throw new IllegalStateException("Interface is not initialized for " + this.tifPath);
92         }
93     }
94
95     public void close() {
96         coverage.dispose(true);
97     }
98
99     public Envelope2D getCornerCoords() {
100         return coverage.getEnvelope2D();
101     }
102
103     public CoordinateReferenceSystem getCRS() {
104         return coverage.getCoordinateReferenceSystem();
105     }
106 }