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.util.FastMath;
20 import java.lang.reflect.Array;
21
22 import org.orekit.rugged.errors.DumpManager;
23 import org.orekit.rugged.errors.RuggedException;
24 import org.orekit.rugged.errors.RuggedMessages;
25
26 /** Cache for Digital Elevation Model {@link Tile tiles}.
27 * <p>
28 * Beware, this cache is <em>not</em> thread-safe!
29 * </p>
30 * @param <T> Type of tiles.
31 * @author Luc Maisonobe
32 */
33 public class TilesCache<T extends Tile> {
34
35 /** Factory for empty tiles. */
36 private final TileFactory<T> factory;
37
38 /** Updater for retrieving tiles data. */
39 private final TileUpdater updater;
40
41 /** Cache. */
42 private final T[] tiles;
43
44 /** Simple constructor.
45 * @param factory factory for creating empty tiles
46 * @param updater updater for retrieving tiles data
47 * @param maxTiles maximum number of tiles stored simultaneously in the cache
48 */
49 public TilesCache(final TileFactory<T> factory, final TileUpdater updater, final int maxTiles) {
50 this.factory = factory;
51 this.updater = updater;
52 @SuppressWarnings("unchecked")
53 final T[] array = (T[]) Array.newInstance(Tile.class, maxTiles);
54 this.tiles = array;
55 }
56
57 /** Get the tile covering a ground point.
58 * @param latitude ground point latitude
59 * @param longitude ground point longitude
60 * @return tile covering the ground point
61 */
62 public T getTile(final double latitude, final double longitude) {
63
64 for (int i = 0; i < tiles.length; ++i) {
65 final T tile = tiles[i];
66 if (tile != null && tile.getLocation(latitude, longitude) == Tile.Location.HAS_INTERPOLATION_NEIGHBORS) {
67 // we have found the tile in the cache
68
69 // put it on the front as it becomes the most recently used
70 while (i > 0) {
71 tiles[i] = tiles[i - 1];
72 --i;
73 }
74 tiles[0] = tile;
75
76 return tile;
77
78 }
79 }
80
81 // none of the tiles in the cache covers the specified points
82
83 // make some room in the cache, possibly evicting the least recently used one
84 for (int i = tiles.length - 1; i > 0; --i) {
85 tiles[i] = tiles[i - 1];
86 }
87
88 // create the tile and retrieve its data
89 final T tile = factory.createTile();
90
91 // In case dump is asked for, suspend the dump manager as we don't need to dump anything here
92 // For instance for SRTM DEM, the user needs to read Geoid data that are not useful in the dump
93 final Boolean wasSuspended = DumpManager.suspend();
94
95 updater.updateTile(latitude, longitude, tile);
96
97 // Resume the dump manager if necessary
98 DumpManager.resume(wasSuspended);
99
100 tile.tileUpdateCompleted();
101
102 if (tile.getLocation(latitude, longitude) != Tile.Location.HAS_INTERPOLATION_NEIGHBORS) {
103 // this should happen only if user set up an inconsistent TileUpdater
104 throw new RuggedException(RuggedMessages.TILE_WITHOUT_REQUIRED_NEIGHBORS_SELECTED,
105 FastMath.toDegrees(latitude),
106 FastMath.toDegrees(longitude));
107 }
108
109 tiles[0] = tile;
110 return tile;
111
112 }
113
114 }