1 /* Copyright 2013-2025 CS GROUP
2 * Licensed to CS GROUP (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.rugged.utils.NormalizedGeodeticPoint;
21
22 /** Interface representing a raster tile.
23 * <p>
24 * The elevations are considered to be at the <em>center</em> of each cells.
25 * The minimum latitude and longitude hence correspond to the <em>center</em>
26 * of the most South-West cell, and the maximum latitude and longitude
27 * correspond to the <em>center</em> of the most North-East cell.
28 * </p>
29 * @author Luc Maisonobe
30 * @author Guylaine Prat
31 */
32 public interface Tile extends UpdatableTile {
33
34 /** Enumerate for point location with respect to the interpolation grid of a tile.
35 * <p>
36 * Elevations in a tile are interpolated using the four neighboring points
37 * in a grid: (i, j), (i+1, j), (i, j+1), (i+1), (j+1). This implies that a point
38 * can be interpolated only if the elevation for these four points is available
39 * in the tile. A consequence is that a point in the northernmost row (resp.
40 * easternmost column) miss neighboring points at row j+1 (resp. neighboring points
41 * at column i+1) and therefore cannot be interpolated.
42 * </p>
43 * <p>
44 * This enumerate represent the position of a point taking this off-by-one property
45 * into account, the value {@link #HAS_INTERPOLATION_NEIGHBORS} correspond to points that
46 * do have the necessary four neighbors, whereas the other values correspond to points
47 * that are either completely outside of the tile or within the tile but in either the
48 * northernmost row or easternmost column.
49 * </p>
50 */
51 enum Location {
52
53 /** Location for points out of tile interpolation grid, in the South-West corner direction. */
54 SOUTH_WEST,
55
56 /** Location for points out of tile interpolation grid, in the West edge direction. */
57 WEST,
58
59 /** Location for points out of tile interpolation grid, in the North-West corner direction.
60 * <p>
61 * The point may still be in the tile, but in the northernmost row thus missing required
62 * interpolation points.
63 * </p>
64 */
65 NORTH_WEST,
66
67 /** Location for points out of tile interpolation grid, in the North edge direction.
68 * <p>
69 * The point may still be in the tile, but in the northernmost row thus missing required
70 * interpolation points.
71 * </p>
72 */
73 NORTH,
74
75 /** Location for points out of tile interpolation grid, in the North-East corner direction.
76 * <p>
77 * The point may still be in the tile, but either in the northernmost row or in the
78 * easternmost column thus missing required interpolation points.
79 * </p>
80 */
81 NORTH_EAST,
82
83 /** Location for points out of tile interpolation grid, in the East edge direction.
84 * <p>
85 * The point may still be in the tile, but in the easternmost column thus missing required
86 * interpolation points.
87 * </p>
88 */
89 EAST,
90
91 /** Location for points out of tile interpolation grid, in the South-East corner direction.
92 * <p>
93 * The point may still be in the tile, but in the easternmost column thus missing required
94 * interpolation points.
95 * </p>
96 */
97 SOUTH_EAST,
98
99 /** Location for points out of tile interpolation grid, in the South edge direction. */
100 SOUTH,
101
102 /** Location for points that do have interpolation neighbors.
103 * <p>
104 * The value corresponds to points that can be interpolated using their four
105 * neighboring points in the grid at indices (i, j), (i+1, j), (i, j+1), (i+1),
106 * (j+1). This implies that these points are neither in the northernmost latitude
107 * row nor in the easternmost longitude column.
108 * </p>
109 */
110 HAS_INTERPOLATION_NEIGHBORS
111
112 }
113
114 /** Hook called at the end of tile update completion.
115 */
116 void tileUpdateCompleted();
117
118 /** Get minimum latitude of grid interpolation points.
119 * @return minimum latitude of grid interpolation points (rad)
120 * (latitude of the center of the cells of South row)
121 */
122 double getMinimumLatitude();
123
124 /** Get the latitude at some index.
125 * @param latitudeIndex latitude index
126 * @return latitude at the specified index (rad)
127 * (latitude of the center of the cells of specified row)
128 */
129 double getLatitudeAtIndex(int latitudeIndex);
130
131 /** Get maximum latitude.
132 * <p>
133 * Beware that as a point at maximum latitude is the northernmost
134 * one of the grid, it doesn't have a northwards neighbor and
135 * therefore calling {@link #getLocation(double, double) getLocation}
136 * on such a latitude will return either {@link Location#NORTH_WEST},
137 * {@link Location#NORTH} or {@link Location#NORTH_EAST}, but can
138 * <em>never</em> return {@link Location#HAS_INTERPOLATION_NEIGHBORS}!
139 * </p>
140 * @return maximum latitude (rad)
141 * (latitude of the center of the cells of North row)
142 */
143 double getMaximumLatitude();
144
145 /** Get minimum longitude.
146 * @return minimum longitude (rad)
147 * (longitude of the center of the cells of West column)
148 */
149 double getMinimumLongitude();
150
151 /** Get the longitude at some index.
152 * @param longitudeIndex longitude index
153 * @return longitude at the specified index (rad)
154 * (longitude of the center of the cells of specified column)
155 */
156 double getLongitudeAtIndex(int longitudeIndex);
157
158 /** Get maximum longitude.
159 * <p>
160 * Beware that as a point at maximum longitude is the easternmost
161 * one of the grid, it doesn't have an eastwards neighbor and
162 * therefore calling {@link #getLocation(double, double) getLocation}
163 * on such a longitude will return either {@link Location#SOUTH_EAST},
164 * {@link Location#EAST} or {@link Location#NORTH_EAST}, but can
165 * <em>never</em> return {@link Location#HAS_INTERPOLATION_NEIGHBORS}!
166 * </p>
167 * @return maximum longitude (rad)
168 * (longitude of the center of the cells of East column)
169 */
170 double getMaximumLongitude();
171
172 /** Get step in latitude (size of one raster element).
173 * @return step in latitude (rad)
174 */
175 double getLatitudeStep();
176
177 /** Get step in longitude (size of one raster element).
178 * @return step in longitude (rad)
179 */
180 double getLongitudeStep();
181
182 /** Get number of latitude rows.
183 * @return number of latitude rows
184 */
185 int getLatitudeRows();
186
187 /** Get number of longitude columns.
188 * @return number of longitude columns
189 */
190 int getLongitudeColumns();
191
192 /** Get the floor latitude index of a point.
193 * <p>
194 * The specified latitude is always between index and index+1.
195 * </p>
196 * @param latitude geodetic latitude
197 * @return floor latitude index (it may lie outside of the tile!)
198 */
199 int getFloorLatitudeIndex(double latitude);
200
201 /** Get the floor longitude index of a point.
202 * <p>
203 * The specified longitude is always between index and index+1.
204 * </p>
205 * @param longitude geodetic longitude
206 * @return floor longitude index (it may lie outside of the tile!)
207 */
208 int getFloorLongitudeIndex(double longitude);
209
210 /** Get the minimum elevation in the tile.
211 * @return minimum elevation in the tile (m)
212 */
213 double getMinElevation();
214
215 /** Get the latitude index of min elevation.
216 * @return latitude index of min elevation*/
217 int getMinElevationLatitudeIndex();
218
219 /** Get the longitude index of min elevation.
220 * @return longitude index of min elevation*/
221 int getMinElevationLongitudeIndex();
222
223 /** Get the maximum elevation in the tile.
224 * @return maximum elevation in the tile (m)
225 */
226 double getMaxElevation();
227
228 /** Get the latitude index of max elevation.
229 * @return latitude index of max elevation*/
230 int getMaxElevationLatitudeIndex();
231
232 /** Get the longitude index of max elevation.
233 * @return longitude index of max elevation*/
234 int getMaxElevationLongitudeIndex();
235
236 /** Get the elevation of an exact grid point.
237 * @param latitudeIndex grid point index along latitude
238 * @param longitudeIndex grid point index along longitude
239 * @return elevation at grid point (m)
240 */
241 double getElevationAtIndices(int latitudeIndex, int longitudeIndex);
242
243 /** Interpolate elevation.
244 * <p>
245 * In order to cope with numerical accuracy issues when computing
246 * points at tile boundary, a slight tolerance (typically 1/8 cell)
247 * around the tile is allowed. Elevation can therefore be interpolated
248 * (really extrapolated in this case) even for points slightly overshooting
249 * tile boundaries, using the closest tile cell. Attempting to interpolate
250 * too far from the tile will trigger an exception.
251 * </p>
252 * @param latitude ground point latitude
253 * @param longitude ground point longitude
254 * @return interpolated elevation (m)
255 */
256 double interpolateElevation(double latitude, double longitude);
257
258 /** Find the intersection of a line-of-sight and a Digital Elevation Model cell.
259 * <p>
260 * Beware that for continuity reasons, the point argument in {@code cellIntersection} is normalized
261 * with respect to other points used by the caller. This implies that the longitude may be
262 * outside of the [-π ; +π] interval (or the [0 ; 2π] interval, depending on the DEM). In particular,
263 * when a Line Of Sight crosses the antimeridian at ±π longitude, the library may call the
264 * {@code cellIntersection} method with a point having a longitude of -π-ε to ensure this continuity.
265 * As tiles are stored with longitude clipped to a some DEM specific interval (either [-π ; +π] or [0 ; 2π]),
266 * implementations MUST take care to clip the input point back to the tile interval using
267 * {@link org.hipparchus.util.MathUtils#normalizeAngle(double, double) MathUtils.normalizeAngle(p.getLongitude(),
268 * someLongitudeWithinTheTile)}. The output point normalization should also be made consistent with
269 * the current tile.
270 * </p>
271 * @param p point on the line (beware its longitude is <em>not</em> normalized with respect to tile)
272 * @param los line-of-sight, in the topocentric frame (East, North, Zenith) of the point,
273 * scaled to match radians in the horizontal plane and meters along the vertical axis
274 * @param latitudeIndex latitude index of the Digital Elevation Model cell
275 * @param longitudeIndex longitude index of the Digital Elevation Model cell
276 * @return point corresponding to line-of-sight crossing the Digital Elevation Model surface
277 * if it lies within the cell, null otherwise
278 */
279 NormalizedGeodeticPoint cellIntersection(NormalizedGeodeticPoint p, Vector3D los,
280 int latitudeIndex, int longitudeIndex);
281
282 /** Check if a tile covers a ground point.
283 * @param latitude ground point latitude
284 * @param longitude ground point longitude
285 * @return location of the ground point with respect to tile
286 */
287 Location getLocation(double latitude, double longitude);
288
289 }