TilesCache.java

  1. /* Copyright 2013-2022 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. import org.hipparchus.util.FastMath;
  19. import java.lang.reflect.Array;

  20. import org.orekit.rugged.errors.DumpManager;
  21. import org.orekit.rugged.errors.RuggedException;
  22. import org.orekit.rugged.errors.RuggedMessages;

  23. /** Cache for Digital Elevation Model {@link Tile tiles}.
  24.  * <p>
  25.  * Beware, this cache is <em>not</em> thread-safe!
  26.  * </p>
  27.  * @param <T> Type of tiles.
  28.  * @author Luc Maisonobe
  29.  */
  30. public class TilesCache<T extends Tile> {

  31.     /** Factory for empty tiles. */
  32.     private final TileFactory<T> factory;

  33.     /** Updater for retrieving tiles data. */
  34.     private final TileUpdater updater;

  35.     /** Cache. */
  36.     private final T[] tiles;

  37.     /** Simple constructor.
  38.      * @param factory factory for creating empty tiles
  39.      * @param updater updater for retrieving tiles data
  40.      * @param maxTiles maximum number of tiles stored simultaneously in the cache
  41.      */
  42.     public TilesCache(final TileFactory<T> factory, final TileUpdater updater, final int maxTiles) {
  43.         this.factory       = factory;
  44.         this.updater    = updater;
  45.         @SuppressWarnings("unchecked")
  46.         final T[] array = (T[]) Array.newInstance(Tile.class, maxTiles);
  47.         this.tiles = array;
  48.     }

  49.     /** Get the tile covering a ground point.
  50.      * @param latitude ground point latitude
  51.      * @param longitude ground point longitude
  52.      * @return tile covering the ground point
  53.      */
  54.     public T getTile(final double latitude, final double longitude) {

  55.         for (int i = 0; i < tiles.length; ++i) {
  56.             final T tile = tiles[i];
  57.             if (tile != null && tile.getLocation(latitude, longitude) == Tile.Location.HAS_INTERPOLATION_NEIGHBORS) {
  58.                 // we have found the tile in the cache

  59.                 // put it on the front as it becomes the most recently used
  60.                 while (i > 0) {
  61.                     tiles[i] = tiles[i - 1];
  62.                     --i;
  63.                 }
  64.                 tiles[0] = tile;

  65.                 return tile;

  66.             }
  67.         }

  68.         // none of the tiles in the cache covers the specified points

  69.         // make some room in the cache, possibly evicting the least recently used one
  70.         for (int i = tiles.length - 1; i > 0; --i) {
  71.             tiles[i] = tiles[i - 1];
  72.         }

  73.         // create the tile and retrieve its data
  74.         final T tile = factory.createTile();

  75.         // In case dump is asked for, suspend the dump manager as we don't need to dump anything here
  76.         // For instance for SRTM DEM, the user needs to read Geoid data that are not useful in the dump
  77.         final Boolean wasSuspended = DumpManager.suspend();

  78.         updater.updateTile(latitude, longitude, tile);

  79.         // Resume the dump manager if necessary
  80.         DumpManager.resume(wasSuspended);

  81.         tile.tileUpdateCompleted();

  82.         if (tile.getLocation(latitude, longitude) != Tile.Location.HAS_INTERPOLATION_NEIGHBORS) {
  83.             // this should happen only if user set up an inconsistent TileUpdater
  84.             throw new RuggedException(RuggedMessages.TILE_WITHOUT_REQUIRED_NEIGHBORS_SELECTED,
  85.                                       FastMath.toDegrees(latitude),
  86.                                       FastMath.toDegrees(longitude));
  87.         }

  88.         tiles[0] = tile;
  89.         return tile;

  90.     }

  91. }