1   /* Copyright 2013-2019 CS Systèmes d'Information
2    * Licensed to CS Systèmes d'Information (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.rugged.raster;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.orekit.bodies.GeodeticPoint;
21  import org.orekit.rugged.utils.NormalizedGeodeticPoint;
22  
23  /** Interface representing a raster tile.
24   * <p>
25   * The elevations are considered to be at the <em>center</em> of each cells.
26   * The minimum latitude and longitude hence correspond to the <em>center</em>
27   * of the most South-West cell, and the maximum latitude and longitude
28   * correspond to the <em>center</em> of the most North-East cell.
29   * </p>
30   * @author Luc Maisonobe
31   * @author Guylaine Prat
32   */
33  public interface Tile extends UpdatableTile {
34  
35      /** Enumerate for point location with respect to the interpolation grid of a tile.
36       * <p>
37       * Elevations in a tile are interpolated using the four neighboring points
38       * in a grid: (i, j), (i+1, j), (i, j+1), (i+1), (j+1). This implies that a point
39       * can be interpolated only if the elevation for these four points is available
40       * in the tile. A consequence is that a point in the northernmost row (resp.
41       * easternmost column) miss neighboring points at row j+1 (resp. neighboring points
42       * at column i+1) and therefore cannot be interpolated.
43       * </p>
44       * <p>
45       * This enumerate represent the position of a point taking this off-by-one property
46       * into account, the value {@link #HAS_INTERPOLATION_NEIGHBORS} correspond to points that
47       * do have the necessary four neightbors, whereas the other values correspond to points
48       * that are either completely outside of the tile or within the tile but in either the
49       * northernmost row or easternmost column.
50       * </p>
51       */
52      enum Location {
53  
54          /** Location for points out of tile interpolation grid, in the South-West corner direction. */
55          SOUTH_WEST,
56  
57          /** Location for points out of tile interpolation grid, in the West edge direction. */
58          WEST,
59  
60          /** Location for points out of tile interpolation grid, in the North-West corner direction.
61           * <p>
62           * The point may still be in the tile, but in the northernmost row thus missing required
63           * interpolation points.
64           * </p>
65           */
66          NORTH_WEST,
67  
68          /** Location for points out of tile interpolation grid, in the North edge direction.
69           * <p>
70           * The point may still be in the tile, but in the northernmost row thus missing required
71           * interpolation points.
72           * </p>
73           */
74          NORTH,
75  
76          /** Location for points out of tile interpolation grid, in the North-East corner direction.
77           * <p>
78           * The point may still be in the tile, but either in the northernmost row or in the
79           * easternmost column thus missing required interpolation points.
80           * </p>
81           */
82          NORTH_EAST,
83  
84          /** Location for points out of tile interpolation grid, in the East edge direction.
85           * <p>
86           * The point may still be in the tile, but in the easternmost column thus missing required
87           * interpolation points.
88           * </p>
89           */
90          EAST,
91  
92          /** Location for points out of tile interpolation grid, in the South-East corner direction.
93           * <p>
94           * The point may still be in the tile, but in the easternmost column thus missing required
95           * interpolation points.
96           * </p>
97           */
98          SOUTH_EAST,
99  
100         /** Location for points out of tile interpolation grid, in the South edge direction. */
101         SOUTH,
102 
103         /** Location for points that do have interpolation neighbors.
104          * <p>
105          * The value corresponds to points that can be interpolated using their four
106          * neighboring points in the grid at indices (i, j), (i+1, j), (i, j+1), (i+1),
107          * (j+1). This implies that these points are neither in the northernmost latitude
108          * row nor in the easternmost longitude column.
109          * </p>
110          */
111         HAS_INTERPOLATION_NEIGHBORS
112 
113     }
114 
115     /** Hook called at the end of tile update completion.
116      */
117     void tileUpdateCompleted();
118 
119     /** Get minimum latitude of grid interpolation points.
120      * @return minimum latitude of grid interpolation points (rad)
121      * (latitude of the center of the cells of South row)
122      */
123     double getMinimumLatitude();
124 
125     /** Get the latitude at some index.
126      * @param latitudeIndex latitude index
127      * @return latitude at the specified index (rad)
128      * (latitude of the center of the cells of specified row)
129      */
130     double getLatitudeAtIndex(int latitudeIndex);
131 
132     /** Get maximum latitude.
133      * <p>
134      * Beware that as a point at maximum latitude is the northernmost
135      * one of the grid, it doesn't have a northwards neighbor and
136      * therefore calling {@link #getLocation(double, double) getLocation}
137      * on such a latitude will return either {@link Location#NORTH_WEST},
138      * {@link Location#NORTH} or {@link Location#NORTH_EAST}, but can
139      * <em>never</em> return {@link Location#HAS_INTERPOLATION_NEIGHBORS}!
140      * </p>
141      * @return maximum latitude (rad)
142      * (latitude of the center of the cells of North row)
143      */
144     double getMaximumLatitude();
145 
146     /** Get minimum longitude.
147      * @return minimum longitude (rad)
148      * (longitude of the center of the cells of West column)
149      */
150     double getMinimumLongitude();
151 
152     /** Get the longitude at some index.
153      * @param longitudeIndex longitude index
154      * @return longitude at the specified index (rad)
155      * (longitude of the center of the cells of specified column)
156      */
157     double getLongitudeAtIndex(int longitudeIndex);
158 
159     /** Get maximum longitude.
160      * <p>
161      * Beware that as a point at maximum longitude is the easternmost
162      * one of the grid, it doesn't have an eastwards neighbor and
163      * therefore calling {@link #getLocation(double, double) getLocation}
164      * on such a longitude will return either {@link Location#SOUTH_EAST},
165      * {@link Location#EAST} or {@link Location#NORTH_EAST}, but can
166      * <em>never</em> return {@link Location#HAS_INTERPOLATION_NEIGHBORS}!
167      * </p>
168      * @return maximum longitude (rad)
169      * (longitude of the center of the cells of East column)
170      */
171     double getMaximumLongitude();
172 
173     /** Get step in latitude (size of one raster element).
174      * @return step in latitude (rad)
175      */
176     double getLatitudeStep();
177 
178     /** Get step in longitude (size of one raster element).
179      * @return step in longitude (rad)
180      */
181     double getLongitudeStep();
182 
183     /** Get number of latitude rows.
184      * @return number of latitude rows
185      */
186     int getLatitudeRows();
187 
188     /** Get number of longitude columns.
189      * @return number of longitude columns
190      */
191     int getLongitudeColumns();
192 
193     /** Get the floor latitude index of a point.
194      * <p>
195      * The specified latitude is always between index and index+1.
196      * </p>
197      * @param latitude geodetic latitude
198      * @return floor latitude index (it may lie outside of the tile!)
199      */
200     int getFloorLatitudeIndex(double latitude);
201 
202     /** Get the floor longitude index of a point.
203      * <p>
204      * The specified longitude is always between index and index+1.
205      * </p>
206      * @param longitude geodetic longitude
207      * @return floor longitude index (it may lie outside of the tile!)
208      */
209     int getFloorLongitudeIndex(double longitude);
210 
211     /** Get the minimum elevation in the tile.
212      * @return minimum elevation in the tile (m)
213      */
214     double getMinElevation();
215 
216     /** Get the latitude index of min elevation.
217      * @return latitude index of min elevation*/
218     int getMinElevationLatitudeIndex();
219 
220     /** Get the longitude index of min elevation.
221      * @return longitude index of min elevation*/
222     int getMinElevationLongitudeIndex();
223 
224    /** Get the maximum elevation in the tile.
225      * @return maximum elevation in the tile (m)
226      */
227     double getMaxElevation();
228 
229     /** Get the latitude index of max elevation.
230      * @return latitude index of max elevation*/
231     int getMaxElevationLatitudeIndex();
232 
233     /** Get the longitude index of max elevation.
234      * @return longitude index of max elevation*/
235     int getMaxElevationLongitudeIndex();
236 
237     /** Get the elevation of an exact grid point.
238      * @param latitudeIndex grid point index along latitude
239      * @param longitudeIndex grid point index along longitude
240      * @return elevation at grid point (m)
241      */
242     double getElevationAtIndices(int latitudeIndex, int longitudeIndex);
243 
244     /** Interpolate elevation.
245      * <p>
246      * In order to cope with numerical accuracy issues when computing
247      * points at tile boundary, a slight tolerance (typically 1/8 cell)
248      * around the tile is allowed. Elevation can therefore be interpolated
249      * (really extrapolated in this case) even for points slightly overshooting
250      * tile boundaries, using the closest tile cell. Attempting to interpolate
251      * too far from the tile will trigger an exception.
252      * </p>
253      * @param latitude ground point latitude
254      * @param longitude ground point longitude
255      * @return interpolated elevation (m)
256      */
257     double interpolateElevation(double latitude, double longitude);
258 
259     /** Find the intersection of a line-of-sight and a Digital Elevation Model cell.
260      * @param p point on the line
261      * @param los line-of-sight, in the topocentric frame (East, North, Zenith) of the point,
262      * scaled to match radians in the horizontal plane and meters along the vertical axis
263      * @param latitudeIndex latitude index of the Digital Elevation Model cell
264      * @param longitudeIndex longitude index of the Digital Elevation Model cell
265      * @return point corresponding to line-of-sight crossing the Digital Elevation Model surface
266      * if it lies within the cell, null otherwise
267      */
268     NormalizedGeodeticPoint cellIntersection(GeodeticPoint p, Vector3D los,
269                                               int latitudeIndex, int longitudeIndex);
270 
271     /** Check if a tile covers a ground point.
272      * @param latitude ground point latitude
273      * @param longitude ground point longitude
274      * @return location of the ground point with respect to tile
275      */
276     Location getLocation(double latitude, double longitude);
277 
278 }