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.util.FastMath;
20 import org.hipparchus.util.MathUtils;
21
22 /**
23 * To simulate DEM SRTM3 V4.0 tiles (without the real data !)
24 * The tiles are seamless = no overlapping
25 *
26 * @author Guylaine Prat
27 */
28 public class DummySRTMsimpleElevationUpdater implements TileUpdater {
29
30 /** SRTM tile size (deg) */
31 private double tileSizeDeg = 5.;
32
33 /** SRTM tile step (rad) */
34 private double stepRad;
35
36 /** SRTM tile number of rows and columns */
37 private int n;
38
39 /** Factor to change resolution above 60 degrees and below 60 degrees */
40 private int resolutionChange;
41
42 private double elevation1;
43 private double elevation2;
44
45 /**
46 * Constructor with dummy elevations to fill in the tile ...
47 * @param rowCol SRTM tile number of rows and column
48 * @param elevation1 chosen elevation1 (m)
49 * @param elevation2 chosen elevation2 (m)
50 * @param resolutionChange factor to change resolution at +/- 60 degrees
51 */
52 public DummySRTMsimpleElevationUpdater(final int rowCol, final double elevation1, final double elevation2, final int resolutionChange) {
53
54 this.n = rowCol;
55 this.stepRad = FastMath.toRadians(this.tileSizeDeg / this.n);
56 this.resolutionChange = resolutionChange;
57
58 this.elevation1 = elevation1;
59 this.elevation2 = elevation2;
60 }
61
62 /**
63 * Update the tile
64 * @param latitude latitude (rad)
65 * @param longitude longitude (rad)
66 * @param tile to be updated
67 */
68 public void updateTile(final double latitude, final double longitude, UpdatableTile tile) {
69
70 int numberOfStep;
71
72 // Change the tile step for latitude above 60 degrees and below 60 degrees
73 if (FastMath.toDegrees(latitude) > 60. || FastMath.toDegrees(latitude) < -60.) {
74 // step * resolutionChange for latitude > 60 or < -60
75 this.stepRad = FastMath.toRadians(this.tileSizeDeg*this.resolutionChange / this.n);
76 numberOfStep = this.n/this.resolutionChange;
77
78 } else { // step = tile size / n
79 this.stepRad = FastMath.toRadians(this.tileSizeDeg / this.n);
80 numberOfStep = this.n;
81 }
82
83 // Get the tile indices that contents the current latitude and longitude
84 int[] tileIndex = findIndexInTile(latitude, longitude);
85 double latIndex = tileIndex[0];
86 double lonIndex = tileIndex[1];
87
88 // Init the tile geometry with the Rugged convention:
89 // the minimum latitude and longitude correspond to the center of the most South-West cell,
90 // and the maximum latitude and longitude correspond to the center of the most North-East cell.
91 // For SRTM : origin latitude is at North of the tile (and latitude step is < 0)
92 double minLatitude = FastMath.toRadians(60. - latIndex*5.) + 0.5*stepRad;
93 double minLongitude = FastMath.toRadians(-180. + (lonIndex - 1)*5.) + 0.5*stepRad;
94
95 tile.setGeometry(minLatitude, minLongitude, stepRad, stepRad, numberOfStep, numberOfStep);
96
97 for (int i = 0; i < numberOfStep; ++i) {
98 int p = (int) FastMath.floor((FastMath.abs(minLatitude) + i * stepRad) / stepRad);
99 for (int j = 0; j < numberOfStep; ++j) {
100 int q = (int) FastMath.floor((FastMath.abs(minLongitude) + j * stepRad) / stepRad);
101 double factor = FastMath.sin(minLatitude + i*stepRad - (minLongitude + j*stepRad))*
102 FastMath.cos(minLatitude + i*stepRad + (minLongitude + j*stepRad));
103 tile.setElevation(i, j, (((p ^ q) & 0x1) == 0) ? factor*lonIndex*elevation1 + q : factor*latIndex*elevation2 + q*p);
104 }
105 }
106 }
107
108 /**
109 * Find tile indices that contain the given (latitude, longitude)
110 * @param latitude latitude (rad)
111 * @param longitude longitude (rad)
112 * @return array : [0] = latitude tile index and [1] = longitude tile index
113 */
114 private int[] findIndexInTile(final double latitude, final double longitude) {
115
116 double latDeg = FastMath.toDegrees(latitude);
117
118 // Assure that the longitude belongs to [-180, + 180]
119 double lonDeg = FastMath.toDegrees(MathUtils.normalizeAngle(longitude, 0.0));
120
121 // Compute longitude tile name with longitude value:
122 // For SRTM with 5 degrees tiles: tile longitude index 1 starts at 180 deg W; tile longitude index 72 starts at 175 deg E
123 int tileLongIndex = (int) (1 + (lonDeg + 180.)/5.);
124
125 // Compute latitude tile name with latitude value:
126 // For SRTM with 5 degrees tiles: tile latitude index 1 starts at 60 deg N; tile latitude index 23 starts at 50 deg S
127 int tileLatIndex = (int) (1 + (60. - latDeg)/5.);
128
129 return new int[] {tileLatIndex, tileLongIndex};
130 }
131
132 public double getTileStepDeg() {
133 return FastMath.toDegrees(this.stepRad);
134 }
135
136 public double getTileSizeDeg() {
137 return this.tileSizeDeg;
138 }
139 }