1 /* Copyright 2022-2025 Thales Alenia Space
2 * Licensed to CS Communication & Systèmes (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.models.earth.troposphere.iturp834;
18
19 /** Holder for one cell of grid data surrounding one point.
20 * @author Luc Maisonobe
21 * @since 13.0
22 */
23 class GridCell {
24
25 /** Latitude difference with respect to South cell edge. */
26 private final double deltaSouth;
27
28 /** Longitude difference with respect to West cell edge. */
29 private final double deltaWest;
30
31 /** Cell size in latitude. */
32 private final double sizeLat;
33
34 /** Cell size in longitude. */
35 private final double sizeLon;
36
37 /** North-West value. */
38 private final double nw;
39
40 /** South-West value. */
41 private final double sw;
42
43 /** South-East value. */
44 private final double se;
45
46 /** North-East value. */
47 private final double ne;
48
49 /**
50 * Build a grid cell from corner data.
51 *
52 * @param deltaSouth point latitude minus South cell edge latitude
53 * @param deltaWest point longitude minus West cell edge longitude
54 * @param sizeLat cell size in latitude
55 * @param sizeLon cell size in longitude
56 * @param nw North-West value
57 * @param sw South-West value
58 * @param se South-East value
59 * @param ne North-East value
60 */
61 GridCell(final double deltaSouth, final double deltaWest, final double sizeLat, final double sizeLon,
62 final double nw, final double sw, final double se, final double ne) {
63 this.deltaSouth = deltaSouth;
64 this.deltaWest = deltaWest;
65 this.sizeLat = sizeLat;
66 this.sizeLon = sizeLon;
67 this.nw = nw;
68 this.sw = sw;
69 this.se = se;
70 this.ne = ne;
71 }
72
73 /** Build a grid cell by applying a function to two existing cells.
74 * <p>
75 * The cells are expected to be consistent (i.e. same locations,
76 * same sizes), but no verification is done here. It works in
77 * the context of ITR-R P.834 because the grids have similar
78 * samplings, it would not work fro general and inconsistent grids.
79 * </p>
80 * @param function function to apply to all cells corners
81 * @param cell1 first cell
82 * @param cell2 second cell
83 */
84 GridCell(final BiFunction function,
85 final GridCell cell1, final GridCell cell2) {
86 this.deltaSouth = cell1.deltaSouth;
87 this.deltaWest = cell1.deltaWest;
88 this.sizeLat = cell1.sizeLat;
89 this.sizeLon = cell1.sizeLon;
90 this.nw = function.apply(cell1.nw, cell2.nw);
91 this.sw = function.apply(cell1.sw, cell2.sw);
92 this.se = function.apply(cell1.se, cell2.se);
93 this.ne = function.apply(cell1.ne, cell2.ne);
94 }
95
96 /** Build a grid cell by applying a function to three existing cells.
97 * <p>
98 * The cells are expected to be consistent (i.e. same locations,
99 * same sizes), but no verification is done here. It works in
100 * the context of ITR-R P.834 because the grids have similar
101 * samplings, it would not work fro general and inconsistent grids.
102 * </p>
103 * @param function function to apply to all cells corners
104 * @param cell1 first cell
105 * @param cell2 second cell
106 * @param cell3 third cell
107 */
108 GridCell(final TriFunction function,
109 final GridCell cell1, final GridCell cell2, final GridCell cell3) {
110 this.deltaSouth = cell1.deltaSouth;
111 this.deltaWest = cell1.deltaWest;
112 this.sizeLat = cell1.sizeLat;
113 this.sizeLon = cell1.sizeLon;
114 this.nw = function.apply(cell1.nw, cell2.nw, cell3.nw);
115 this.sw = function.apply(cell1.sw, cell2.sw, cell3.sw);
116 this.se = function.apply(cell1.se, cell2.se, cell3.se);
117 this.ne = function.apply(cell1.ne, cell2.ne, cell3.ne);
118 }
119
120 /** Build a grid cell by applying a function to four existing cells.
121 * <p>
122 * The cells are expected to be consistent (i.e. same locations,
123 * same sizes), but no verification is done here. It works in
124 * the context of ITR-R P.834 because the grids have similar
125 * samplings, it would not work fro general and inconsistent grids.
126 * </p>
127 * @param function function to apply to all cells corners
128 * @param cell1 first cell
129 * @param cell2 second cell
130 * @param cell3 third cell
131 * @param cell4 fourth cell
132 */
133 GridCell(final QuarticFunction function,
134 final GridCell cell1, final GridCell cell2,
135 final GridCell cell3, final GridCell cell4) {
136 this.deltaSouth = cell1.deltaSouth;
137 this.deltaWest = cell1.deltaWest;
138 this.sizeLat = cell1.sizeLat;
139 this.sizeLon = cell1.sizeLon;
140 this.nw = function.apply(cell1.nw, cell2.nw, cell3.nw, cell4.nw);
141 this.sw = function.apply(cell1.sw, cell2.sw, cell3.sw, cell4.sw);
142 this.se = function.apply(cell1.se, cell2.se, cell3.se, cell4.se);
143 this.ne = function.apply(cell1.ne, cell2.ne, cell3.ne, cell4.ne);
144 }
145
146 /** Build a grid cell by applying a function to five existing cells.
147 * <p>
148 * The cells are expected to be consistent (i.e. same locations,
149 * same sizes), but no verification is done here. It works in
150 * the context of ITR-R P.834 because the grids have similar
151 * samplings, it would not work fro general and inconsistent grids.
152 * </p>
153 * @param function function to apply to all cells corners
154 * @param cell1 first cell
155 * @param cell2 second cell
156 * @param cell3 third cell
157 * @param cell4 fourth cell
158 * @param cell5 fifth cell
159 */
160 GridCell(final QuinticFunction function,
161 final GridCell cell1, final GridCell cell2, final GridCell cell3,
162 final GridCell cell4, final GridCell cell5) {
163 this.deltaSouth = cell1.deltaSouth;
164 this.deltaWest = cell1.deltaWest;
165 this.sizeLat = cell1.sizeLat;
166 this.sizeLon = cell1.sizeLon;
167 this.nw = function.apply(cell1.nw, cell2.nw, cell3.nw, cell4.nw, cell5.nw);
168 this.sw = function.apply(cell1.sw, cell2.sw, cell3.sw, cell4.sw, cell5.sw);
169 this.se = function.apply(cell1.se, cell2.se, cell3.se, cell4.se, cell5.se);
170 this.ne = function.apply(cell1.ne, cell2.ne, cell3.ne, cell4.ne, cell5.ne);
171 }
172
173 /** Evaluate cell value at point location using bi-linear interpolation.
174 * @return cell value at point location
175 */
176 public double evaluate() {
177 final double deltaNorth = sizeLat - deltaSouth;
178 final double deltaEast = sizeLon - deltaWest;
179 return (deltaSouth * (deltaWest * ne + deltaEast * nw) +
180 deltaNorth * (deltaWest * se + deltaEast * sw)) /
181 (sizeLat * sizeLon);
182 }
183
184 /** Interface for function that can be applied to the corners of two cells. */
185 @FunctionalInterface
186 public interface BiFunction {
187 /** Apply function to similar corners coming from two cells.
188 * @param corner1 value at corner of first cell
189 * @param corner2 value at corner of second cell
190 * @return function evaluated at similar corners of two cells
191 */
192 double apply(double corner1, double corner2);
193 }
194
195 /** Interface for function that can be applied to the corners of three cells. */
196 @FunctionalInterface
197 public interface TriFunction {
198 /** Apply function to similar corners coming from three cells.
199 * @param corner1 value at corner of first cell
200 * @param corner2 value at corner of second cell
201 * @param corner3 value at corner of third cell
202 * @return function evaluated at similar corners of three cells
203 */
204 double apply(double corner1, double corner2, double corner3);
205 }
206
207 /** Interface for function that can be applied to the corners of four cells. */
208 @FunctionalInterface
209 public interface QuarticFunction {
210 /** Apply function to similar corners coming from four cells.
211 * @param corner1 value at corner of first cell
212 * @param corner2 value at corner of second cell
213 * @param corner3 value at corner of third cell
214 * @param corner4 value at corner of fourth cell
215 * @return function evaluated at similar corners of four cells
216 */
217 double apply(double corner1, double corner2, double corner3, double corner4);
218 }
219
220 /** Interface for function that can be applied to the corners of five cells. */
221 @FunctionalInterface
222 public interface QuinticFunction {
223 /** Apply function to similar corners coming from five cells.
224 * @param corner1 value at corner of first cell
225 * @param corner2 value at corner of second cell
226 * @param corner3 value at corner of third cell
227 * @param corner4 value at corner of fourth cell
228 * @param corner5 value at corner of fifth cell
229 * @return function evaluated at similar corners of five cells
230 */
231 double apply(double corner1, double corner2, double corner3, double corner4, double corner5);
232 }
233
234 }